def authenticate(self, request, username, password): # LDAP is case- and whitespace-insensitive # we do normalization to avoid duplicate django db entries # and help mockldap username = username.lower().strip() try: bound_ldapuser = get_bound_ldapuser(request=request, username=username, password=password) with bound_ldapuser as u: UserModel = get_user_model() attr_dict = {UserModel.USERNAME_FIELD: u.username} user = UserModel(**attr_dict) try: user.save() except IntegrityError: user = UserModel.objects.get(**attr_dict) return user except ldap.INVALID_CREDENTIALS: return None except ldap.STRONG_AUTH_REQUIRED: return None
def authenticate(self, request, username, password): # LDAP is case- and whitespace-insensitive # we do normalization to avoid duplicate django db entries # and help mockldap username = username.lower().strip() try: bound_ldapuser = get_bound_ldapuser( request=request, username=username, password=password) with bound_ldapuser as u: UserModel = get_user_model() attr_dict = { UserModel.USERNAME_FIELD: u.username } user = UserModel(**attr_dict) try: user.save() except IntegrityError: user = UserModel.objects.get(**attr_dict) return user except ldap.INVALID_CREDENTIALS: return None except ldap.STRONG_AUTH_REQUIRED: return None
def test_get_bound_ldapuser_bind_as_is_properly_set_from_password(self): request = set_request('/', user=vars.USER_ALICE) with get_bound_ldapuser(request, password='******') as user: # noqa db_alias = 'ldap_%s' % request.session.cache_key self.assertTrue( ldap_md5_crypt.verify( settings.DATABASES[db_alias]['PASSWORD'], ldap_users('alice')[1]['userPassword'][0]))
def contact_settings(request): """ Contact details """ with get_bound_ldapuser(request) as user_info: contact_settings = None if request.method == "POST": contact_settings = ContactSettingsForm(request.POST) if contact_settings.is_valid(): try: gpg_fingerprint = contact_settings.cleaned_data[ 'gpg_fingerprint'] im = contact_settings.cleaned_data['im'] latitude = contact_settings.cleaned_data['latitude'] location = contact_settings.cleaned_data['location'] longitude = contact_settings.cleaned_data['longitude'] phone = contact_settings.cleaned_data['phone'] website = contact_settings.cleaned_data['website'] if user_info.location != location: user_info.location = location if user_info.phone != phone: user_info.phone = phone if user_info.website != website: user_info.website.pop() user_info.website.append(website) if user_info.im != im: user_info.im.pop() user_info.im.append(im) if user_info.longitude != longitude: user_info.longitude = longitude if user_info.latitude != latitude: user_info.latitude = latitude if user_info.gpg_fingerprint != gpg_fingerprint: user_info.gpg_fingerprint.pop() user_info.gpg_fingerprint.append(gpg_fingerprint) try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: contact_settings = ContactSettingsForm() return render(request, 'settings-contact.html', { 'contact_settings': contact_settings, 'user_info': user_info, })
def test_get_bound_ldapuser_from_request(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode( secondary_password)) self.ldapobj.directory[ldap_users('alice')[0]][ 'userPassword'].append(secondary_password_crypt) request = set_request('/', user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt( secondary_password) with get_bound_ldapuser(request) as user: self.assertEqual(user.username, vars.USER_ALICE.username)
def test_get_bound_ldapuser_from_request(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt( b64encode(secondary_password)) self.ldapobj.directory[ldap_users('alice')[0]]['userPassword'].append( secondary_password_crypt) request = set_request('/', user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt( secondary_password) with get_bound_ldapuser(request) as user: self.assertEqual(user.username, vars.USER_ALICE.username)
def gentoo_dev_settings(request): """ Gentoo related information """ with get_bound_ldapuser(request) as user_info: gentoo_account_settings = None if request.method == "POST": gentoo_account_settings = GentooAccountSettingsForm(request.POST) if gentoo_account_settings.is_valid(): try: devbug = gentoo_account_settings.cleaned_data[ 'developer_bug'] gentoo_join_date = gentoo_account_settings.cleaned_data[ 'gentoo_join_date'] gentoo_mentor = gentoo_account_settings.cleaned_data[ 'mentor'] ssh_pubkey = gentoo_account_settings.cleaned_data[ 'ssh_key'] if user_info.developer_bug != devbug: user_info.developer_bug.append(devbug) if user_info.gentoo_join_date != gentoo_join_date: user_info.gentoo_join_date.append(gentoo_join_date) if user_info.mentor != gentoo_mentor: user_info.mentor.append(gentoo_mentor) if ssh_pubkey: user_info.ssh_key.append(ssh_pubkey) if user_info.is_retired or user_info.gentoo_retire_date: gentoo_retire_date = gentoo_account_settings.cleaned_data[ 'gentoo_retire_date'] if user_info.gentoo_retire_date != gentoo_retire_date: user_info.gentoo_retire_date.append( gentoo_retire_date) try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: gentoo_account_settings = GentooAccountSettingsForm() return render(request, 'settings-gentoo.html', { 'gentoo_account_settings': gentoo_account_settings, 'user_info': user_info, })
def test_get_bound_ldapuser_bind_as_is_properly_set_from_request(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode( secondary_password)) self.ldapobj.directory[ldap_users('alice')[0]][ 'userPassword'].append(secondary_password_crypt) request = set_request('/', user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt( secondary_password) with get_bound_ldapuser(request) as user: # noqa db_alias = 'ldap_%s' % request.session.cache_key self.assertEqual(settings.DATABASES[db_alias]['PASSWORD'], b64encode(secondary_password))
def test_get_bound_ldapuser_bind_as_is_properly_set_from_request(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt( b64encode(secondary_password)) self.ldapobj.directory[ldap_users('alice')[0]]['userPassword'].append( secondary_password_crypt) request = set_request('/', user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt( secondary_password) with get_bound_ldapuser(request) as user: # noqa db_alias = 'ldap_%s' % request.session.cache_key self.assertEqual(settings.DATABASES[db_alias]['PASSWORD'], b64encode(secondary_password))
def test_get_bound_ldapuser_context_manager_cleans_up_settings(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt(b64encode( secondary_password)) self.ldapobj.directory[ldap_users('alice')[0]][ 'userPassword'].append(secondary_password_crypt) request = set_request('/', user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt( secondary_password) with get_bound_ldapuser(request) as user: # noqa pass db_alias = 'ldap_%s' % request.session.cache_key self.assertNotIn('USER', settings.DATABASES.get(db_alias, {})) self.assertNotIn('PASSWORD', settings.DATABASES.get(db_alias, {}))
def test_get_bound_ldapuser_context_manager_cleans_up_settings(self): secondary_password = Random.get_random_bytes(48) secondary_password_crypt = ldap_md5_crypt.encrypt( b64encode(secondary_password)) self.ldapobj.directory[ldap_users('alice')[0]]['userPassword'].append( secondary_password_crypt) request = set_request('/', user=vars.USER_ALICE) request.session['secondary_password'] = cipher.encrypt( secondary_password) with get_bound_ldapuser(request) as user: # noqa pass db_alias = 'ldap_%s' % request.session.cache_key self.assertNotIn('USER', settings.DATABASES.get(db_alias, {})) self.assertNotIn('PASSWORD', settings.DATABASES.get(db_alias, {}))
def password_settings(request): """ Password settings """ with get_bound_ldapuser(request) as user_info: password_settings = None if request.method == "POST": password_settings = PasswordSettingsForm(request.POST) if password_settings.is_valid(): try: new_password = password_settings.cleaned_data[ 'new_password'] new_password_verify = password_settings.cleaned_data[ 'new_password_verify'] old_password = password_settings.cleaned_data[ 'old_password'] if old_password and (new_password == new_password_verify): for hash in list(user_info.password): print hash try: if ldap_md5_crypt.verify(old_password, hash): user_info.password.append( ldap_md5_crypt.encrypt( new_password_verify)) user_info.password.remove(hash) break except ValueError: # ignore unknown hashes pass try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: password_settings = PasswordSettingsForm() return render(request, 'settings-password.html', { 'password_settings': password_settings, 'user_info': user_info, })
def profile_settings(request): """ Primary account settings, """ with get_bound_ldapuser(request) as user_info: profile_settings = None if request.method == "POST": profile_settings = ProfileSettingsForm(request.POST) if profile_settings.is_valid(): try: #birthday = profile_settings.cleaned_data['birthday'] first_name = profile_settings.cleaned_data['first_name'] last_name = profile_settings.cleaned_data['last_name'] if user_info.first_name != first_name: user_info.first_name = first_name if user_info.last_name != last_name: user_info.last_name = last_name user_info.full_name = '%s %s' % (first_name, last_name) user_info.gecos = '%s %s' % (first_name, last_name) """ if user_info.birthday != birthday: user_info.birthday = birthday """ try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: profile_settings = ProfileSettingsForm() return render(request, 'settings-profile.html', { 'profile_settings': profile_settings, 'user_info': user_info, })
def email_settings(request): """ Email Settings """ with get_bound_ldapuser(request) as user_info: email_settings = None if request.method == "POST": email_settings = EmailSettingsForm(request.POST) if email_settings.is_valid(): try: email = email_settings.cleaned_data['email'] gravatar_mail = email_settings.cleaned_data['gravatar'] if request.POST.get('delete'): user_info.email.remove(email) else: user_info.email.append(email) if gravatar_mail: gravatar_hash = hashlib.md5(gravatar_mail).hexdigest() user_info.gravatar = gravatar_hash try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: email_settings = EmailSettingsForm() return render(request, 'settings-email.html', { 'email_settings': email_settings, 'user_info': user_info, })
def otp_setup(request): dev = TOTPDevice.objects.get(user=request.user) secret = None conf_form = None skeys = None if request.method == 'POST': if 'disable' in request.POST: with get_bound_ldapuser(request) as user: dev.disable(user) elif 'confirm' in request.POST and 'otp_secret' in request.session: secret = request.session['otp_secret'] conf_form = OTPForm(request.POST) try: if not conf_form.is_valid(): raise OkupyError() token = conf_form.cleaned_data['otp_token'] # prevent reusing the same token to login if not RevokedToken.add(token, request.user): raise OkupyError() if not dev.verify_token(token, secret): raise OkupyError() except OkupyError: messages.error(request, 'Token verification failed.') conf_form = OTPForm() else: with get_bound_ldapuser(request) as user: dev.enable(user, secret) secret = None conf_form = None sdev = SOTPDevice.objects.get(user=request.user) skeys = sdev.gen_keys(user) messages.info(request, 'The new secret has been set.') elif 'enable' in request.POST: secret = dev.gen_secret() request.session['otp_secret'] = secret conf_form = OTPForm() elif 'recovery' in request.POST: sdev = SOTPDevice.objects.get(user=request.user) with get_bound_ldapuser(request) as user: skeys = sdev.gen_keys(user) messages.info(request, 'Your old recovery keys have been revoked.') elif 'cancel' in request.POST: messages.info( request, 'Secret change aborted. Previous settings' 'are in effect.') if secret: # into groups of four characters secret = ' '.join([secret[i:i + 4] for i in range(0, len(secret), 4)]) if skeys: # xxx xx xxx def group_key(s): return ' '.join([s[0:3], s[3:5], s[5:8]]) skeys = list([group_key(k) for k in skeys]) return render( request, 'otp-setup.html', { 'otp_enabled': dev.is_enabled(), 'secret': secret, 'conf_form': conf_form, 'skeys': skeys, })
def gentoo_dev_settings(request): """ Gentoo related information """ with get_bound_ldapuser(request) as user_info: gentoo_account_settings = None if request.method == "POST": gentoo_account_settings = GentooAccountSettingsForm(request.POST) if gentoo_account_settings.is_valid(): try: devbug = gentoo_account_settings.cleaned_data[ 'developer_bug'] gentoo_join_date = gentoo_account_settings.cleaned_data[ 'gentoo_join_date'] gentoo_mentor = gentoo_account_settings.cleaned_data[ 'mentor'] gentoo_retire_date = gentoo_account_settings.cleaned_data[ 'gentoo_retire_date'] gentoo_mentor = gentoo_account_settings.cleaned_data[ 'mentor'] planet_feed = gentoo_account_settings.cleaned_data[ 'planet_feed'] universe_feed = gentoo_account_settings.cleaned_data[ 'universe_feed'] if request.POST.get('delete_devbug'): user_info.devbug.remove(devbug) elif devbug and (not devbug in user_info.developer_bug): user_info.developer_bug.append(devbug) if request.POST.get('delete_gjd'): user_info.gentoo_join_date.remove(gentoo_join_date) elif gentoo_join_date and (not gentoo_join_date in user_info.gentoo_join_date): user_info.gentoo_join_date.append(gentoo_join_date) if request.POST.get('delete_mentor'): user_info.mentor.remove(gentoo_mentor) elif gentoo_mentor and \ (not gentoo_mentor in user_info.mentor): user_info.mentor.append(gentoo_mentor) if user_info.gentoo_retire_date: if request.POST.get('delete_grd'): user_info.gentoo_retire_date.remove( gentoo_retire_date) elif gentoo_retire_date and ( not gentoo_retire_date in user_info.gentoo_retire_date): user_info.gentoo_retire_date.append( gentoo_retire_date) if user_info.planet_feed != planet_feed: user_info.planet_feed = planet_feed if user_info.universe_feed != universe_feed: user_info.universe_feed = universe_feed try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: gentoo_account_settings = GentooAccountSettingsForm() return render( request, 'settings-gentoo.html', { 'gentoo_account_settings': gentoo_account_settings, 'user_info': user_info, })
def contact_settings(request): """ Contact details """ with get_bound_ldapuser(request) as user_info: contact_settings = None if request.method == "POST": contact_settings = ContactSettingsForm(request.POST) if contact_settings.is_valid(): try: gpg_fingerprint = contact_settings.cleaned_data[ 'gpg_fingerprint'] im = contact_settings.cleaned_data['im'] latitude = contact_settings.cleaned_data['latitude'] location = contact_settings.cleaned_data['location'] longitude = contact_settings.cleaned_data['longitude'] phone = contact_settings.cleaned_data['phone'] website = contact_settings.cleaned_data['website'] if location and user_info.location != location: user_info.location = location if user_info.phone != phone: user_info.phone = phone if request.POST.get('delete_web'): user_info.website.remove(website) elif website and (not website in user_info.website): user_info.website.append(website) if request.POST.get('delete_im'): user_info.im.remove(im) elif im and (not im in user_info.im): user_info.im.append(im) if user_info.longitude != longitude: user_info.longitude = longitude if user_info.latitude != latitude: user_info.latitude = latitude if request.POST.get('delete_gpg'): user_info.gpg_fingerprint.remove(gpg_fingerprint) elif gpg_fingerprint and \ (not gpg_fingerprint in user_info.gpg_fingerprint): user_info.gpg_fingerprint.append(gpg_fingerprint) try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: contact_settings = ContactSettingsForm() return render(request, 'settings-contact.html', { 'contact_settings': contact_settings, 'user_info': user_info, })
def otp_setup(request): dev = TOTPDevice.objects.get(user=request.user) secret = None conf_form = None skeys = None if request.method == 'POST': if 'disable' in request.POST: with get_bound_ldapuser(request) as user: dev.disable(user) elif 'confirm' in request.POST and 'otp_secret' in request.session: secret = request.session['otp_secret'] conf_form = OTPForm(request.POST) try: if not conf_form.is_valid(): raise OkupyError() token = conf_form.cleaned_data['otp_token'] # prevent reusing the same token to login if not RevokedToken.add(token, request.user): raise OkupyError() if not dev.verify_token(token, secret): raise OkupyError() except OkupyError: messages.error(request, 'Token verification failed.') conf_form = OTPForm() else: with get_bound_ldapuser(request) as user: dev.enable(user, secret) secret = None conf_form = None sdev = SOTPDevice.objects.get(user=request.user) skeys = sdev.gen_keys(user) messages.info(request, 'The new secret has been set.') elif 'enable' in request.POST: secret = dev.gen_secret() request.session['otp_secret'] = secret conf_form = OTPForm() elif 'recovery' in request.POST: sdev = SOTPDevice.objects.get(user=request.user) with get_bound_ldapuser(request) as user: skeys = sdev.gen_keys(user) messages.info(request, 'Your old recovery keys have been revoked.') elif 'cancel' in request.POST: messages.info(request, 'Secret change aborted. Previous settings' 'are in effect.') if secret: # into groups of four characters secret = ' '.join([secret[i:i + 4] for i in range(0, len(secret), 4)]) if skeys: # xxx xx xxx def group_key(s): return ' '.join([s[0:3], s[3:5], s[5:8]]) skeys = list([group_key(k) for k in skeys]) return render(request, 'otp-setup.html', { 'otp_enabled': dev.is_enabled(), 'secret': secret, 'conf_form': conf_form, 'skeys': skeys, })
def test_get_bound_ldapuser_password_set(self): request = set_request('/', user=vars.USER_ALICE) with get_bound_ldapuser(request, password='******') as user: self.assertEqual(user.username, vars.USER_ALICE.username)
def gentoo_dev_settings(request): """ Gentoo related information """ with get_bound_ldapuser(request) as user_info: gentoo_account_settings = None if request.method == "POST": gentoo_account_settings = GentooAccountSettingsForm(request.POST) if gentoo_account_settings.is_valid(): try: devbug = gentoo_account_settings.cleaned_data[ 'developer_bug'] gentoo_join_date = gentoo_account_settings.cleaned_data[ 'gentoo_join_date'] gentoo_mentor = gentoo_account_settings.cleaned_data[ 'mentor'] gentoo_retire_date = gentoo_account_settings.cleaned_data[ 'gentoo_retire_date'] gentoo_mentor = gentoo_account_settings.cleaned_data[ 'mentor'] planet_feed = gentoo_account_settings.cleaned_data[ 'planet_feed'] universe_feed = gentoo_account_settings.cleaned_data[ 'universe_feed'] if request.POST.get('delete_devbug'): user_info.devbug.remove(devbug) elif devbug and (not devbug in user_info.developer_bug): user_info.developer_bug.append(devbug) if request.POST.get('delete_gjd'): user_info.gentoo_join_date.remove(gentoo_join_date) elif gentoo_join_date and (not gentoo_join_date in user_info.gentoo_join_date): user_info.gentoo_join_date.append(gentoo_join_date) if request.POST.get('delete_mentor'): user_info.mentor.remove(gentoo_mentor) elif gentoo_mentor and \ (not gentoo_mentor in user_info.mentor): user_info.mentor.append(gentoo_mentor) if user_info.gentoo_retire_date: if request.POST.get('delete_grd'): user_info.gentoo_retire_date.remove(gentoo_retire_date) elif gentoo_retire_date and (not gentoo_retire_date in user_info.gentoo_retire_date): user_info.gentoo_retire_date.append(gentoo_retire_date) if user_info.planet_feed != planet_feed: user_info.planet_feed = planet_feed if user_info.universe_feed != universe_feed: user_info.universe_feed = universe_feed try: user_info.save() except IntegrityError: pass except ldap.TYPE_OR_VALUE_EXISTS: pass except Exception as error: logger.critical(error, extra=log_extra_data(request)) logger_mail.exception(error) raise OkupyError("Can't contact LDAP server") else: gentoo_account_settings = GentooAccountSettingsForm() return render(request, 'settings-gentoo.html', { 'gentoo_account_settings': gentoo_account_settings, 'user_info': user_info, })
def test_get_bound_ldapuser_bind_as_is_properly_set_from_password(self): request = set_request('/', user=vars.USER_ALICE) with get_bound_ldapuser(request, password='******') as user: # noqa db_alias = 'ldap_%s' % request.session.cache_key self.assertTrue(ldap_md5_crypt.verify(settings.DATABASES[db_alias][ 'PASSWORD'], ldap_users('alice')[1]['userPassword'][0]))