/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk

« back to all changes in this revision

Viewing changes to mandos

  • Committer: Teddy Hogeborn
  • Date: 2009-04-03 03:36:08 UTC
  • Revision ID: teddy@fukt.bsnet.se-20090403033608-ftgzsnnuzo7gbvzc
* mandos (peer_certificate, fingerprint): Moved into "TCP_handler"
                                          class.
  (TCP_handler.peer_certificate, TCP_handler.fingerprint): Moved here.
  (TCP_handler.handle): Do not log conditions also sent via IPC.
  (IPv6_TCPServer.handle_ipc): Bug fix: Remove extra newline from IPC
                               command log message.  Bug fix:  Strip
                               CR and NL from IPC line.  Log
                               conditions recieved via IPC.  Log error
                               if IPC recieved about unknown client.

Show diffs side-by-side

added added

removed removed

Lines of Context:
673
673
    del _interface
674
674
 
675
675
 
676
 
def peer_certificate(session):
677
 
    "Return the peer's OpenPGP certificate as a bytestring"
678
 
    # If not an OpenPGP certificate...
679
 
    if (gnutls.library.functions
680
 
        .gnutls_certificate_type_get(session._c_object)
681
 
        != gnutls.library.constants.GNUTLS_CRT_OPENPGP):
682
 
        # ...do the normal thing
683
 
        return session.peer_certificate
684
 
    list_size = ctypes.c_uint(1)
685
 
    cert_list = (gnutls.library.functions
686
 
                 .gnutls_certificate_get_peers
687
 
                 (session._c_object, ctypes.byref(list_size)))
688
 
    if not bool(cert_list) and list_size.value != 0:
689
 
        raise gnutls.errors.GNUTLSError("error getting peer"
690
 
                                        " certificate")
691
 
    if list_size.value == 0:
692
 
        return None
693
 
    cert = cert_list[0]
694
 
    return ctypes.string_at(cert.data, cert.size)
695
 
 
696
 
 
697
 
def fingerprint(openpgp):
698
 
    "Convert an OpenPGP bytestring to a hexdigit fingerprint string"
699
 
    # New GnuTLS "datum" with the OpenPGP public key
700
 
    datum = (gnutls.library.types
701
 
             .gnutls_datum_t(ctypes.cast(ctypes.c_char_p(openpgp),
702
 
                                         ctypes.POINTER
703
 
                                         (ctypes.c_ubyte)),
704
 
                             ctypes.c_uint(len(openpgp))))
705
 
    # New empty GnuTLS certificate
706
 
    crt = gnutls.library.types.gnutls_openpgp_crt_t()
707
 
    (gnutls.library.functions
708
 
     .gnutls_openpgp_crt_init(ctypes.byref(crt)))
709
 
    # Import the OpenPGP public key into the certificate
710
 
    (gnutls.library.functions
711
 
     .gnutls_openpgp_crt_import(crt, ctypes.byref(datum),
712
 
                                gnutls.library.constants
713
 
                                .GNUTLS_OPENPGP_FMT_RAW))
714
 
    # Verify the self signature in the key
715
 
    crtverify = ctypes.c_uint()
716
 
    (gnutls.library.functions
717
 
     .gnutls_openpgp_crt_verify_self(crt, 0, ctypes.byref(crtverify)))
718
 
    if crtverify.value != 0:
719
 
        gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
720
 
        raise gnutls.errors.CertificateSecurityError("Verify failed")
721
 
    # New buffer for the fingerprint
722
 
    buf = ctypes.create_string_buffer(20)
723
 
    buf_len = ctypes.c_size_t()
724
 
    # Get the fingerprint from the certificate into the buffer
725
 
    (gnutls.library.functions
726
 
     .gnutls_openpgp_crt_get_fingerprint(crt, ctypes.byref(buf),
727
 
                                         ctypes.byref(buf_len)))
728
 
    # Deinit the certificate
729
 
    gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
730
 
    # Convert the buffer to a Python bytestring
731
 
    fpr = ctypes.string_at(buf, buf_len.value)
732
 
    # Convert the bytestring to hexadecimal notation
733
 
    hex_fpr = u''.join(u"%02X" % ord(char) for char in fpr)
734
 
    return hex_fpr
735
 
 
736
 
 
737
676
class TCP_handler(SocketServer.BaseRequestHandler, object):
738
677
    """A TCP request handler class.
739
678
    Instantiated by IPv6_TCPServer for each request to handle it.
783
722
                return
784
723
            logger.debug(u"Handshake succeeded")
785
724
            try:
786
 
                fpr = fingerprint(peer_certificate(session))
 
725
                fpr = self.fingerprint(self.peer_certificate(session))
787
726
            except (TypeError, gnutls.errors.GNUTLSError), error:
788
727
                logger.warning(u"Bad certificate: %s", error)
789
728
                session.bye()
795
734
                    client = c
796
735
                    break
797
736
            else:
798
 
                logger.warning(u"Client not found for fingerprint: %s",
799
 
                               fpr)
800
737
                ipc.write("NOTFOUND %s\n" % fpr)
801
738
                session.bye()
802
739
                return
804
741
            # possible that the client timed out while establishing
805
742
            # the GnuTLS session.
806
743
            if not client.still_valid():
807
 
                logger.warning(u"Client %(name)s is invalid",
808
 
                               vars(client))
809
744
                ipc.write("INVALID %s\n" % client.name)
810
745
                session.bye()
811
746
                return
818
753
                             - (sent_size + sent))
819
754
                sent_size += sent
820
755
            session.bye()
 
756
    
 
757
    @staticmethod
 
758
    def peer_certificate(session):
 
759
        "Return the peer's OpenPGP certificate as a bytestring"
 
760
        # If not an OpenPGP certificate...
 
761
        if (gnutls.library.functions
 
762
            .gnutls_certificate_type_get(session._c_object)
 
763
            != gnutls.library.constants.GNUTLS_CRT_OPENPGP):
 
764
            # ...do the normal thing
 
765
            return session.peer_certificate
 
766
        list_size = ctypes.c_uint(1)
 
767
        cert_list = (gnutls.library.functions
 
768
                     .gnutls_certificate_get_peers
 
769
                     (session._c_object, ctypes.byref(list_size)))
 
770
        if not bool(cert_list) and list_size.value != 0:
 
771
            raise gnutls.errors.GNUTLSError("error getting peer"
 
772
                                            " certificate")
 
773
        if list_size.value == 0:
 
774
            return None
 
775
        cert = cert_list[0]
 
776
        return ctypes.string_at(cert.data, cert.size)
 
777
    
 
778
    @staticmethod
 
779
    def fingerprint(openpgp):
 
780
        "Convert an OpenPGP bytestring to a hexdigit fingerprint"
 
781
        # New GnuTLS "datum" with the OpenPGP public key
 
782
        datum = (gnutls.library.types
 
783
                 .gnutls_datum_t(ctypes.cast(ctypes.c_char_p(openpgp),
 
784
                                             ctypes.POINTER
 
785
                                             (ctypes.c_ubyte)),
 
786
                                 ctypes.c_uint(len(openpgp))))
 
787
        # New empty GnuTLS certificate
 
788
        crt = gnutls.library.types.gnutls_openpgp_crt_t()
 
789
        (gnutls.library.functions
 
790
         .gnutls_openpgp_crt_init(ctypes.byref(crt)))
 
791
        # Import the OpenPGP public key into the certificate
 
792
        (gnutls.library.functions
 
793
         .gnutls_openpgp_crt_import(crt, ctypes.byref(datum),
 
794
                                    gnutls.library.constants
 
795
                                    .GNUTLS_OPENPGP_FMT_RAW))
 
796
        # Verify the self signature in the key
 
797
        crtverify = ctypes.c_uint()
 
798
        (gnutls.library.functions
 
799
         .gnutls_openpgp_crt_verify_self(crt, 0,
 
800
                                         ctypes.byref(crtverify)))
 
801
        if crtverify.value != 0:
 
802
            gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
 
803
            raise (gnutls.errors.CertificateSecurityError
 
804
                   ("Verify failed"))
 
805
        # New buffer for the fingerprint
 
806
        buf = ctypes.create_string_buffer(20)
 
807
        buf_len = ctypes.c_size_t()
 
808
        # Get the fingerprint from the certificate into the buffer
 
809
        (gnutls.library.functions
 
810
         .gnutls_openpgp_crt_get_fingerprint(crt, ctypes.byref(buf),
 
811
                                             ctypes.byref(buf_len)))
 
812
        # Deinit the certificate
 
813
        gnutls.library.functions.gnutls_openpgp_crt_deinit(crt)
 
814
        # Convert the buffer to a Python bytestring
 
815
        fpr = ctypes.string_at(buf, buf_len.value)
 
816
        # Convert the bytestring to hexadecimal notation
 
817
        hex_fpr = u''.join(u"%02X" % ord(char) for char in fpr)
 
818
        return hex_fpr
821
819
 
822
820
 
823
821
class ForkingMixInWithPipe(SocketServer.ForkingMixIn, object):
939
937
            # Stop calling this function
940
938
            return False
941
939
        
942
 
        logger.debug("IPC command: %r\n" % cmdline)
 
940
        logger.debug("IPC command: %r", cmdline)
943
941
        
944
942
        # Parse and act on command
945
 
        cmd, args = cmdline.split(None, 1)
 
943
        cmd, args = cmdline.rstrip("\r\n").split(None, 1)
 
944
        
946
945
        if cmd == "NOTFOUND":
 
946
            logger.warning(u"Client not found for fingerprint: %s",
 
947
                           args)
947
948
            if self.settings["use_dbus"]:
948
949
                # Emit D-Bus signal
949
950
                mandos_dbus_service.ClientNotFound(args)
950
951
        elif cmd == "INVALID":
951
 
            if self.settings["use_dbus"]:
952
 
                for client in self.clients:
953
 
                    if client.name == args:
 
952
            for client in self.clients:
 
953
                if client.name == args:
 
954
                    logger.warning(u"Client %s is invalid", args)
 
955
                    if self.settings["use_dbus"]:
954
956
                        # Emit D-Bus signal
955
957
                        client.Rejected()
956
 
                        break
 
958
                    break
 
959
            else:
 
960
                logger.error(u"Unknown client %s is invalid", args)
957
961
        elif cmd == "SENDING":
958
962
            for client in self.clients:
959
963
                if client.name == args:
 
964
                    logger.info(u"Sending secret to %s", client.name)
960
965
                    client.checked_ok()
961
966
                    if self.settings["use_dbus"]:
962
967
                        # Emit D-Bus signal
963
968
                        client.ReceivedSecret()
964
969
                    break
 
970
            else:
 
971
                logger.error(u"Sending secret to unknown client %s",
 
972
                             args)
965
973
        else:
966
974
            logger.error("Unknown IPC command: %r", cmdline)
967
975