Esempio n. 1
0
 def handle(self, packet) -> bool:
     digest = bytestostr(packet[3])
     if not digest.startswith("u2f:"):
         log("%s is not a u2f challenge", digest)
         return False
     try:
         from pyu2f import model                     #@UnresolvedImport
         from pyu2f.u2f import GetLocalU2FInterface  #@UnresolvedImport
     except ImportError as e:
         log.warn("Warning: cannot use u2f authentication handler")
         log.warn(" %s", e)
         return False
     if not is_debug_enabled("auth"):
         logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
         logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
     dev = GetLocalU2FInterface()
     APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
     key_handle = self.get_key_handle()
     if not key_handle:
         return False
     key = model.RegisteredKey(key_handle)
     #use server salt as challenge directly
     challenge = packet[1]
     log.info("activate your U2F device for authentication")
     response = dev.Authenticate(APP_ID, challenge, [key])
     sig = response.signature_data
     client_data = response.client_data
     log("process_challenge_u2f client data=%s, signature=%s", client_data, binascii.hexlify(sig))
     self.client.do_send_challenge_reply(bytes(sig), client_data.origin)
     return True
Esempio n. 2
0
 def process_challenge_u2f(self, packet):
     digest = packet[3]
     if not digest.startswith(b"u2f:"):
         authlog("%s is not a u2f challenge", digest)
         return False
     import binascii
     import logging
     if not is_debug_enabled("auth"):
         logging.getLogger("pyu2f.hardware").setLevel(logging.INFO)
         logging.getLogger("pyu2f.hidtransport").setLevel(logging.INFO)
     from pyu2f import model
     from pyu2f.u2f import GetLocalU2FInterface
     dev = GetLocalU2FInterface()
     APP_ID = os.environ.get("XPRA_U2F_APP_ID", "Xpra")
     key_handle_str = os.environ.get("XPRA_U2F_KEY_HANDLE")
     authlog("process_challenge_u2f XPRA_U2F_KEY_HANDLE=%s", key_handle_str)
     if not key_handle_str:
         #try to load the key handle from the user conf dir(s):
         from xpra.platform.paths import get_user_conf_dirs
         info = self._protocol.get_info(False)
         key_handle_filenames = []
         for hostinfo in ("-%s" % info.get("host", ""), ""):
             key_handle_filenames += [
                 os.path.join(d, "u2f-keyhandle%s.hex" % hostinfo)
                 for d in get_user_conf_dirs()
             ]
         for filename in key_handle_filenames:
             p = osexpand(filename)
             key_handle_str = load_binary_file(p)
             authlog("key_handle_str(%s)=%s", p, key_handle_str)
             if key_handle_str:
                 key_handle_str = key_handle_str.rstrip(b" \n\r")
                 break
         if not key_handle_str:
             authlog.warn("Warning: no U2F key handle found")
             return False
     authlog("process_challenge_u2f key_handle=%s", key_handle_str)
     key_handle = binascii.unhexlify(key_handle_str)
     key = model.RegisteredKey(key_handle)
     #use server salt as challenge directly
     challenge = packet[1]
     authlog.info("activate your U2F device for authentication")
     response = dev.Authenticate(APP_ID, challenge, [key])
     sig = response.signature_data
     client_data = response.client_data
     authlog("process_challenge_u2f client data=%s, signature=%s",
             client_data, binascii.hexlify(sig))
     self.do_send_challenge_reply(bytes(sig), client_data.origin)
     return True
Esempio n. 3
0
def main():
    from xpra.platform import program_context
    with program_context("U2F-Register", "Xpra U2F Registration Tool"):
        gui = not sys.stdin.isatty() or os.environ.get("MSYSCON")
        if gui:
            from xpra.gtk_common.gobject_compat import import_gtk, import_glib
            gtk = import_gtk()
            glib = import_glib()
            from xpra.gtk_common.gtk_util import MESSAGE_INFO, MESSAGE_ERROR, BUTTONS_CLOSE

            def show_dialog(mode, *msgs):
                dialog = gtk.MessageDialog(None, 0, mode, BUTTONS_CLOSE,
                                           "\n".join(msgs))
                dialog.set_title("Xpra U2F Registration Tool")
                v = dialog.run()
                dialog.destroy()
                #run the main loop long enough to destroy the dialog:
                glib.idle_add(gtk.main_quit)
                gtk.main()
                return v

            def error(*msgs):
                return show_dialog(MESSAGE_ERROR, *msgs)

            def info(*msgs):
                return show_dialog(MESSAGE_INFO, *msgs)
        else:
            print("U2F Registration Tool")

            def printmsgs(*msgs):
                for x in msgs:
                    print(x)

            error = info = printmsgs

        key_handle_filenames = [
            os.path.join(d, "u2f-keyhandle.hex") for d in get_user_conf_dirs()
        ]
        assert len(key_handle_filenames) > 0
        for filename in key_handle_filenames:
            p = osexpand(filename)
            key_handle_str = load_binary_file(p)
            if key_handle_str:
                error(
                    " found an existing key handle in file '%s':" % p,
                    #" %s" % key_handle_str,
                    " skipping U2F registration",
                    " delete this file if you want to register again")
                return 1
        public_key_filenames = []
        for d in get_user_conf_dirs():
            public_key_filenames += glob.glob(os.path.join(d, "u2f*.pub"))
        if public_key_filenames:
            info(
                " found %i existing public key%s" %
                (len(public_key_filenames, engs(public_key_filenames))),
                *((" - %s" % x) for x in public_key_filenames))

        #pick the first directory:
        conf_dir = osexpand(get_user_conf_dirs()[0])
        if not os.path.exists(conf_dir):
            os.mkdir(conf_dir)

        from pyu2f.u2f import GetLocalU2FInterface  #@UnresolvedImport
        try:
            dev = GetLocalU2FInterface()
        except Exception as e:
            error("Failed to open local U2F device:",
                  "%s" % (str(e) or type(e)))
            return 1

        info("Please activate your U2F device now to generate a new key")
        registered_keys = []
        challenge = b'01234567890123456789012345678901'  #unused
        rr = dev.Register(APP_ID, challenge, registered_keys)
        b = rr.registration_data
        assert b[0] == 5
        pubkey = bytes(b[1:66])
        khl = b[66]
        key_handle = bytes(b[67:67 + khl])

        #save to files:
        key_handle_filename = osexpand(key_handle_filenames[0])
        f = open(key_handle_filename, "wb")
        f.write(hexstr(key_handle).encode())
        f.close
        #find a filename we can use for this public key:
        i = 1
        while True:
            c = ""
            if i > 1:
                c = "-%i"
            public_key_filename = os.path.join(conf_dir, "u2f%s-pub.hex" % c)
            if not os.path.exists(public_key_filename):
                break
        f = open(public_key_filename, "wb")
        f.write(hexstr(pubkey).encode())
        f.close
        #info("key handle: %s" % csv(hex40(key_handle)),
        #     "saved to file '%s'" % key_handle_filename,
        #     "public key: %s" % csv(hex40(pubkey)),
        #     "saved to file '%s'" % public_key_filename,
        #     )
        info(
            "key handle saved to file:",
            "'%s'" % key_handle_filename,
            "public key saved to file:",
            "'%s'" % public_key_filename,
        )
        return 0