Exemple #1
0
 async def delete_user(self, username):
     await self.send_recv(CCProtocolPacker.delete_user(username))
Exemple #2
0
def new_user(username,
             totp_create=False,
             totp_secret=None,
             text_secret=None,
             ask_pass=False,
             do_delete=False,
             debug=False,
             show_qr=False,
             hotp=False,
             pick_pass=False):
    """
    Create a new user on the Coldcard for HSM policy (also delete).

    You can input a password (interactively), or one can be picked
    by the Coldcard. When possible the QR to enrol your 2FA app will
    be shown on the Coldcard screen.
    """
    from base64 import b32encode, b32decode

    username = username.encode('ascii')
    assert 1 <= len(username) <= MAX_USERNAME_LEN, "Username length wrong"

    with get_device() as dev:
        dev.check_mitm()

        if do_delete:
            dev.send_recv(CCProtocolPacker.delete_user(username))
            click.echo('Deleted, if it was there')
            return

        if ask_pass:
            assert not text_secret, "dont give and ask for password"
            text_secret = click.prompt('Password (hidden)',
                                       hide_input=True,
                                       confirmation_prompt=True)
            mode = USER_AUTH_HMAC

        if totp_secret:
            secret = b32decode(totp_secret, casefold=True)
            assert len(secret) in {10, 20}
            mode = USER_AUTH_TOTP
        elif hotp:
            mode = USER_AUTH_HOTP
            secret = b''
        elif pick_pass or text_secret:
            mode = USER_AUTH_HMAC
        else:
            # default is TOTP
            secret = b''
            mode = USER_AUTH_TOTP

        if mode == USER_AUTH_HMAC:
            # default is text passwords
            secret = dev.hash_password(
                text_secret.encode('utf8')) if text_secret else b''
            assert not show_qr, 'QR not appropriate for text passwords'

        if not secret and not show_qr:
            # ask the Coldcard to show the QR (for password or TOTP shared secret)
            mode |= USER_AUTH_SHOW_QR

        new_secret = dev.send_recv(
            CCProtocolPacker.create_user(username, mode, secret))

        if show_qr and new_secret:
            # format the URL thing ... needs a spec
            username = username.decode('ascii')
            secret = new_secret or b32encode(secret).decode('ascii')
            mode = 'hotp' if mode == USER_AUTH_HOTP else 'totp'
            click.echo(
                f'otpauth://{mode}/{username}?secret={secret}&issuer=Coldcard%20{dev.serial}'
            )
        elif not text_secret and new_secret:
            click.echo(f'New password is: {new_secret}')
        else:
            click.echo('Done')