def deselect_handler(args):
    selectors = get_server_setting(selectors_setting)
    if isinstance(selectors, str):
        selectors = [selectors]
        set_server_setting(selectors_setting, selectors)
    if selectors is None:
        selectors = []
        set_server_setting(selectors_setting, selectors)

    errors = False
    for selector in args.selector:
        try:
            selectors.remove(selector)
        except ValueError:
            sys.stderr.write(
                'Selector {} is not currently selected.\n'.format(selector))
            errors = True
    if errors:
        sys.exit(1)

    for selector in args.selector:
        log.info('Removing secret-keeping selector {}', selector)

    save_server_settings()

    set_client_setting(selectors_setting, selectors)
    save_client_settings()

    print(restart_note)
def disable_handler(args):
    if not get_server_setting('secret_keeping:enabled'):
        sys.exit('Secret-keeping is not enabled.')

    set_server_setting('secret_keeping:enabled', False)
    save_server_settings()

    set_client_setting('secret_keeping:enabled', False)
    save_client_settings()

    print(restart_note)

    log.info('Disabled secret-keeping')
def select_handler(args):
    selectors = get_server_setting(selectors_setting)
    if isinstance(selectors, str):
        selectors = [selectors]
        set_server_setting(selectors_setting, selectors)
    if selectors is None:
        selectors = []
        set_server_setting(selectors_setting, selectors)

    errors = False
    for selector in args.selector:
        if selector in selectors:
            sys.stderr.write(
                'Selector {} is already added.\n'.format(selector))
            errors = True
    if errors:
        sys.exit(1)

    if not args.force:
        db = get_db()
        for selector in args.selector:
            if not db.clients.find_one({selector: {
                    '$exists': True
            }},
                                       projection=[]):
                sys.stderr.write(
                    'Selector {} does not match anything.\n'
                    'Specify --force to save anyway.\n'.format(selector))
                errors = True
        if errors:
            sys.exit(1)

    for selector in args.selector:
        log.info('Adding secret-keeping selector {}', selector)

    selectors.extend(args.selector)
    save_server_settings()

    set_client_setting(selectors_setting, selectors)
    save_client_settings()

    print(restart_note)
def enable_handler(args):
    if get_server_setting('secret_keeping:enabled'):
        sys.exit('Secret-keeping is already enabled.')

    if get_server_setting('secret_keeping:key_id'):
        if not (args.replace or args.preserve):
            sys.exit('Must specify --replace or --preserve.')
    else:
        args.replace = True

    args.shares = args.shares or \
        get_server_setting('secret_keeping:num_shares')
    if args.shares < 2:
        sys.exit('--num-shares must be at least 2.')

    args.combine_threshold = args.combine_threshold or \
        get_server_setting('secret_keeping:combine_threshold')
    if args.combine_threshold < 2:
        sys.exit('--combine-threshold must be at least 2.')
    if args.combine_threshold > args.shares:
        sys.exit(
            '--combine-threshold must be less than {}.'.format(args.shares +
                                                               1))

    if args.replace:
        key_name = 'penguindome-secret-keeping-' + uuid.uuid4().hex
        output = gpg_command('--passphrase',
                             '',
                             '--quick-gen-key',
                             key_name,
                             with_trustdb=True,
                             quiet=False)
        match = re.search(r'key (.*) marked as ultimately trusted', output)
        key_id = match.group(1)
        match = re.search(r'/([0-9A-F]+)\.rev', output)
        key_fingerprint = match.group(1)

        split_dir = os.path.join(var_dir, key_name)
        key_file = os.path.join(split_dir, 'private_key.asc')
        os.makedirs(split_dir)
        gpg_command('--export-secret-key', '--armor', '-o', key_file, key_id)
        subprocess.check_output(('gfsplit', '-n', str(
            args.combine_threshold), '-m', str(args.shares), key_file),
                                stderr=subprocess.STDOUT)
        try:
            gpg_command('--delete-secret-keys', key_fingerprint)
        except subprocess.CalledProcessError as e:
            sys.exit('Failed to delete secret key:\n{}'.format(
                e.output.decode('utf8')))
        subprocess.check_output(('shred', '-u', key_file),
                                stderr=subprocess.STDOUT)

        with NamedTemporaryFile() as public_key_file:
            gpg_command('--export', '-o', public_key_file.name, key_id)
            set_gpg('client')
            try:
                gpg_command('--import', public_key_file.name)
            finally:
                set_gpg('server')

        set_server_setting('secret_keeping:key_name', key_name)
        set_server_setting('secret_keeping:key_id', key_id)
        set_server_setting('secret_keeping:key_fingerprint', key_fingerprint)

        set_client_setting('secret_keeping:key_id', key_id)

    set_server_setting('secret_keeping:num_shares', args.shares)
    set_server_setting('secret_keeping:combine_threshold',
                       args.combine_threshold)
    set_server_setting('secret_keeping:enabled', True)
    save_server_settings()

    set_client_setting('secret_keeping:enabled', True)
    save_client_settings()

    print(
        distribute_secrets_note.format(m=args.shares,
                                       n=args.combine_threshold,
                                       split_dir=split_dir))
    print(restart_note)

    log.info('Enabled secret-keeping')
Esempio n. 5
0
def configure_client(args):
    changed = False
    url = get_client_setting('server_url')
    if url:
        url = list(urlparse(url))
    else:
        url = ['', '', '', '', '', '']
    if ':' in url[1]:
        hostname, port = url[1].split(':')
        port = int(port)
    else:
        hostname = url[1]
        port = 443 if url[0] == 'https' else 80

    if args.hostname:
        if hostname != args.hostname:
            hostname = args.hostname
            changed = True

    if args.port:
        if port != args.port:
            port = args.port
            changed = True
        if port == 443 and args.ssl is None:
            args.ssl = True

    if args.ssl:
        if url[0] != 'https':
            url[0] = 'https'
            changed = True
    elif args.ssl is False:
        if url[0] != 'http':
            url[0] = 'http'
            changed = True

    if port == 443 and url[0] != 'https':
        print("\n"
              "WARNING: Are you sure you don't want to use SSL on port 443?\n")

    verbose_port = port or 80
    try:
        server_port_ssl = get_port_setting(
            verbose_port, 'ssl:enabled',
            bool(get_port_setting(verbose_port, 'ssl:certificate')))
    except:
        server_port_ssl = False
    if server_port_ssl and url[0] != 'https':
        print('\n'
              'WARNING: Port {} on the server is using SSL.\n'
              '         Does the client need to?\n'.format(verbose_port))
    elif not server_port_ssl and url[0] != 'http':
        print('\n'
              'WARNING: Port {} on the server is not using SSL.\n'
              '         Are you sure the client should?\n'.format(
                  verbose_port))

    if not hostname:
        sys.exit('You must specify hostname.')
    if url[0] not in ('http', 'https'):
        changed = True
        url[0] = 'https' if port == 443 else 80
    if port and ((url[0] == 'http' and port != 80) or
                 (url[0] == 'https' and port != 443)):
        loc = '{}:{}'.format(hostname, port)
        if url[1] != loc:
            changed = True
            url[1] = loc
    else:
        url[1] = hostname

    if args.ssl_ca_file is False:
        if get_client_setting('ssl:ca_path'):
            set_client_setting('ssl:ca_path', None)
            changed = True
    elif args.ssl_ca_file:
        try:
            server_port = int(args.ssl_ca_file)
        except:
            pass
        else:
            args.ssl_ca_file = get_port_setting(server_port, 'ssl:certificate')
            if not args.ssl_ca_file:
                sys.exit('Server port {} does not have an SSL certificate.'
                         .format(server_port))
        client_file = os.path.join('client', 'cacert.pem')
        if not os.path.exists(args.ssl_ca_file):
            sys.exit('The file {} does not exist.'.format(args.ssl_ca_file))
        if not (os.path.exists(client_file) and
                filecmp.cmp(args.ssl_ca_file, client_file)):
            shutil.copy(args.ssl_ca_file, client_file)
            changed = True
        if get_client_setting('ssl:ca_path') != client_file:
            set_client_setting('ssl:ca_path', client_file)
            changed = True

    url = urlunparse(url)
    url = re.sub(r'/+$', '', url)
    if changed:
        set_client_setting('server_url', url)
        save_client_settings()
        print('Updated client configuration.')
        show_configuration(args)
        print("\n"
              "WARNING: Don't forget to build a new client release.\n")
    else:
        print('Client configuration unchanged.')