Skip to content
Snippets Groups Projects
Commit 320573d2 authored by coffee's avatar coffee
Browse files

Fix indent for real this time.

parent 895fc483
No related merge requests found
......@@ -40,99 +40,99 @@ else:
#initalise ldap instace
_ldap_inst = Connection(
Server(getattr(settings, 'AUTH_LDAP_SERVER_URI')),
user = getattr(settings, 'AUTH_LDAP_BIND_DN'),
password = getattr(settings, 'AUTH_LDAP_BIND_PASSWORD'),
client_strategy='SYNC',
raise_exceptions= True,
)
Server(getattr(settings, 'AUTH_LDAP_SERVER_URI')),
user = getattr(settings, 'AUTH_LDAP_BIND_DN'),
password = getattr(settings, 'AUTH_LDAP_BIND_PASSWORD'),
client_strategy='SYNC',
raise_exceptions= True,
)
# get the ldap instance and bind if required
def get_ldap_instance():
if not _ldap_inst.bound:
try:
_ldap_inst.bind()
except LDAPInvalidCredentialsResult:
log.error("LDAP: Invalid bind credentials")
raise
return _ldap_inst
if not _ldap_inst.bound:
try:
_ldap_inst.bind()
except LDAPInvalidCredentialsResult:
log.error("LDAP: Invalid bind credentials")
raise
return _ldap_inst
def get_ldap_attrs(dn, filter, limit, attrs):
ld = get_ldap_instance()
ld.search(dn, filter, size_limit=limit, attributes=attrs)
result = ld.result
# fetch matched objects on success
if (result['result'] == RESULT_SUCCESS):
entries = ld.entries
else:
# otherwise raise an exception
raise LDAPOperationResult(
result=result['result'],
description=result['description'],
dn=result['dn'],
message=result['message'],
response_type=result['type'])
if len(entries) == 0:
raise LDAPNoSuchObjectResult()
return entries;
ld = get_ldap_instance()
ld.search(dn, filter, size_limit=limit, attributes=attrs)
result = ld.result
# fetch matched objects on success
if (result['result'] == RESULT_SUCCESS):
entries = ld.entries
else:
# otherwise raise an exception
raise LDAPOperationResult(
result=result['result'],
description=result['description'],
dn=result['dn'],
message=result['message'],
response_type=result['type'])
if len(entries) == 0:
raise LDAPNoSuchObjectResult()
return entries;
def get_user_attrs(username, attrs):
ld = get_ldap_instance()
# find the user
filter = '(cn=%s)' % username
ld = get_ldap_instance()
# find the user
filter = '(cn=%s)' % username
result = get_ldap_attrs(ldap_user_dn, filter, 1, attrs)
result = get_ldap_attrs(ldap_user_dn, filter, 1, attrs)
return result[0];
return result[0];
def get_maxuid():
ld = get_ldap_instance()
filter = "(cn=*)"
attrs = ['msSFU30MaxUidNumber']
result = get_ldap_attrs(maxuid_dn, filter, 1, attrs)
ld = get_ldap_instance()
filter = "(cn=*)"
attrs = ['msSFU30MaxUidNumber']
result = get_ldap_attrs(maxuid_dn, filter, 1, attrs)
return result[0]
return result[0]
def get_account_lock_status(username):
ld = get_ldap_instance()
try:
result = get_user_attrs(username, ['userAccountControl'])
# user does not exist
except LDAPNoSuchObjectResult:
return None
# return UAC flag 0x002 ('ACCOUNT_DISABLE')
return bool(result[1]['userAccountControl'] & 0x002)
ld = get_ldap_instance()
try:
result = get_user_attrs(username, ['userAccountControl'])
# user does not exist
except LDAPNoSuchObjectResult:
return None
# return UAC flag 0x002 ('ACCOUNT_DISABLE')
return bool(result[1]['userAccountControl'] & 0x002)
def validate_username(value : str):
# note: slug validator ensures that username only contains [a-z0-9_-]
# usernames can't begin with a numeric
if not value[0].isalpha():
raise ValidationError(_('Username must begin with a letter'))
# ensure username is lowercase
if not value.islower():
raise ValidationError(_('Username cannot contain uppercase characters'))
# check if the user exists, this test should catch *most* cases
if subprocess.call(["id", value], stderr=subprocess.DEVNULL) == 0:
raise ValidationError(_('Username already taken (passwd)'))
# usernames cannot conflict with hostnames
try:
socket.gethostbyname(value)
raise ValidationError(
_('Username already taken (CNAME)')
)
except socket.gaierror:
pass
# lookup user in ldap, required because not all users are mapped to *nix users
try:
get_user_attrs(value, None)
except LDAPNoSuchObjectResult:
pass
else:
raise ValidationError(_('Username already taken (AD)'))
# note: slug validator ensures that username only contains [a-z0-9_-]
# usernames can't begin with a numeric
if not value[0].isalpha():
raise ValidationError(_('Username must begin with a letter'))
# ensure username is lowercase
if not value.islower():
raise ValidationError(_('Username cannot contain uppercase characters'))
# check if the user exists, this test should catch *most* cases
if subprocess.call(["id", value], stderr=subprocess.DEVNULL) == 0:
raise ValidationError(_('Username already taken (passwd)'))
# usernames cannot conflict with hostnames
try:
socket.gethostbyname(value)
raise ValidationError(
_('Username already taken (CNAME)')
)
except socket.gaierror:
pass
# lookup user in ldap, required because not all users are mapped to *nix users
try:
get_user_attrs(value, None)
except LDAPNoSuchObjectResult:
pass
else:
raise ValidationError(_('Username already taken (AD)'))
# locks the specified User Account by performing the following actions:
......@@ -140,160 +140,160 @@ def validate_username(value : str):
# 2. set user shell to `/etc/locked20xx` via ldap
# 3. do `dispense user type disabled <username> <reason>`
def lock_account(username):
# TODO: error handling
ld = get_ldap_instance()
today = date.today()
try:
# fetch current uac
result = get_user_attrs(username, ['userAccountControl'])
dn = result.entry_dn
uac = result['userAccountControl'] | 0x002 # set ACCOUNTDISABLE
actions = {
"userAccountControl": [(MODIFY_REPLACE,[uac])],
"userShell": [(MODIFY_REPLACE,["/etc/locked"+str(today.year)])]
}
# write record
ld.modify(dn, actions)
except LDAPOperationResult:
raise
finally:
ld.unbind()
reason = "account locked by uccportal on %s" % str(today)
dispense.set_dispense_flag(username, 'disabled', reason)
# TODO: error handling
ld = get_ldap_instance()
today = date.today()
try:
# fetch current uac
result = get_user_attrs(username, ['userAccountControl'])
dn = result.entry_dn
uac = result['userAccountControl'] | 0x002 # set ACCOUNTDISABLE
actions = {
"userAccountControl": [(MODIFY_REPLACE,[uac])],
"userShell": [(MODIFY_REPLACE,["/etc/locked"+str(today.year)])]
}
# write record
ld.modify(dn, actions)
except LDAPOperationResult:
raise
finally:
ld.unbind()
reason = "account locked by uccportal on %s" % str(today)
dispense.set_dispense_flag(username, 'disabled', reason)
def unlock_account(username):
# TODO: error handling
ld = get_ldap_instance()
today = date.today()
try:
# fetch current uac
result = get_user_attrs(username, ['userAccountControl'])
dn = result[0]
uac = result[1]['userAccountControl'] & ~0x002 # clear ACCOUNTDISABLE
actions = {
"userAccountControl": [(MODIFY_REPLACE,[uac])],
"userShell": [(MODIFY_REPLACE,["/bin/zsh"])]
}
# write record
ld.modify(dn, actions)
except LDAPOperationResult:
raise
finally:
ld.unbind()
reason = "account unlocked by uccportal on %s" % str(today)
dispense.set_dispense_flag(username, '!disabled', reason)
# TODO: error handling
ld = get_ldap_instance()
today = date.today()
try:
# fetch current uac
result = get_user_attrs(username, ['userAccountControl'])
dn = result[0]
uac = result[1]['userAccountControl'] & ~0x002 # clear ACCOUNTDISABLE
actions = {
"userAccountControl": [(MODIFY_REPLACE,[uac])],
"userShell": [(MODIFY_REPLACE,["/bin/zsh"])]
}
# write record
ld.modify(dn, actions)
except LDAPOperationResult:
raise
finally:
ld.unbind()
reason = "account unlocked by uccportal on %s" % str(today)
dispense.set_dispense_flag(username, '!disabled', reason)
# Account creation
def create_ad_user(form_data, member):
log.info("I: creating new account for %s (%s)")
# store user details
# TODO add overides
username=form_data['username']
displayName = member.first_name + ' ' + member.last_name
dn = 'CN=' + username +','+ ldap_user_dn
# enclose password in quotes and convert to utf16 as required:
# https://msdn.microsoft.com/en-us/library/cc223248.aspx
quotedpass = '"'+ form_data['password']+'"'
utf16pass = quotedpass.encode('utf-16-le')
# generate uid
try:
result = get_maxuid()
except:
log.error("LDAP: cannot find base uid")
raise
maxuid = int(result.msSFU30MaxUidNumber.value)
# gets all uids >= maxuid
# this is done so that we don't encounter the 1000 item limit to ad queries
entries = get_ldap_attrs(ldap_user_dn,"(uidNumber>=%s)" % maxuid, 100, ['uidNumber'])
# generate a new uid
uids = []
for user in entries:
uids.append(int(user.uidNumber.value))
uids.sort()
# use max uid if it is free
if uids[0] != maxuid:
newuid = str(maxuid)
else:
prev = uids[0]
for uid in uids:
if uid - prev > 1:
newuid = uid + 1
break;
prev = uid
#increment uid
newuid = str(prev + 1)
# sanity check: make sure the uid is free
if subprocess.call(["id", newuid], stderr=subprocess.DEVNULL) == 0:
log.error("LDAP: UID Conflict UID %s already assigned" % newuid)
raise ValueError
# create the new user struct
objclass = ['top','posixAccount','person','organizationalPerson','user']
attrs = {
'cn' : username,
'sAMAccountName' : username,
'givenName' : member.first_name,
'sn': member.last_name,
'displayName': displayName,
'userAccountControl' : '512',
'unixHomeDirectory' : "/home/ucc/" + username,
'loginShell' : '/bin/zsh',
'gidNumber' : '20021',
'uidNumber' : newuid,
'gecos' : displayName,
'mail' : username + '@ucc.gu.uwa.edu.au',
'unicodePwd': utf16pass
}
# commit the new user to AD
ld = get_ldap_instance()
result = ld.add(dn, objclass, attrs)
if not result:
log.error("LDAP: user add failed")
raise LDAPOperationsErrorResult
# set maxuid
result = ld.modify(maxuid_dn, {'msSFU30MaxUidNumber': [(MODIFY_REPLACE, newuid)]})
if not result:
log.warning("LDAP: user created but msSFU30MaxUidNumber not updated")
ld.unbind();
return True;
log.info("I: creating new account for %s (%s)")
# store user details
# TODO add overides
username=form_data['username']
displayName = member.first_name + ' ' + member.last_name
dn = 'CN=' + username +','+ ldap_user_dn
# enclose password in quotes and convert to utf16 as required:
# https://msdn.microsoft.com/en-us/library/cc223248.aspx
quotedpass = '"'+ form_data['password']+'"'
utf16pass = quotedpass.encode('utf-16-le')
# generate uid
try:
result = get_maxuid()
except:
log.error("LDAP: cannot find base uid")
raise
maxuid = int(result.msSFU30MaxUidNumber.value)
# gets all uids >= maxuid
# this is done so that we don't encounter the 1000 item limit to ad queries
entries = get_ldap_attrs(ldap_user_dn,"(uidNumber>=%s)" % maxuid, 100, ['uidNumber'])
# generate a new uid
uids = []
for user in entries:
uids.append(int(user.uidNumber.value))
uids.sort()
# use max uid if it is free
if uids[0] != maxuid:
newuid = str(maxuid)
else:
prev = uids[0]
for uid in uids:
if uid - prev > 1:
newuid = uid + 1
break;
prev = uid
#increment uid
newuid = str(prev + 1)
# sanity check: make sure the uid is free
if subprocess.call(["id", newuid], stderr=subprocess.DEVNULL) == 0:
log.error("LDAP: UID Conflict UID %s already assigned" % newuid)
raise ValueError
# create the new user struct
objclass = ['top','posixAccount','person','organizationalPerson','user']
attrs = {
'cn' : username,
'sAMAccountName' : username,
'givenName' : member.first_name,
'sn': member.last_name,
'displayName': displayName,
'userAccountControl' : '512',
'unixHomeDirectory' : "/home/ucc/" + username,
'loginShell' : '/bin/zsh',
'gidNumber' : '20021',
'uidNumber' : newuid,
'gecos' : displayName,
'mail' : username + '@ucc.gu.uwa.edu.au',
'unicodePwd': utf16pass
}
# commit the new user to AD
ld = get_ldap_instance()
result = ld.add(dn, objclass, attrs)
if not result:
log.error("LDAP: user add failed")
raise LDAPOperationsErrorResult
# set maxuid
result = ld.modify(maxuid_dn, {'msSFU30MaxUidNumber': [(MODIFY_REPLACE, newuid)]})
if not result:
log.warning("LDAP: user created but msSFU30MaxUidNumber not updated")
ld.unbind();
return True;
def make_home(formdata, member):
user = member.username
mail = formdata['email_address'] if formdata['forward'] else ""
user = member.username
mail = formdata['email_address'] if formdata['forward'] else ""
result = subprocess.run(make_home_cmd + [user, mail])
if result == 0:
return True
else:
raise CalledProcessError
return True
else:
raise CalledProcessError
def subscribe_to_list(member):
# TODO: when (if) we upgrade to mailman 3 we should switch to the new
# mailman REST API.
# aweful hack
result = os.system(make_mail_cmd % (make_mail_key, member.username))
if result == 0:
return True
else:
raise CalledProcessError
result = os.system(make_mail_cmd % (make_mail_key, member.username))
if result == 0:
return True
else:
raise CalledProcessError
def set_pin(member, pin):
return
return
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment