- add propagate field
- don't propagate PMs
- filter commands sent to client via udp by nick/channel
alcuin-9995.diff alcuin-9995.tar.gz
| 1 | |
| 2 | diff --git a/Makefile b/Makefile |
| 3 | index 7ab6ef1..5b21c74 100644 |
| 4 | |
| 5 | |
| 6 | |
| 7 | rm -rf alcuin-$(VERSION) |
| 8 | |
| 9 | clean: |
| 10 | - rm -rf genesis.diff alcuin-$(VERSION).diff.escaped alcuin-$(VERSION) |
| 11 | + rm -rf alcuin-$(VERSION).diff alcuin-$(VERSION).diff.escaped alcuin-$(VERSION) |
| 12 | rm *.tar.gz |
| 13 | - rm *.diff.escaped |
| 14 | find . -name "*.swp" -delete |
| 15 | find . -name "*.pyc" -delete |
| 16 | |
| 17 | diff --git a/lib/client.py b/lib/client.py |
| 18 | index f3dc6ab..25ec4ab 100644 |
| 19 | |
| 20 | |
| 21 | |
| 22 | else: |
| 23 | self.__handle_command = self.__registration_handler |
| 24 | |
| 25 | + def is_addressed_to_me(self, message): |
| 26 | + command = self.__parse_udp_message(message) |
| 27 | + if command[0] == 'PRIVMSG': |
| 28 | + if command[1][0][0] == '#' or command[1][0] == self.nickname: |
| 29 | + return True |
| 30 | + else: |
| 31 | + return False |
| 32 | + else: |
| 33 | + return True |
| 34 | + |
| 35 | def get_prefix(self): |
| 36 | return "%s!%s@%s" % (self.nickname, self.user, self.host) |
| 37 | prefix = property(get_prefix) |
| 38 | |
| 39 | def write_queue_size(self): |
| 40 | return len(self.__writebuffer) |
| 41 | |
| 42 | + def __parse_udp_message(self, message): |
| 43 | + data = " ".join(message.split()[1:]) + "\r\n" |
| 44 | + lines = self.__linesep_regexp.split(data) |
| 45 | + lines = lines[:-1] |
| 46 | + commands = [] |
| 47 | + for line in lines: |
| 48 | + if not line: |
| 49 | + # Empty line. Ignore. |
| 50 | + continue |
| 51 | + x = line.split(" ", 1) |
| 52 | + command = x[0].upper() |
| 53 | + if len(x) == 1: |
| 54 | + arguments = [] |
| 55 | + else: |
| 56 | + if len(x[1]) > 0 and x[1][0] == ":": |
| 57 | + arguments = [x[1][1:]] |
| 58 | + else: |
| 59 | + y = string.split(x[1], " :", 1) |
| 60 | + arguments = string.split(y[0]) |
| 61 | + if len(y) == 2: |
| 62 | + arguments.append(y[1]) |
| 63 | + commands.append([command, arguments]) |
| 64 | + return commands[0] |
| 65 | + |
| 66 | def __parse_read_buffer(self): |
| 67 | lines = self.__linesep_regexp.split(self.__readbuffer) |
| 68 | self.__readbuffer = lines[-1] |
| 69 | |
| 70 | targetname = arguments[0] |
| 71 | message = arguments[1] |
| 72 | client = server.get_client(targetname) |
| 73 | + self.server.print_debug(self.server.nicknames) |
| 74 | |
| 75 | - if client: |
| 76 | - formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message) |
| 77 | - client.message(formatted_message) |
| 78 | - self.server.peer_broadcast(formatted_message) |
| 79 | - elif server.has_channel(targetname): |
| 80 | + if server.has_channel(targetname): |
| 81 | channel = server.get_channel(targetname) |
| 82 | self.message_channel( |
| 83 | channel, command, "%s :%s" % (channel.name, message)) |
| 84 | self.channel_log(channel, message) |
| 85 | else: |
| 86 | - # this isn't reliably true so let's not send the error |
| 87 | - return |
| 88 | - self.reply("401 %s %s :No such nick/channel" |
| 89 | - % (self.nickname, targetname)) |
| 90 | + formatted_message = ":%s %s %s :%s" % (self.prefix, command, targetname, message) |
| 91 | + if(client): |
| 92 | + client.message(formatted_message) |
| 93 | + self.server.peer_broadcast(formatted_message, False) |
| 94 | |
| 95 | def part_handler(): |
| 96 | if len(arguments) < 1: |
| 97 | diff --git a/lib/infosec.py b/lib/infosec.py |
| 98 | index a431c2f..b0c9c86 100644 |
| 99 | |
| 100 | |
| 101 | |
| 102 | import struct |
| 103 | import sys |
| 104 | |
| 105 | -PACKET_SIZE = 580 |
| 106 | +PACKET_SIZE = 581 |
| 107 | MAX_MESSAGE_SIZE = 512 |
| 108 | MAX_SECRET_SIZE = 24 |
| 109 | TS_ACCEPTABLE_SKEW = 60 * 15 |
| 110 | |
| 111 | def __init__(self, server=None): |
| 112 | self.server = server |
| 113 | |
| 114 | - def pack(self, peer, message, timestamp=None): |
| 115 | + def pack(self, peer, message, propagate, timestamp=None): |
| 116 | # if we are rebroadcasting we need to use the original timestamp |
| 117 | if(timestamp == None): |
| 118 | int_ts = int(time.time()) |
| 119 | |
| 120 | self.server.print_debug("added %d to recent" % int_ts) |
| 121 | |
| 122 | # build the packet and return it |
| 123 | - packet = struct.pack("!L64s512s", int_ts, digest_bytes, ciphertext_bytes) |
| 124 | + packet = struct.pack("!L64s?512s", int_ts, digest_bytes, propagate, ciphertext_bytes) |
| 125 | return packet |
| 126 | |
| 127 | def unpack(self, peer, packet): |
| 128 | try: |
| 129 | - int_ts, digest, ciphertext_bytes = struct.unpack("!L64s512s", packet) |
| 130 | + int_ts, digest, propagate, ciphertext_bytes = struct.unpack("!L64s?512s", packet) |
| 131 | except: |
| 132 | self.server.print_error("Discarding malformed packet?") |
| 133 | - return None, None |
| 134 | + return None, None, None |
| 135 | |
| 136 | # Check the timestamp and digest |
| 137 | digest_check = hashlib.sha512(peer.remote_secret + ciphertext_bytes).digest() |
| 138 | |
| 139 | if(int_ts not in self._ts_range()): |
| 140 | self.server.print_debug("rejected message with timestamp out of range") |
| 141 | - return None, None |
| 142 | + return None, None, None |
| 143 | elif(self.server.recent.has(int_ts)): |
| 144 | self.server.print_debug("rejected known message: %d" % int_ts) |
| 145 | - return None, None |
| 146 | + return None, None, None |
| 147 | elif(digest_check != digest): |
| 148 | self.server.print_debug("name: %s" % peer.name) |
| 149 | self.server.print_debug("remote_secret: %s" % peer.remote_secret) |
| 150 | self.server.print_debug("ciphertext_bytes: %s" % binascii.hexlify(ciphertext_bytes)) |
| 151 | self.server.print_debug("digest_check: %s" % binascii.hexlify(digest_check)) |
| 152 | self.server.print_debug("rejected bad digest: %s" % binascii.hexlify(digest)) |
| 153 | - return None, None |
| 154 | + return None, None, None |
| 155 | else: |
| 156 | # Return the cleartext |
| 157 | serpent = Serpent(self._pad(peer.remote_secret, MAX_SECRET_SIZE)) |
| 158 | cleartext = serpent.decrypt(ciphertext_bytes).rstrip() |
| 159 | self.server.print_debug("received, validated, and decrypted udp packet: %s" % cleartext) |
| 160 | self.server.recent.insert(int_ts) |
| 161 | - return cleartext, int_ts |
| 162 | + # self.server.print_debug("%s %d %s") % cleartext, int_ts, propagate |
| 163 | + return cleartext, int_ts, propagate |
| 164 | |
| 165 | def _pad(self, text, size): |
| 166 | return text.ljust(size) |
| 167 | diff --git a/lib/peer.py b/lib/peer.py |
| 168 | index e108328..5c25d25 100644 |
| 169 | |
| 170 | |
| 171 | |
| 172 | self.socket = socket.socket(family=socket.AF_INET, type=socket.SOCK_DGRAM) |
| 173 | self.infosec = Infosec(server) |
| 174 | |
| 175 | - def send(self, msg, timestamp=None): |
| 176 | + def send(self, msg, propagate, timestamp=None): |
| 177 | try: |
| 178 | full_message = str.encode(msg) |
| 179 | self.server.print_debug("sending message: %s" % full_message) |
| 180 | - self.socket.sendto(self.infosec.pack(self, full_message, timestamp), (self.address, self.port)) |
| 181 | + self.socket.sendto(self.infosec.pack(self, full_message, propagate, timestamp), (self.address, self.port)) |
| 182 | except Exception as ex: |
| 183 | print("Exception while attempting to encode message: %s" % ex) |
| 184 | diff --git a/lib/server.py b/lib/server.py |
| 185 | index 9e8cbe5..bdd44d5 100644 |
| 186 | |
| 187 | |
| 188 | |
| 189 | -VERSION = "9996" |
| 190 | +VERSION = "9995" |
| 191 | |
| 192 | import os |
| 193 | import select |
| 194 | |
| 195 | |
| 196 | def handle_udp_data(self, data): |
| 197 | for peer in self.peers: |
| 198 | - message, timestamp = self.infosec.unpack(peer, data) |
| 199 | + message, timestamp, propagate = self.infosec.unpack(peer, data) |
| 200 | if(message != None): |
| 201 | self.print_debug("valid message from peer: %s" % peer.name) |
| 202 | # send the message to all clients |
| 203 | for c in self.clients: |
| 204 | - self.clients[c].message(message) |
| 205 | - # send the message to all other peers |
| 206 | - self.rebroadcast(peer, message, timestamp) |
| 207 | + # self.clients[c].udp_socket_readable_notification(message) |
| 208 | + if (self.clients[c].is_addressed_to_me(message)): |
| 209 | + self.clients[c].message(message) |
| 210 | + # send the message to all other peers if it should be propagated |
| 211 | + if(propagate == True): |
| 212 | + self.rebroadcast(peer, message, timestamp) |
| 213 | else: |
| 214 | self.print_debug("Unknown peer address: %s" % peer.address) |
| 215 | |
| 216 | - def peer_broadcast(self, message): |
| 217 | + def peer_broadcast(self, message, propagate=True): |
| 218 | for peer in self.peers: |
| 219 | - peer.send(message) |
| 220 | + peer.send(message, propagate) |
| 221 | |
| 222 | def rebroadcast(self, source_peer, message, timestamp): |
| 223 | for peer in self.peers: |
| 224 |