|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
# pam.py - functions authentication, authorisation and session handling
|
|
Packit |
6bd9ab |
#
|
|
Packit |
6bd9ab |
# Copyright (C) 2010, 2011, 2012, 2013 Arthur de Jong
|
|
Packit |
6bd9ab |
#
|
|
Packit |
6bd9ab |
# This library is free software; you can redistribute it and/or
|
|
Packit |
6bd9ab |
# modify it under the terms of the GNU Lesser General Public
|
|
Packit |
6bd9ab |
# License as published by the Free Software Foundation; either
|
|
Packit |
6bd9ab |
# version 2.1 of the License, or (at your option) any later version.
|
|
Packit |
6bd9ab |
#
|
|
Packit |
6bd9ab |
# This library is distributed in the hope that it will be useful,
|
|
Packit |
6bd9ab |
# but WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
Packit |
6bd9ab |
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
Packit |
6bd9ab |
# Lesser General Public License for more details.
|
|
Packit |
6bd9ab |
#
|
|
Packit |
6bd9ab |
# You should have received a copy of the GNU Lesser General Public
|
|
Packit |
6bd9ab |
# License along with this library; if not, write to the Free Software
|
|
Packit |
6bd9ab |
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
|
|
Packit |
6bd9ab |
# 02110-1301 USA
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
import logging
|
|
Packit |
6bd9ab |
import random
|
|
Packit |
6bd9ab |
import socket
|
|
Packit |
6bd9ab |
import time
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
from ldap.controls.ppolicy import PasswordPolicyControl, PasswordPolicyError
|
|
Packit |
6bd9ab |
from ldap.filter import escape_filter_chars
|
|
Packit |
6bd9ab |
import ldap
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
import cfg
|
|
Packit |
6bd9ab |
import common
|
|
Packit |
6bd9ab |
import constants
|
|
Packit |
6bd9ab |
import passwd
|
|
Packit |
6bd9ab |
import search
|
|
Packit |
6bd9ab |
import shadow
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
random = random.SystemRandom()
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def authenticate(binddn, password):
|
|
Packit |
6bd9ab |
# open a new connection
|
|
Packit |
6bd9ab |
conn = search.Connection()
|
|
Packit |
6bd9ab |
# bind using the specified credentials
|
|
Packit |
6bd9ab |
pwctrl = PasswordPolicyControl()
|
|
Packit |
6bd9ab |
res, data, msgid, ctrls = conn.simple_bind_s(binddn, password, serverctrls=[pwctrl])
|
|
Packit |
6bd9ab |
# go over bind result server controls
|
|
Packit |
6bd9ab |
for ctrl in ctrls:
|
|
Packit |
6bd9ab |
if ctrl.controlType == PasswordPolicyControl.controlType:
|
|
Packit |
6bd9ab |
# found a password policy control
|
|
Packit |
6bd9ab |
logging.debug('PasswordPolicyControl found: error=%s (%s), timeBeforeExpiration=%s, graceAuthNsRemaining=%s',
|
|
Packit |
6bd9ab |
'None' if ctrl.error is None else PasswordPolicyError(ctrl.error).prettyPrint(),
|
|
Packit |
6bd9ab |
ctrl.error, ctrl.timeBeforeExpiration, ctrl.graceAuthNsRemaining)
|
|
Packit |
6bd9ab |
if ctrl.error == 0: # passwordExpired
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_AUTHTOK_EXPIRED, PasswordPolicyError(ctrl.error).prettyPrint()
|
|
Packit |
6bd9ab |
elif ctrl.error == 1: # accountLocked
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_ACCT_EXPIRED, PasswordPolicyError(ctrl.error).prettyPrint()
|
|
Packit |
6bd9ab |
elif ctrl.error == 2: # changeAfterReset
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password change is needed after reset'
|
|
Packit |
6bd9ab |
elif ctrl.error:
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_PERM_DENIED, PasswordPolicyError(ctrl.error).prettyPrint()
|
|
Packit |
6bd9ab |
elif ctrl.timeBeforeExpiration is not None:
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password will expire in %d seconds' % ctrl.timeBeforeExpiration
|
|
Packit |
6bd9ab |
elif ctrl.graceAuthNsRemaining is not None:
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_NEW_AUTHTOK_REQD, 'Password expired, %d grace logins left' % ctrl.graceAuthNsRemaining
|
|
Packit |
6bd9ab |
# perform search for own object (just to do any kind of search)
|
|
Packit |
6bd9ab |
results = search.LDAPSearch(conn, base=binddn, scope=ldap.SCOPE_BASE,
|
|
Packit |
6bd9ab |
filter='(objectClass=*)', attributes=['dn', ])
|
|
Packit |
6bd9ab |
for entry in results:
|
|
Packit |
6bd9ab |
if entry[0] == binddn:
|
|
Packit |
6bd9ab |
return conn, constants.NSLCD_PAM_SUCCESS, ''
|
|
Packit |
6bd9ab |
# if our DN wasn't found raise an error to signal bind failure
|
|
Packit |
6bd9ab |
raise ldap.NO_SUCH_OBJECT()
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def pwmod(conn, userdn, oldpassword, newpassword):
|
|
Packit |
6bd9ab |
# perform request without old password
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
conn.passwd_s(userdn, None, newpassword)
|
|
Packit |
6bd9ab |
except ldap.LDAPError:
|
|
Packit |
6bd9ab |
# retry with old password
|
|
Packit |
6bd9ab |
if oldpassword:
|
|
Packit |
6bd9ab |
conn.passwd_s(userdn, oldpassword, newpassword)
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
raise
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def update_lastchange(conns, userdn):
|
|
Packit |
6bd9ab |
"""Try to update the shadowLastChange attribute of the entry."""
|
|
Packit |
6bd9ab |
attribute = shadow.attmap['shadowLastChange']
|
|
Packit |
6bd9ab |
if attribute == '${shadowLastChange:--1}':
|
|
Packit |
6bd9ab |
attribute = 'shadowLastChange'
|
|
Packit |
6bd9ab |
if not attribute or '$' in attribute:
|
|
Packit |
6bd9ab |
raise ValueError('shadowLastChange has unsupported mapping')
|
|
Packit |
6bd9ab |
# build the value for the new attribute
|
|
Packit |
6bd9ab |
if attribute.lower() == 'pwdlastset':
|
|
Packit |
6bd9ab |
# for AD we use another timestamp */
|
|
Packit |
6bd9ab |
value = '%d000000000' % (time.time() / 100L + (134774L * 864L))
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
# time in days since Jan 1, 1970
|
|
Packit |
6bd9ab |
value = '%d' % (time.time() / (60 * 60 * 24))
|
|
Packit |
6bd9ab |
# perform the modification, return at first success
|
|
Packit |
6bd9ab |
for conn in conns:
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
conn.modify_s(userdn, [(ldap.MOD_REPLACE, attribute, [value])])
|
|
Packit |
6bd9ab |
return
|
|
Packit |
6bd9ab |
except ldap.LDAPError:
|
|
Packit |
6bd9ab |
pass # ignore error and try next connection
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
class PAMRequest(common.Request):
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def validate(self, parameters):
|
|
Packit |
6bd9ab |
"""This method checks the provided username for validity and fills
|
|
Packit |
6bd9ab |
in the DN if needed."""
|
|
Packit |
6bd9ab |
# check username for validity
|
|
Packit |
6bd9ab |
common.validate_name(parameters['username'])
|
|
Packit |
6bd9ab |
# look up user DN
|
|
Packit |
6bd9ab |
entry = passwd.uid2entry(self.conn, parameters['username'])
|
|
Packit |
6bd9ab |
if not entry:
|
|
Packit |
6bd9ab |
# FIXME: we should close the stream with an empty response here
|
|
Packit |
6bd9ab |
raise ValueError('%r: user not found' % parameters['username'])
|
|
Packit |
6bd9ab |
# save the DN
|
|
Packit |
6bd9ab |
parameters['userdn'] = entry[0]
|
|
Packit |
6bd9ab |
# get the "real" username
|
|
Packit |
6bd9ab |
value = passwd.attmap.get_rdn_value(entry[0], 'uid')
|
|
Packit |
6bd9ab |
if not value:
|
|
Packit |
6bd9ab |
# get the username from the uid attribute
|
|
Packit |
6bd9ab |
values = entry[1]['uid']
|
|
Packit |
6bd9ab |
if not values or not values[0]:
|
|
Packit |
6bd9ab |
logging.warning('%s: is missing a %s attribute', entry[0], passwd.attmap['uid'])
|
|
Packit |
6bd9ab |
value = values[0]
|
|
Packit |
6bd9ab |
# check the username
|
|
Packit |
6bd9ab |
if value and not common.is_valid_name(value):
|
|
Packit |
6bd9ab |
raise ValueError('%s: has invalid %s attribute', entry[0], passwd.attmap['uid'])
|
|
Packit |
6bd9ab |
# check if the username is different and update it if needed
|
|
Packit |
6bd9ab |
if value != parameters['username']:
|
|
Packit |
6bd9ab |
logging.info('username changed from %r to %r', parameters['username'], value)
|
|
Packit |
6bd9ab |
parameters['username'] = value
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
class PAMAuthenticationRequest(PAMRequest):
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
action = constants.NSLCD_ACTION_PAM_AUTHC
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def read_parameters(self, fp):
|
|
Packit |
6bd9ab |
return dict(username=fp.read_string(),
|
|
Packit |
6bd9ab |
service=fp.read_string(),
|
|
Packit |
6bd9ab |
ruser=fp.read_string(),
|
|
Packit |
6bd9ab |
rhost=fp.read_string(),
|
|
Packit |
6bd9ab |
tty=fp.read_string(),
|
|
Packit |
6bd9ab |
password=fp.read_string())
|
|
Packit |
6bd9ab |
# TODO: log call with parameters
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def write(self, username, authc=constants.NSLCD_PAM_SUCCESS,
|
|
Packit |
6bd9ab |
authz=constants.NSLCD_PAM_SUCCESS, msg=''):
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
|
|
Packit |
6bd9ab |
self.fp.write_int32(authc)
|
|
Packit |
6bd9ab |
self.fp.write_string(username)
|
|
Packit |
6bd9ab |
self.fp.write_int32(authz)
|
|
Packit |
6bd9ab |
self.fp.write_string(msg)
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_END)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def handle_request(self, parameters):
|
|
Packit |
6bd9ab |
# if the username is blank and rootpwmoddn is configured, try to
|
|
Packit |
6bd9ab |
# authenticate as administrator, otherwise validate request as usual
|
|
Packit |
6bd9ab |
if not parameters['username'] and cfg.rootpwmoddn:
|
|
Packit |
6bd9ab |
# authenticate as rootpwmoddn
|
|
Packit |
6bd9ab |
binddn = cfg.rootpwmoddn
|
|
Packit |
6bd9ab |
# if the caller is root we will allow the use of rootpwmodpw
|
|
Packit |
6bd9ab |
if not parameters['password'] and self.calleruid == 0 and cfg.rootpwmodpw:
|
|
Packit |
6bd9ab |
password = cfg.rootpwmodpw
|
|
Packit |
6bd9ab |
elif parameters['password']:
|
|
Packit |
6bd9ab |
password = parameters['password']
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
raise ValueError('password missing')
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
self.validate(parameters)
|
|
Packit |
6bd9ab |
binddn = parameters['userdn']
|
|
Packit |
6bd9ab |
password = parameters['password']
|
|
Packit |
6bd9ab |
# try authentication
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
conn, authz, msg = authenticate(binddn, password)
|
|
Packit |
6bd9ab |
except ldap.INVALID_CREDENTIALS, e:
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
msg = e[0]['desc']
|
|
Packit |
6bd9ab |
except:
|
|
Packit |
6bd9ab |
msg = str(e)
|
|
Packit |
6bd9ab |
logging.debug('bind failed: %s', msg)
|
|
Packit |
6bd9ab |
self.write(parameters['username'], authc=constants.NSLCD_PAM_AUTH_ERR, msg=msg)
|
|
Packit |
6bd9ab |
return
|
|
Packit |
6bd9ab |
if authz != constants.NSLCD_PAM_SUCCESS:
|
|
Packit |
6bd9ab |
logging.warning('%s: %s: %s', binddn, parameters['username'], msg)
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
logging.debug('bind successful')
|
|
Packit |
6bd9ab |
# FIXME: perform shadow attribute checks with check_shadow()
|
|
Packit |
6bd9ab |
self.write(parameters['username'], authz=authz, msg=msg)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
class PAMAuthorisationRequest(PAMRequest):
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
action = constants.NSLCD_ACTION_PAM_AUTHZ
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def read_parameters(self, fp):
|
|
Packit |
6bd9ab |
return dict(username=fp.read_string(),
|
|
Packit |
6bd9ab |
service=fp.read_string(),
|
|
Packit |
6bd9ab |
ruser=fp.read_string(),
|
|
Packit |
6bd9ab |
rhost=fp.read_string(),
|
|
Packit |
6bd9ab |
tty=fp.read_string())
|
|
Packit |
6bd9ab |
# TODO: log call with parameters
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def write(self, authz=constants.NSLCD_PAM_SUCCESS, msg=''):
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
|
|
Packit |
6bd9ab |
self.fp.write_int32(authz)
|
|
Packit |
6bd9ab |
self.fp.write_string(msg)
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_END)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def check_authz_search(self, parameters):
|
|
Packit |
6bd9ab |
if not cfg.pam_authz_searches:
|
|
Packit |
6bd9ab |
return
|
|
Packit |
6bd9ab |
# escape all parameters
|
|
Packit |
6bd9ab |
variables = dict((k, escape_filter_chars(v)) for k, v in parameters.items())
|
|
Packit |
6bd9ab |
variables.update(
|
|
Packit |
6bd9ab |
hostname=escape_filter_chars(socket.gethostname()),
|
|
Packit |
6bd9ab |
fqdn=escape_filter_chars(socket.getfqdn()),
|
|
Packit |
6bd9ab |
dn=variables['userdn'],
|
|
Packit |
6bd9ab |
uid=variables['username'],
|
|
Packit |
6bd9ab |
)
|
|
Packit |
6bd9ab |
# go over all authz searches
|
|
Packit |
6bd9ab |
for x in cfg.pam_authz_searches:
|
|
Packit |
6bd9ab |
filter = x.value(variables)
|
|
Packit |
6bd9ab |
logging.debug('trying pam_authz_search "%s"', filter)
|
|
Packit |
6bd9ab |
srch = search.LDAPSearch(self.conn, filter=filter, attributes=('dn', ))
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
dn, values = srch.items().next()
|
|
Packit |
6bd9ab |
except StopIteration:
|
|
Packit |
6bd9ab |
logging.error('pam_authz_search "%s" found no matches', filter)
|
|
Packit |
6bd9ab |
raise
|
|
Packit |
6bd9ab |
logging.debug('pam_authz_search found "%s"', dn)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def handle_request(self, parameters):
|
|
Packit |
6bd9ab |
# fill in any missing userdn, etc.
|
|
Packit |
6bd9ab |
self.validate(parameters)
|
|
Packit |
6bd9ab |
# check authorisation search
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
self.check_authz_search(parameters)
|
|
Packit |
6bd9ab |
except StopIteration:
|
|
Packit |
6bd9ab |
self.write(constants.NSLCD_PAM_PERM_DENIED,
|
|
Packit |
6bd9ab |
'LDAP authorisation check failed')
|
|
Packit |
6bd9ab |
return
|
|
Packit |
6bd9ab |
# all tests passed, return OK response
|
|
Packit |
6bd9ab |
self.write()
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
class PAMPasswordModificationRequest(PAMRequest):
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
action = constants.NSLCD_ACTION_PAM_PWMOD
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def read_parameters(self, fp):
|
|
Packit |
6bd9ab |
return dict(username=fp.read_string(),
|
|
Packit |
6bd9ab |
service=fp.read_string(),
|
|
Packit |
6bd9ab |
ruser=fp.read_string(),
|
|
Packit |
6bd9ab |
rhost=fp.read_string(),
|
|
Packit |
6bd9ab |
tty=fp.read_string(),
|
|
Packit |
6bd9ab |
asroot=fp.read_int32(),
|
|
Packit |
6bd9ab |
oldpassword=fp.read_string(),
|
|
Packit |
6bd9ab |
newpassword=fp.read_string())
|
|
Packit |
6bd9ab |
# TODO: log call with parameters
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def write(self, rc=constants.NSLCD_PAM_SUCCESS, msg=''):
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
|
|
Packit |
6bd9ab |
self.fp.write_int32(rc)
|
|
Packit |
6bd9ab |
self.fp.write_string(msg)
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_END)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def handle_request(self, parameters):
|
|
Packit |
6bd9ab |
# fill in any missing userdn, etc.
|
|
Packit |
6bd9ab |
self.validate(parameters)
|
|
Packit |
6bd9ab |
# check if pam_password_prohibit_message is set
|
|
Packit |
6bd9ab |
if cfg.pam_password_prohibit_message:
|
|
Packit |
6bd9ab |
self.write(constants.NSLCD_PAM_PERM_DENIED,
|
|
Packit |
6bd9ab |
cfg.pam_password_prohibit_message)
|
|
Packit |
6bd9ab |
return
|
|
Packit |
6bd9ab |
# check if the the user passed the rootpwmoddn
|
|
Packit |
6bd9ab |
if parameters['asroot']:
|
|
Packit |
6bd9ab |
binddn = cfg.rootpwmoddn
|
|
Packit |
6bd9ab |
# check if rootpwmodpw should be used
|
|
Packit |
6bd9ab |
if not parameters['oldpassword'] and self.calleruid == 0 and cfg.rootpwmodpw:
|
|
Packit |
6bd9ab |
password = cfg.rootpwmodpw
|
|
Packit |
6bd9ab |
elif parameters['oldpassword']:
|
|
Packit |
6bd9ab |
password = parameters['oldpassword']
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
raise ValueError('password missing')
|
|
Packit |
6bd9ab |
else:
|
|
Packit |
6bd9ab |
binddn = parameters['userdn']
|
|
Packit |
6bd9ab |
password = parameters['oldpassword']
|
|
Packit |
6bd9ab |
# TODO: check if shadow properties allow password change
|
|
Packit |
6bd9ab |
# perform password modification
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
conn, authz, msg = authenticate(binddn, password)
|
|
Packit |
6bd9ab |
pwmod(conn, parameters['userdn'], parameters['oldpassword'], parameters['newpassword'])
|
|
Packit |
6bd9ab |
# try to update lastchange with normal or user connection
|
|
Packit |
6bd9ab |
update_lastchange((self.conn, conn), parameters['userdn'])
|
|
Packit |
6bd9ab |
except ldap.INVALID_CREDENTIALS, e:
|
|
Packit |
6bd9ab |
try:
|
|
Packit |
6bd9ab |
msg = e[0]['desc']
|
|
Packit |
6bd9ab |
except:
|
|
Packit |
6bd9ab |
msg = str(e)
|
|
Packit |
6bd9ab |
logging.debug('pwmod failed: %s', msg)
|
|
Packit |
6bd9ab |
self.write(constants.NSLCD_PAM_PERM_DENIED, msg)
|
|
Packit |
6bd9ab |
return
|
|
Packit |
6bd9ab |
logging.debug('pwmod successful')
|
|
Packit |
6bd9ab |
self.write()
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
SESSION_ID_LENGTH = 25
|
|
Packit |
6bd9ab |
SESSION_ID_ALPHABET = (
|
|
Packit |
6bd9ab |
"ABCDEFGHIJKLMNOPQRSTUVWXYZ" +
|
|
Packit |
6bd9ab |
"abcdefghijklmnopqrstuvwxyz" +
|
|
Packit |
6bd9ab |
"01234567890"
|
|
Packit |
6bd9ab |
)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def generate_session_id():
|
|
Packit |
6bd9ab |
return ''.join(
|
|
Packit |
6bd9ab |
random.choice(SESSION_ID_ALPHABET)
|
|
Packit |
6bd9ab |
for i in range(SESSION_ID_LENGTH)
|
|
Packit |
6bd9ab |
)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
class PAMSessionOpenRequest(PAMRequest):
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
action = constants.NSLCD_ACTION_PAM_SESS_O
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def read_parameters(self, fp):
|
|
Packit |
6bd9ab |
return dict(username=fp.read_string(),
|
|
Packit |
6bd9ab |
service=fp.read_string(),
|
|
Packit |
6bd9ab |
ruser=fp.read_string(),
|
|
Packit |
6bd9ab |
rhost=fp.read_string(),
|
|
Packit |
6bd9ab |
tty=fp.read_string())
|
|
Packit |
6bd9ab |
# TODO: log call with parameters
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def write(self, sessionid):
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
|
|
Packit |
6bd9ab |
self.fp.write_string(sessionid)
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_END)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def handle_request(self, parameters):
|
|
Packit |
6bd9ab |
# generate a session id
|
|
Packit |
6bd9ab |
session_id = generate_session_id()
|
|
Packit |
6bd9ab |
self.write(session_id)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
class PAMSessionCloseRequest(PAMRequest):
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
action = constants.NSLCD_ACTION_PAM_SESS_C
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def read_parameters(self, fp):
|
|
Packit |
6bd9ab |
return dict(username=fp.read_string(),
|
|
Packit |
6bd9ab |
service=fp.read_string(),
|
|
Packit |
6bd9ab |
ruser=fp.read_string(),
|
|
Packit |
6bd9ab |
rhost=fp.read_string(),
|
|
Packit |
6bd9ab |
tty=fp.read_string(),
|
|
Packit |
6bd9ab |
session_id=fp.read_string())
|
|
Packit |
6bd9ab |
# TODO: log call with parameters
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def write(self):
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_BEGIN)
|
|
Packit |
6bd9ab |
self.fp.write_int32(constants.NSLCD_RESULT_END)
|
|
Packit |
6bd9ab |
|
|
Packit |
6bd9ab |
def handle_request(self, parameters):
|
|
Packit |
6bd9ab |
self.write()
|