diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2012-05-04 13:36:45 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2012-05-04 13:36:45 +0000 |
commit | dcb2c6be4101985dd7f9d519635227e9f81ac2a7 (patch) | |
tree | 636c6577afc2c42fb1ea3319dadd16d7436d2773 | |
parent | d02bfa44cfda8b7d5b95817305e30f77cfbee079 (diff) |
allow the pam_authz_search option to be specified multiple times
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1679 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | man/nslcd.conf.5.xml | 4 | ||||
-rw-r--r-- | nslcd/cfg.c | 15 | ||||
-rw-r--r-- | nslcd/cfg.h | 13 | ||||
-rw-r--r-- | nslcd/pam.c | 114 | ||||
-rw-r--r-- | pynslcd/cfg.py | 5 |
5 files changed, 88 insertions, 63 deletions
diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml index fef3280..1ca324e 100644 --- a/man/nslcd.conf.5.xml +++ b/man/nslcd.conf.5.xml @@ -751,8 +751,8 @@ <literallayout><literal>(&(objectClass=posixAccount)(uid=$username)(|(host=$hostname)(host=$fqdn)(host=\\*)))</literal></literallayout> </para> <para> - The default behaviour is not to do this extra search and always - grant access. + This option may be specified multiple times and all specified searches + should at least return one entry for access to be granted. </para> </listitem> </varlistentry> diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 73199bb..0811954 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -126,7 +126,8 @@ static void cfg_defaults(struct ldap_config *cfg) cfg->ldc_restart=1; cfg->ldc_pagesize=0; cfg->ldc_nss_initgroups_ignoreusers=NULL; - cfg->ldc_pam_authz_search=NULL; + for (i=0;i<NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES;i++) + cfg->ldc_pam_authz_search[i]=NULL; cfg->ldc_nss_min_uid=0; parse_validnames_statement(__FILE__,__LINE__,"", "/^[a-z0-9._@$][a-z0-9._@$ \\~-]*[a-z0-9._@$~-]$/i",cfg); @@ -782,9 +783,17 @@ static void parse_pam_authz_search_statement( const char **list; int i; check_argumentcount(filename,lnr,keyword,(line!=NULL)&&(*line!='\0')); - cfg->ldc_pam_authz_search=xstrdup(line); + /* find free spot for search filter */ + for (i=0;(i<NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES)&&(cfg->ldc_pam_authz_search[i]!=NULL);i++); + if (i>=NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES) + { + log_log(LOG_ERR,"%s:%d: maximum number of pam_authz_search options (%d) exceeded", + filename,lnr,NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES); + exit(EXIT_FAILURE); + } + cfg->ldc_pam_authz_search[i]=xstrdup(line); /* check the variables used in the expression */ - set=expr_vars(cfg->ldc_pam_authz_search,NULL); + set=expr_vars(cfg->ldc_pam_authz_search[i],NULL); list=set_tolist(set); for (i=0;list[i]!=NULL;i++) { diff --git a/nslcd/cfg.h b/nslcd/cfg.h index 45d909c..a7e08b4 100644 --- a/nslcd/cfg.h +++ b/nslcd/cfg.h @@ -5,7 +5,7 @@ Copyright (C) 1997-2005 Luke Howard Copyright (C) 2007 West Consulting - Copyright (C) 2007, 2008, 2009, 2010, 2011 Arthur de Jong + Copyright (C) 2007, 2008, 2009, 2010, 2011, 2012 Arthur de Jong This library is free software; you can redistribute it and/or modify it under the terms of the GNU Lesser General Public @@ -40,11 +40,14 @@ #define NOGID ((gid_t)-1) /* maximum number of URIs */ -#define NSS_LDAP_CONFIG_URI_MAX 31 +#define NSS_LDAP_CONFIG_URI_MAX 31 -/* maximum number of 'passwd base's */ +/* maximum number of search bases */ #define NSS_LDAP_CONFIG_MAX_BASES 7 +/* maximum number of pam_authz_search options */ +#define NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES 8 + enum ldap_ssl_options { SSL_OFF, @@ -138,8 +141,8 @@ struct ldap_config int ldc_pagesize; /* the users for which no initgroups() searches should be done */ SET *ldc_nss_initgroups_ignoreusers; - /* the search that should be performed to do autorisation checks */ - char *ldc_pam_authz_search; + /* the searches that should be performed to do autorisation checks */ + char *ldc_pam_authz_search[NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES]; /* minimum uid for users retreived from LDAP */ uid_t ldc_nss_min_uid; /* the regular expression to determine valid names */ diff --git a/nslcd/pam.c b/nslcd/pam.c index 663c9dd..15d9362 100644 --- a/nslcd/pam.c +++ b/nslcd/pam.c @@ -378,66 +378,80 @@ static int try_autzsearch(MYLDAP_SESSION *session,const char *dn, { char hostname[HOST_NAME_MAX+1]; const char *fqdn; - DICT *dict; + DICT *dict=NULL; char filter_buffer[4096]; MYLDAP_SEARCH *search; MYLDAP_ENTRY *entry; static const char *attrs[2]; int rc; const char *res; - /* check whether the search filter is configured at all */ - if (!nslcd_cfg->ldc_pam_authz_search) - return LDAP_SUCCESS; - /* build the dictionary with variables - NOTE: any variables added here also need to be added to - cfg.c:parse_pam_authz_search_statement() */ - dict=dict_new(); - autzsearch_var_add(dict,"username",username); - autzsearch_var_add(dict,"service",servicename); - autzsearch_var_add(dict,"ruser",ruser); - autzsearch_var_add(dict,"rhost",rhost); - autzsearch_var_add(dict,"tty",tty); - if (gethostname(hostname,sizeof(hostname))==0) - autzsearch_var_add(dict,"hostname",hostname); - if ((fqdn=getfqdn())!=NULL) - autzsearch_var_add(dict,"fqdn",fqdn); - autzsearch_var_add(dict,"dn",dn); - autzsearch_var_add(dict,"uid",username); - /* build the search filter */ - res=expr_parse(nslcd_cfg->ldc_pam_authz_search, - filter_buffer,sizeof(filter_buffer), - autzsearch_var_get,(void *)dict); - autzsearch_vars_free(dict); - dict_free(dict); - if (res==NULL) - { - log_log(LOG_ERR,"invalid pam_authz_search \"%s\"",nslcd_cfg->ldc_pam_authz_search); - return LDAP_LOCAL_ERROR; - } - log_log(LOG_DEBUG,"trying pam_authz_search \"%s\"",filter_buffer); - /* perform the search */ - attrs[0]="dn"; - attrs[1]=NULL; - /* FIXME: this only searches the first base */ - search=myldap_search(session,nslcd_cfg->ldc_bases[0],LDAP_SCOPE_SUBTREE, - filter_buffer,attrs,&rc); - if (search==NULL) + int i; + /* go over all pam_authz_search options */ + for (i=0;(i<NSS_LDAP_CONFIG_MAX_AUTHZ_SEARCHES)&&(nslcd_cfg->ldc_pam_authz_search[i]!=NULL);i++) { - log_log(LOG_ERR,"pam_authz_search \"%s\" failed: %s", - filter_buffer,ldap_err2string(rc)); - return rc; + if (dict==NULL) + { + /* build the dictionary with variables + NOTE: any variables added here also need to be added to + cfg.c:parse_pam_authz_search_statement() */ + dict=dict_new(); + autzsearch_var_add(dict,"username",username); + autzsearch_var_add(dict,"service",servicename); + autzsearch_var_add(dict,"ruser",ruser); + autzsearch_var_add(dict,"rhost",rhost); + autzsearch_var_add(dict,"tty",tty); + if (gethostname(hostname,sizeof(hostname))==0) + autzsearch_var_add(dict,"hostname",hostname); + if ((fqdn=getfqdn())!=NULL) + autzsearch_var_add(dict,"fqdn",fqdn); + autzsearch_var_add(dict,"dn",dn); + autzsearch_var_add(dict,"uid",username); + } + /* build the search filter */ + res=expr_parse(nslcd_cfg->ldc_pam_authz_search[i], + filter_buffer,sizeof(filter_buffer), + autzsearch_var_get,(void *)dict); + if (res==NULL) + { + autzsearch_vars_free(dict); + dict_free(dict); + log_log(LOG_ERR,"invalid pam_authz_search \"%s\"",nslcd_cfg->ldc_pam_authz_search[i]); + return LDAP_LOCAL_ERROR; + } + log_log(LOG_DEBUG,"trying pam_authz_search \"%s\"",filter_buffer); + /* perform the search */ + attrs[0]="dn"; + attrs[1]=NULL; + /* FIXME: this only searches the first base */ + search=myldap_search(session,nslcd_cfg->ldc_bases[0],LDAP_SCOPE_SUBTREE, + filter_buffer,attrs,&rc); + if (search==NULL) + { + autzsearch_vars_free(dict); + dict_free(dict); + log_log(LOG_ERR,"pam_authz_search \"%s\" failed: %s", + filter_buffer,ldap_err2string(rc)); + return rc; + } + /* try to get an entry */ + entry=myldap_get_entry(search,&rc); + if (entry==NULL) + { + autzsearch_vars_free(dict); + dict_free(dict); + log_log(LOG_ERR,"pam_authz_search \"%s\" found no matches",filter_buffer); + if (rc==LDAP_SUCCESS) + rc=LDAP_NO_SUCH_OBJECT; + return rc; + } + log_log(LOG_DEBUG,"pam_authz_search found \"%s\"",myldap_get_dn(entry)); } - /* try to get an entry */ - entry=myldap_get_entry(search,&rc); - if (entry==NULL) + /* we went over all pam_authz_search entries */ + if (dict!=NULL) { - log_log(LOG_ERR,"pam_authz_search \"%s\" found no matches",filter_buffer); - if (rc==LDAP_SUCCESS) - rc=LDAP_NO_SUCH_OBJECT; - return rc; + autzsearch_vars_free(dict); + dict_free(dict); } - log_log(LOG_DEBUG,"pam_authz_search found \"%s\"",myldap_get_dn(entry)); - /* we've found an entry so it's OK */ return LDAP_SUCCESS; } diff --git a/pynslcd/cfg.py b/pynslcd/cfg.py index 9386716..a0415e3 100644 --- a/pynslcd/cfg.py +++ b/pynslcd/cfg.py @@ -82,7 +82,7 @@ pagesize = 0 nss_initgroups_ignoreusers = set() nss_min_uid = 0 validnames = re.compile(r'^[a-z0-9._@$][a-z0-9._@$ \\~-]{0,98}[a-z0-9._@$~-]$', re.IGNORECASE) -pam_authz_search = None +pam_authz_search = [] # allowed boolean values @@ -248,9 +248,8 @@ def read(filename): # pam_authz_search <FILTER> m = re.match('pam_authz_search\s+(?P<value>\S.*)', line, re.IGNORECASE) if m: - global pam_authz_search from attmap import Expression - pam_authz_search = Expression(m.group('value')) + pam_authz_search.append(Expression(m.group('value'))) # TODO: check pam_authz_search expression to only contain username, service, ruser, rhost, tty, hostname, fqdn, dn or uid variables continue # ssl <on|off|start_tls> |