Esempio n. 1
0
def change_password_with_keytab(username,
                                password,
                                keytab,
                                principal,
                                comment=None):
    """Change a user's Kerberos password using a keytab, subject to username
    and password validation.

    :param comment: comment to include in notification email
    """
    validators.validate_username(username, check_exists=True)
    validators.validate_password(username, password)

    # try changing using kadmin pexpect
    cmd = '{kadmin_path} -K {keytab} -p {principal} cpw {username}'.format(
        kadmin_path=shlex.quote(KADMIN_PATH),
        keytab=shlex.quote(keytab),
        principal=shlex.quote(principal),
        username=shlex.quote(username))

    child = pexpect.spawn(cmd, timeout=10)

    child.expect("{}@OCF.BERKELEY.EDU's Password:"******"Verify password - {}@OCF.BERKELEY.EDU's Password:".format(username))
    child.sendline(password)

    child.expect(pexpect.EOF)

    output = child.before.decode('utf8')
    if 'kadmin' in output:
        raise ValueError('kadmin Error: {}'.format(output))

    _notify_password_change(username, comment=comment)
Esempio n. 2
0
def change_password_with_staffer(username, password, principal,
                                 admin_password):
    """Change a user's Kerberos password using kadmin and a password, subject
    to username and password validation."""
    validators.validate_username(username)
    validators.validate_password(username, password)

    # try changing using kadmin pexpect
    cmd = '{kadmin_path} -p {principal} cpw {username}'.format(
        kadmin_path=shell.escape_arg(constants.KADMIN_PATH),
        principal=shell.escape_arg(principal),
        username=shell.escape_arg(username))

    child = pexpect.spawn(cmd, timeout=10)

    child.expect("{}@OCF.BERKELEY.EDU's Password:"******"Verify password - {}@OCF.BERKELEY.EDU's Password:"******"{}@OCF.BERKELEY.EDU's Password:".format(principal))
    child.sendline(admin_password)

    child.expect(pexpect.EOF)

    output = child.before.decode('utf8')
    if 'Looping detected' in output:
        raise ValueError('Invalid admin password given.')
    elif 'kadmin' in output:
        raise ValueError('kadmin Error: {}'.format(output))

    _notify_password_change(username)
Esempio n. 3
0
def change_password_with_keytab(username, password, keytab, principal, comment=None):
    """Change a user's Kerberos password using a keytab, subject to username
    and password validation.

    :param comment: comment to include in notification email
    """
    validators.validate_username(username, check_exists=True)
    validators.validate_password(username, password)

    # try changing using kadmin pexpect
    cmd = '{kadmin_path} -K {keytab} -p {principal} cpw {username}'.format(
        kadmin_path=shell.escape_arg(constants.KADMIN_PATH),
        keytab=shell.escape_arg(keytab),
        principal=shell.escape_arg(principal),
        username=shell.escape_arg(username))

    child = pexpect.spawn(cmd, timeout=10)

    child.expect("{}@OCF.BERKELEY.EDU's Password:"******"Verify password - {}@OCF.BERKELEY.EDU's Password:"
                 .format(username))
    child.sendline(password)

    child.expect(pexpect.EOF)

    output = child.before.decode('utf8')
    if 'kadmin' in output:
        raise ValueError('kadmin Error: {}'.format(output))

    _notify_password_change(username, comment=comment)
Esempio n. 4
0
def _get_password(request, addr_name):
    # If addr_name is None, then this is a wildcard address, and those can't
    # have passwords.
    if addr_name is None:
        return REMOVE_PASSWORD

    password = request.POST.get('password')
    if password is not None:
        password = password.strip()
        if not password:
            return REMOVE_PASSWORD
        try:
            validate_password(addr_name, password, strength_check=True)
        except ValueError as ex:
            _error(request, ex.args[0])
        else:
            return crypt_password(password)
Esempio n. 5
0
def _get_password(request, addr_name):
    # If addr_name is None, then this is a wildcard address, and those can't
    # have passwords.
    if addr_name is None:
        return REMOVE_PASSWORD

    password = request.POST.get('password')
    if password is not None:
        password = password.strip()
        if not password:
            return REMOVE_PASSWORD
        try:
            validate_password(addr_name, password, strength_check=True)
        except ValueError as ex:
            _error(request, ex.args[0])
        else:
            return crypt_password(password)
Esempio n. 6
0
def password_matches(username, password):
    """Returns True if the password matches the user account given"""

    validators.validate_username(username)
    validators.validate_password(username, password, strength_check=False)

    if not validators.user_exists(username):
        raise ValueError("User doesn't exist")

    cmd = 'kinit --no-forwardable -l0 {}@OCF.BERKELEY.EDU'.format(username)
    child = pexpect.spawn(cmd, timeout=10)

    child.expect("{}@OCF.BERKELEY.EDU's Password:".format(username))
    child.sendline(password)

    child.expect(pexpect.EOF)
    child.close()

    return child.exitstatus == 0
Esempio n. 7
0
def password_matches(username, password):
    """Returns True if the password matches the user account given"""

    validators.validate_username(username)
    validators.validate_password(username, password, strength_check=False)

    if not validators.user_exists(username):
        raise ValueError("User doesn't exist")

    cmd = 'kinit --no-forwardable -l0 {}@OCF.BERKELEY.EDU'.format(username)
    child = pexpect.spawn(cmd, timeout=10)

    child.expect("{}@OCF.BERKELEY.EDU's Password:".format(username))
    child.sendline(password)

    child.expect(pexpect.EOF)
    child.close()

    return child.exitstatus == 0
Esempio n. 8
0
def change_password_with_staffer(username,
                                 password,
                                 principal,
                                 admin_password,
                                 comment=None):
    """Change a user's Kerberos password using kadmin and a password, subject
    to username and password validation.

    :param comment: comment to include in notification email
    """
    validators.validate_username(username)
    validators.validate_password(username, password)

    # try changing using kadmin pexpect
    cmd = '{kadmin_path} -p {principal} cpw {username}'.format(
        kadmin_path=shlex.quote(KADMIN_PATH),
        principal=shlex.quote(principal),
        username=shlex.quote(username))

    child = pexpect.spawn(cmd, timeout=10)

    child.expect("{}@OCF.BERKELEY.EDU's Password:"******"Verify password - {}@OCF.BERKELEY.EDU's Password:"******"{}@OCF.BERKELEY.EDU's Password:".format(principal))
    child.sendline(admin_password)

    child.expect(pexpect.EOF)

    output = child.before.decode('utf8')
    if 'Looping detected' in output:
        raise ValueError('Invalid admin password given.')
    elif 'kadmin' in output:
        raise ValueError('kadmin Error: {}'.format(output))

    _notify_password_change(username, comment=comment)
Esempio n. 9
0
 def test_success(self, password):
     validate_password('ckuehl', password)
Esempio n. 10
0
 def test_failure(self, password):
     with pytest.raises(ValueError):
         validate_password('ckuehl', password)
Esempio n. 11
0
def main():
    def pause_error_msg():
        input('Press enter to edit group information (or Ctrl-C to exit)...')

    parser = ArgumentParser(description='Create new OCF group accounts.')
    parser.add_argument('oid',
                        type=int,
                        nargs='?',
                        help='CalLink OID for the group.')
    args = parser.parse_args()

    group_name, callink_oid, email = get_group_information(args.oid)

    content = TEMPLATE.format(group_name=group_name,
                              callink_oid=callink_oid,
                              email=email)

    while True:
        content = edit_file(content)
        try:
            account = yaml.safe_load(content)
        except yaml.YAMLError as ex:
            print('Error parsing your YAML:')
            print(ex)
            pause_error_msg()
            continue

        missing_key = False
        for key in ['user_name', 'group_name', 'callink_oid', 'email']:
            if account.get(key) is None:
                print('Missing value for key: ' + key)
                missing_key = True
        if missing_key:
            pause_error_msg()
            continue

        try:
            password = prompt_for_new_password(
                validator=lambda pwd: validate_password(
                    account['user_name'], pwd), )
        except KeyboardInterrupt:
            # we want to allow cancelling during the "enter password" stage
            # without completely exiting approve
            print()
            pause_error_msg()
            continue

        request = make_account_request(account, password)

        if input('Submit request? [yN] ') not in ('y', 'Y'):
            pause_error_msg()
            continue

        tasks, celery, response = create_account(request)
        new_request = None

        if response.status == NewAccountResponse.REJECTED:
            print(
                bold(
                    red('Account requested was rejected for the following reasons:'
                        )))
            for error in response.errors:
                print(red('  - {}'.format(error)))

            pause_error_msg()
            continue
        elif response.status == NewAccountResponse.FLAGGED:
            print(
                bold(
                    yellow(
                        'Account requested was flagged for the following reasons:'
                    )))
            for error in response.errors:
                print(yellow('  - {}'.format(error)))
            print(
                bold(
                    'You can either create the account anyway, or go back and '
                    'modify the request.'))
            choice = input('Create the account anyway? [yN] ')

            if choice in ('y', 'Y'):
                new_request = request._replace(
                    handle_warnings=NewAccountRequest.WARNINGS_CREATE, )
                task = tasks.validate_then_create_account.delay(new_request)
                response = wait_for_task(celery, task)
            else:
                pause_error_msg()
                continue

        if response.status == NewAccountResponse.CREATED:
            print(bold(green('Account created!')))
            print('Your account was created successfully.')
            print('You\'ve been sent an email with more information.')
            return
        else:
            # this shouldn't be possible; we must have entered some weird state
            error_report(request, new_request, response)
            pause_error_msg()
Esempio n. 12
0
 def test_success(self, password):
     validate_password('ckuehl', password)
Esempio n. 13
0
def validate_password(username, password):
    try:
        validators.validate_password(username, password)
    except ValueError as ex:
        raise ValidationError(str(ex))
Esempio n. 14
0
def validate_password(username, password):
    try:
        validators.validate_password(username, password)
    except ValueError as ex:
        raise ValidationError(str(ex))
Esempio n. 15
0
def main():
    def pause_error_msg():
        input('Press enter to edit group information (or Ctrl-C to exit)...')

    parser = ArgumentParser(description='Create new OCF group accounts.')
    parser.add_argument('oid', type=int, nargs='?', help='CalLink OID for the group.')
    args = parser.parse_args()

    group_name, callink_oid, email = get_group_information(args.oid)

    content = TEMPLATE.format(
        group_name=group_name,
        callink_oid=callink_oid,
        email=email
    )

    while True:
        content = edit_file(content)
        try:
            account = yaml.safe_load(content)
        except yaml.YAMLError as ex:
            print('Error parsing your YAML:')
            print(ex)
            pause_error_msg()
            continue

        missing_key = False
        for key in ['user_name', 'group_name', 'callink_oid', 'email']:
            if account.get(key) is None:
                print('Missing value for key: ' + key)
                missing_key = True
        if missing_key:
            pause_error_msg()
            continue

        try:
            password = prompt_for_new_password(
                validator=lambda pwd: validate_password(
                    account['user_name'], pwd),
            )
        except KeyboardInterrupt:
            # we want to allow cancelling during the "enter password" stage
            # without completely exiting approve
            print()
            pause_error_msg()
            continue

        request = make_account_request(account, password)

        if input('Submit request? [yN] ') not in ('y', 'Y'):
            pause_error_msg()
            continue

        tasks, celery, response = create_account(request)
        new_request = None

        if response.status == NewAccountResponse.REJECTED:
            print(bold(red(
                'Account requested was rejected for the following reasons:'
            )))
            for error in response.errors:
                print(red('  - {}'.format(error)))

            pause_error_msg()
            continue
        elif response.status == NewAccountResponse.FLAGGED:
            print(bold(yellow(
                'Account requested was flagged for the following reasons:'
            )))
            for error in response.errors:
                print(yellow('  - {}'.format(error)))
            print(bold(
                'You can either create the account anyway, or go back and '
                'modify the request.'
            ))
            choice = input('Create the account anyway? [yN] ')

            if choice in ('y', 'Y'):
                new_request = request._replace(
                    handle_warnings=NewAccountRequest.WARNINGS_CREATE,
                )
                task = tasks.validate_then_create_account.delay(new_request)
                response = wait_for_task(celery, task)
            else:
                pause_error_msg()
                continue

        if response.status == NewAccountResponse.CREATED:
            print(bold(green('Account created!')))
            print('Your account was created successfully.')
            print('You\'ve been sent an email with more information.')
            return
        else:
            # this shouldn't be possible; we must have entered some weird state
            error_report(request, new_request, response)
            pause_error_msg()
Esempio n. 16
0
 def test_success(self, password):
     validate_password("ckuehl", password)
Esempio n. 17
0
 def test_failure(self, password):
     with pytest.raises(ValueError):
         validate_password("ckuehl", password)
Esempio n. 18
0
def main():
    def_group_name = ''
    def_callink_oid = ''
    def_email = ''

    parser = ArgumentParser(description='Create new OCF group accounts.')
    parser.add_argument('oid', type=int, nargs='?', help='CalLink OID for the group.')
    args = parser.parse_args()

    if args.oid:
        group = group_by_oid(args.oid)
        if not group:
            print(red('No group with OID {}').format(args.oid))
            return
        if group['accounts']:
            print(yellow(
                'Warning: there is an existing group account with OID {}: {}'.format(
                    args.oid,
                    ', '.join(group['accounts']),
                ),
            ))
            input('Press any key to continue...')
        def_group_name = group['name']
        def_callink_oid = args.oid
        def_email = group['email']

    content = TEMPLATE.format(
        group_name=def_group_name,
        callink_oid=def_callink_oid,
        email=def_email
    )

    while True:
        content = edit_file(content)
        try:
            account = yaml.safe_load(content)
        except yaml.YAMLError as ex:
            print('Error parsing your YAML:')
            print(ex)
            input('Press enter to continue...')
            continue

        missing_key = False
        for key in ['user_name', 'group_name', 'callink_oid', 'email']:
            if account.get(key) is None:
                print('Missing value for key: ' + key)
                missing_key = True
        if missing_key:
            input('Press enter to continue...')
            continue

        try:
            password = prompt_for_new_password(
                validator=lambda pwd: validate_password(
                    account['user_name'], pwd),
            )
        except KeyboardInterrupt:
            # we want to allow cancelling during the "enter password" stage
            # without completely exiting approve
            print()
            input('Press enter to start over (or ^C again to cancel)...')
            continue

        request = NewAccountRequest(
            user_name=account['user_name'],
            real_name=account['group_name'],
            is_group=True,
            calnet_uid=None,
            callink_oid=account['callink_oid'],
            email=account['email'],
            encrypted_password=encrypt_password(
                password,
                RSA.importKey(CREATE_PUBLIC_KEY),
            ),
            handle_warnings=NewAccountRequest.WARNINGS_WARN,
        )

        print()
        print(bold('Pending account request:'))
        print(dedent(
            """\
            User Name: {request.user_name}
            Group Name: {request.real_name}
            CalLink OID: {request.callink_oid}
            Email: {request.email}
            """
        ).format(request=request))

        if input('Submit request? [yN] ') != 'y':
            input('Press enter to continue.')
            continue

        conf = ConfigParser()
        conf.read('/etc/ocf-create/ocf-create.conf')

        celery = Celery(
            broker=conf.get('celery', 'broker'),
            backend=conf.get('celery', 'backend'),
        )
        tasks = get_tasks(celery)
        task = tasks.validate_then_create_account.delay(request)

        response = wait_for_task(celery, task)
        new_request = None

        if response.status == NewAccountResponse.REJECTED:
            print(bold(red(
                'Account requested was rejected for the following reasons:'
            )))
            for error in response.errors:
                print(red('  - {}'.format(error)))
            input('Press enter to start over (or ^C to cancel)...')
            continue
        elif response.status == NewAccountResponse.FLAGGED:
            print(bold(yellow(
                'Account requested was flagged for the following reasons:'
            )))
            for error in response.errors:
                print(yellow('  - {}'.format(error)))
            print(bold(
                'You can either create the account anyway, or go back and '
                'modify the request.'
            ))
            choice = input('Create the account anyway? [yN] ')

            if choice in ('y', 'Y'):
                new_request = request._replace(
                    handle_warnings=NewAccountRequest.WARNINGS_CREATE,
                )
                task = tasks.validate_then_create_account.delay(new_request)
                response = wait_for_task(celery, task)
            else:
                input('Starting over, press enter to continue...')
                continue

        if response.status == NewAccountResponse.CREATED:
            print(bold(green('Account created!')))
            print('Your account was created successfully.')
            print('You\'ve been sent an email with more information.')
            return
        else:
            # this shouldn't be possible; we must have entered some weird state
            # TODO: report via ocflib
            print(bold(red('Error: Entered unexpected state.')))
            print(red('The request we submitted was:'))
            print(red(request))
            print(red('The new request we submitted (if any) was:'))
            print(red(new_request))
            print(red('The response we received was:'))
            print(red(response))
            print(bold(red('Not really sure what to do here, sorry.')))
            input('Press enter to start over...')