Example #1
0
 def parse_encrypted(self, part_len, data):
     if part_len != len(data):
         raise ProtocolError("Enc pkt size disaggrees with header.")
     if len(data) <= 38:
         raise ProtocolError("Truncated encrypted part.")
     uname_len, data = struct.unpack("!H", data[:2])[0], data[2:]
     if len(data) <= uname_len + 36:
         raise ProtocolError("Truncated encrypted part.")
     uname, data = data[:uname_len].decode(), data[uname_len:]
     if uname not in self.auth_db:
         raise ProtocolError("Couldn't decrypt, unknown user '%s'" % uname)
     iv, data = data[:16], data[16:]
     password = self.auth_db[uname].encode()
     key = sha256(password).digest()
     pad_bytes = 16 - (len(data) % 16)
     data += b'\0' * pad_bytes
     cipher = Cipher(algorithms.AES(key), modes.OFB(iv), backend=self.crypto_backend)
     decryptor = cipher.decryptor()
     data = decryptor.update(data)
     data = data[:-pad_bytes]
     tag, data = data[:20], data[20:]
     tag2 = sha1(data).digest()
     if not self._hashes_match(tag, tag2):
         raise ProtocolError("Bad checksum on enc pkt for '%s'" % uname)
     return data
Example #2
0
 def parse_values(self, stype, data):
     types = {0: "!Q", 1: "<d", 2: "!q", 3: "!Q"}
     (nvals,) = struct.unpack("!H", data[:2])
     data = data[2:]
     if len(data) != 9 * nvals:
         raise ProtocolError("Invalid value structure length.")
     vtypes = self.types.get(stype)
     if nvals != len(vtypes):
         raise ProtocolError("Values different than types.db info.")
     for i in range(nvals):
         if six.PY3:
             vtype = data[i]
         else:
             (vtype,) = struct.unpack("B", data[i])
         if vtype != vtypes[i][1]:
             if self.counter_eq_derive and \
                (vtype, vtypes[i][1]) in ((0, 2), (2, 0)):
                 # if counter vs derive don't break, assume server is right
                 log.debug("Type mismatch (counter/derive) for %s/%s",
                           stype, vtypes[i][0])
             else:
                 raise ProtocolError("Type mismatch with types.db")
     data = data[nvals:]
     for i in range(nvals):
         vdata, data = data[:8], data[8:]
         (val,) = struct.unpack(types[vtypes[i][1]], vdata)
         yield vtypes[i][0], vtypes[i][1], val
Example #3
0
 def parse_number(self, data):
     fmt = self.NUMERIC_TYPES.get(data[0])
     if fmt is None:
         raise ProtocolError("Invalid numeric type")
     sz = struct.calcsize(fmt)
     if sz > len(data) - 1:
         raise ProtocolError("Truncated numeric value")
     (val, ) = struct.unpack(data[1:1 + sz])
     return val, data[1 + sz:]
Example #4
0
 def parse_string(self, data):
     (length, ) = struct.unpack("!H", data[:2])
     if length > len(data) - 2:
         raise ProtocolError("Truncated string value")
     if data[2 + length] != 0x00:
         raise ProtocolError("String missing null-byte terminator")
     try:
         ret = data[2:2 + length - 1].decode("utf-8")
         return ret, data[2 + length + 1:]
     except UnicodeDecodeError:
         raise ProtocolError("String is not value UTF-8")
Example #5
0
 def parse_signed(self, part_len, data):
     if part_len <= 32:
         raise ProtocolError("Truncated signed part.")
     sig, data = data[:32], data[32:]
     uname_len = part_len - 32
     uname = data[:uname_len].decode()
     if uname not in self.auth_db:
         raise ProtocolError("Signed packet, unknown user '%s'" % uname)
     password = self.auth_db[uname].encode()
     sig2 = hmac.new(password, msg=data, digestmod=sha256).digest()
     if not self._hashes_match(sig, sig2):
         raise ProtocolError("Bad signature from user '%s'" % uname)
     data = data[uname_len:]
     return data
Example #6
0
 def parse_metric(self, hostname, data):
     cmd, data = data[0], data[1:]
     mtype = cmd & 0xF0
     action = cmd & 0x0F
     if mtype not in self.METRIC_TYPES:
         raise ProtocolError("Invalid metric type")
     if action not in self.METRIC_ACTIONS:
         raise ProtocolError("Invalid metric action")
     name, data = self.parse_string(data)
     if action is MetricsDCommand.UPDATE:
         value, data = self.parse_number(data)
     else:
         value = None
     stat = names.statname(hostname, name.split("."))
     cmd = MetricsDCommand(stat, mtype, action, value)
     return cmd, data
Example #7
0
 def parse(self, data):
     if data[0] != 0xAA:
         raise ProtocolError("Invalid magic byte")
     hostname, data = self.parse_string(data)
     while len(data):
         mc, data = self.parse_metric(hostname, data)
         yield mc
Example #8
0
 def parse_data(self, data):
     types = set([
         0x0000, 0x0001, 0x0002, 0x0003, 0x0004, 0x0005, 0x0006, 0x0007,
         0x0008, 0x0009, 0x0100, 0x0101, 0x0200, 0x0210
     ])
     while len(data) > 0:
         if len(data) < 4:
             raise ProtocolError("Truncated header.")
         (part_type, part_len) = struct.unpack("!HH", data[:4])
         data = data[4:]
         if part_type not in types:
             raise ProtocolError("Invalid part type: 0x%02x" % part_type)
         part_len -= 4  # includes four header bytes we just parsed
         if len(data) < part_len:
             raise ProtocolError("Truncated value.")
         part_data, data = data[:part_len], data[part_len:]
         yield (part_type, part_data)
Example #9
0
 def parse_values(self, stype, data):
     types = {0: "!Q", 1: "<d", 2: "!q", 3: "!Q"}
     (nvals, ) = struct.unpack("!H", data[:2])
     data = data[2:]
     if len(data) != 9 * nvals:
         raise ProtocolError("Invalid value structure length.")
     vtypes = self.types.get(stype)
     if nvals != len(vtypes):
         raise ProtocolError("Values different than types.db info.")
     for i in range(nvals):
         (vtype, ) = struct.unpack("B", data[i])
         if vtype != vtypes[i][1]:
             raise ProtocolError("Type mismatch with types.db")
     data = data[nvals:]
     for i in range(nvals):
         vdata, data = data[:8], data[8:]
         (val, ) = struct.unpack(types[vtypes[i][1]], vdata)
         yield vtypes[i][0], vtypes[i][1], val
Example #10
0
 def parse(self, data):
     if len(data) < 4:
         raise ProtocolError("Truncated header.")
     part_type, part_len = struct.unpack("!HH", data[:4])
     sec_level = {0x0200: 1, 0x0210: 2}.get(part_type, 0)
     if sec_level < self.sec_level:
         raise ProtocolError("Packet has lower security level than allowed")
     if not sec_level:
         return data
     if sec_level == 1 and not self.sec_level:
         return data[part_len:]
     data = data[4:]
     part_len -= 4
     if len(data) < part_len:
         raise ProtocolError("Truncated part payload.")
     if self.cfg_mon is not None and self.cfg_mon.modified():
         log.info("Collectd authfile modified, reloading")
         self.load_auth_file()
     if sec_level == 1:
         return self.parse_signed(part_len, data)
     if sec_level == 2:
         return self.parse_encrypted(part_len, data)
Example #11
0
 def get(self, name):
     t = self.types.get(name)
     if t is None:
         raise ProtocolError("Invalid type name: %s" % name)
     return t
Example #12
0
 def _parser(sample, data):
     if len(data) != 8:
         raise ProtocolError("Invalid hires time data length.")
     (val, ) = struct.unpack("!Q", data)
     sample[name] = val * (2**-30)
Example #13
0
 def _parser(sample, data):
     if len(data) != 8:
         raise ProtocolError("Invalid time data length.")
     (val, ) = struct.unpack("!Q", data)
     sample[name] = float(val)
Example #14
0
 def _parser(sample, data):
     if data[-1] != '\0':
         raise ProtocolError("Invalid string detected.")
     sample[name] = data[:-1]