Esempio n. 1
0
def MD5(io, ip, port, md5):
    if md5:
        os = platform.system()
        if os == 'FreeBSD':
            if md5 != 'kernel':
                raise MD5Error(
                    'FreeBSD requires that you set your MD5 key via ipsec.conf.\n'
                    'Something like:\n'
                    'flush;\n'
                    'add <local ip> <peer ip> tcp 0x1000 -A tcp-md5 "password";'
                )
            try:
                TCP_MD5SIG = 0x10
                io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, 1)
            except socket.error:
                raise MD5Error(
                    'FreeBSD requires that you rebuild your kernel to enable TCP MD5 Signatures:\n'
                    'options         IPSEC\n'
                    'options         TCP_SIGNATURE\n'
                    'device          crypto\n')
        elif os == 'Linux':
            try:
                # __kernel_sockaddr_storage
                n_af = IP.toaf(ip)
                n_addr = IP.pton(ip)
                n_port = socket.htons(port)

                # pack 'x' is padding, so we want the struct
                # Do not use '!' for the pack, the network (big) endian switch in
                # struct.pack is fighting against inet_pton and htons (note the n)

                if IP.toafi(ip) == AFI.ipv4:
                    # SS_MAXSIZE is 128 but addr_family, port and ipaddr (8 bytes total) are written independently of the padding
                    SS_MAXSIZE_PADDING = 128 - calcsize('HH4s')  # 8
                    sockaddr = pack('HH4s%dx' % SS_MAXSIZE_PADDING,
                                    socket.AF_INET, n_port, n_addr)
                else:
                    SS_MAXSIZE_PADDING = 128 - calcsize('HI16sI')  # 28
                    SIN6_FLOWINFO = 0
                    SIN6_SCOPE_ID = 0
                    sockaddr = pack('HHI16sI%dx' % SS_MAXSIZE_PADDING, n_af,
                                    n_port, SIN6_FLOWINFO, n_addr,
                                    SIN6_SCOPE_ID)

                TCP_MD5SIG_MAXKEYLEN = 80
                key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5), md5)

                TCP_MD5SIG = 14
                io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key)
            except socket.error, exc:
                raise MD5Error(
                    'This linux machine does not support TCP_MD5SIG, you can not use MD5 (%s)'
                    % errstr(exc))
        else:
            raise MD5Error('ExaBGP has no MD5 support for %s' % os)
Esempio n. 2
0
def MD5(io, ip, port, md5, md5_base64):
    platform_os = platform.system()
    if platform_os == 'FreeBSD':
        if md5:
            if md5 != 'kernel':
                raise MD5Error(
                    'FreeBSD requires that you set your MD5 key via ipsec.conf.\n'
                    'Something like:\n'
                    'flush;\n'
                    'add <local ip> <peer ip> tcp 0x1000 -A tcp-md5 "password";'
                )
            try:
                TCP_MD5SIG = 0x10
                io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, 1)
            except socket.error:
                raise MD5Error(
                    'FreeBSD requires that you rebuild your kernel to enable TCP MD5 Signatures:\n'
                    'options         IPSEC\n'
                    'options         TCP_SIGNATURE\n'
                    'device          crypto\n')
    elif platform_os == 'Linux':
        try:
            md5_bytes = None
            if md5:
                if md5_base64 is True:
                    try:
                        md5_bytes = base64.b64decode(md5)
                    except TypeError:
                        raise MD5Error("Failed to decode base 64 encoded PSK")
                elif md5_base64 is None and not re.match('.*[^a-f0-9].*',
                                                         md5):  # auto
                    options = [md5 + '==', md5 + '=', md5]
                    for md5 in options:
                        try:
                            md5_bytes = base64.b64decode(md5)
                            break
                        except TypeError:
                            pass

            # __kernel_sockaddr_storage
            n_af = IP.toaf(ip)
            n_addr = IP.pton(ip)
            n_port = socket.htons(port)

            # pack 'x' is padding, so we want the struct
            # Do not use '!' for the pack, the network (big) endian switch in
            # struct.pack is fighting against inet_pton and htons (note the n)

            if IP.toafi(ip) == AFI.ipv4:
                # SS_MAXSIZE is 128 but addr_family, port and ipaddr (8 bytes total) are written independently of the padding
                SS_MAXSIZE_PADDING = 128 - calcsize('HH4s')  # 8
                sockaddr = pack('HH4s%dx' % SS_MAXSIZE_PADDING, socket.AF_INET,
                                n_port, n_addr)
            else:
                SS_MAXSIZE_PADDING = 128 - calcsize('HI16sI')  # 28
                SIN6_FLOWINFO = 0
                SIN6_SCOPE_ID = 0
                sockaddr = pack('HHI16sI%dx' % SS_MAXSIZE_PADDING, n_af,
                                n_port, SIN6_FLOWINFO, n_addr, SIN6_SCOPE_ID)

            TCP_MD5SIG_MAXKEYLEN = 80
            TCP_MD5SIG = 14

            if md5_bytes:
                key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5_bytes),
                           md5_bytes)
                io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key)
            elif md5:
                md5_bytes = bytes(md5, 'ascii')
                key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, len(md5_bytes),
                           md5_bytes)
                io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key)
            # else:
            # 	key = pack('2xH4x%ds' % TCP_MD5SIG_MAXKEYLEN, 0, b'')
            # 	io.setsockopt(socket.IPPROTO_TCP, TCP_MD5SIG, sockaddr + key)

        except socket.error as exc:
            if exc.errno != errno.ENOENT:
                raise MD5Error(
                    'This linux machine does not support TCP_MD5SIG, you can not use MD5 (%s)'
                    % errstr(exc))
    elif md5:
        raise MD5Error('ExaBGP has no MD5 support for %s' % platform_os)