#!/usr/bin/python3

# Copyright (C) 2010 Red Hat Inc.
# Author: Mike McGrath <mmcgrath@redhat.com>
# 
# This program is free software; you can redistribute it and/or modify it
# under the terms of the GNU General Public License as published by the
# Free Software Foundation; either version 2 of the License, or (at your
# option) any later version.  See http://www.gnu.org/copyleft/gpl.html for
# the full text of the license.

# ykpersonalize -ofixed=ccccccccccci -afcaa0c5bf2e83ec040e4aeb7f8565293 -ouid=1e7f1da7d6d1
from fedora.client import AccountSystem, AuthError
from getpass import getpass
import sys
import gettext
from optparse import OptionParser
import yubico

t = gettext.translation('fas', '/usr/share/locale', fallback = True)
_ = t.gettext

try:
    ykey = yubico.find_yubikey(False)
except yubico.yubikey.YubiKeyError as ex:
    print('Unable to get access to a yubikey: %s' % ex)
    sys.exit(1)

parser = OptionParser(version = "0.1")
parser.add_option('-u', '--username',
                  dest = 'username',
                  default = None,
                  metavar = 'username',
                  help = _('Fedora Account System username'))
parser.add_option('-S', '--slot',
                  dest = 'slot',
                  default = '1',
                  metavar = 'slot',
                  help = _('The Yubikey slot to be used'))
parser.add_option('-U', '--url',
                  dest = 'url',
                  default = 'https://admin.fedoraproject.org/accounts/',
                  metavar = 'url',
                  help = _('FAS URL (Default: https://admin.fedoraproject.org/accounts/'))

(opts, args) = parser.parse_args()
slot = opts.slot

if not opts.username:
    print(_('Please provide a username.'))
    parser.print_help()
    sys.exit(0)

print(_(
'''
Attention: You are about to reprogram your yubikey!  Please ensure it is
plugged in to your USB slot before continuing.  The secret key currently on
your yubikey will be destroyed as part of this operation!

'''))

print('Contacting %s' % opts.url)
password = getpass('Password for %s: ' % opts.username)

fas = AccountSystem(username=opts.username, password=password, base_url=opts.url)
try:
    new_key = fas.send_request('yubikey/genkey', auth=True)
except AuthError as e:
    print(e)
    sys.exit(1)

print("")
print(_('New key generated in FAS, attempting to burn to yubikey'))
print("")

opts = new_key['key'].split()

try:
    ykconfig = ykey.init_config()
    ykconfig.mode_yubikey_otp(f'h:{opts[1]}'.encode(), f'h:{opts[2]}'.encode())
    ykconfig.fixed_string(str(f'm:{opts[0]}'))
    ykconfig.ticket_flag('APPEND_CR', True)
    ykconfig.config_flag('STATIC_TICKET', False)
    if ykey.version_num() >= (2, 1):
        ykconfig.config_flag('STRONG_PW1', False)
        ykconfig.config_flag('STRONG_PW2', False)
        ykconfig.config_flag('MAN_UPDATE', False)
    if ykey.version_num() >= (2, 2):
        ykconfig.extended_flag('SERIAL_API_VISIBLE', True)
    ykey.write_config(ykconfig, slot=int(slot))
    print("Success!  Your Yubikey ID is %s" % opts[0])
except yubico.yubikey.YubiKeyError as ex:
    print('Yubikey error: %s' % ex)
