diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2011-03-25 13:30:46 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2011-03-25 13:30:46 +0000 |
commit | 72c4709eefbfac429eca3ed8fb66decd03ed098d (patch) | |
tree | a4fdb41fba9ba7af21955457cc6dc229b3e5e8fb | |
parent | 1fb820314c4b6f720bfca5ce5bfbc32183e3c3af (diff) |
implement a validnames option that can be used to fine-tune the test for valid user and group names using a regular expression
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1411 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | configure.ac | 2 | ||||
-rw-r--r-- | man/nslcd.conf.5.xml | 19 | ||||
-rw-r--r-- | nslcd/cfg.c | 59 | ||||
-rw-r--r-- | nslcd/cfg.h | 5 | ||||
-rw-r--r-- | nslcd/common.c | 44 | ||||
-rw-r--r-- | tests/Makefile.am | 2 | ||||
-rw-r--r-- | tests/test_common.c | 7 |
7 files changed, 95 insertions, 43 deletions
diff --git a/configure.ac b/configure.ac index ba4b3bf..b625a4c 100644 --- a/configure.ac +++ b/configure.ac @@ -549,6 +549,7 @@ then then AC_CHECK_HEADERS(gssapi/gssapi.h gssapi/gssapi_generic.h gssapi/gssapi_krb5.h gssapi.h) fi + AC_CHECK_HEADERS(regex.h) # checks for availability of system libraries for nslcd AC_SEARCH_LIBS(gethostbyname,nsl socket) @@ -563,6 +564,7 @@ then AC_CHECK_FUNCS(__nss_configure_lookup) AC_CHECK_FUNCS(getenv putenv clearenv) AC_CHECK_FUNCS(dlopen dlsym dlerror) + AC_CHECK_FUNCS(regcomp regexec regerror) # replace getopt_long() function if it is not on the system AC_REPLACE_FUNCS(getopt_long) diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml index 29ecd23..45d48bc 100644 --- a/man/nslcd.conf.5.xml +++ b/man/nslcd.conf.5.xml @@ -671,6 +671,25 @@ </listitem> </varlistentry> + <varlistentry id="validnames"> + <term><option>validnames</option> <replaceable>REGEX</replaceable></term> + <listitem> + <para> + This option can be used to specify how user and group names are + verified within the system. This pattern is used to check all user and + group names that are requested and returned from <acronym>LDAP</acronym>. + </para> + <para> + The regular expression should be specified as a POSIX extended regular + expression. The expression itself needs to be separated by slash (/) + characters and the 'i' flag may be appended at the end to indicate + that the match should be case-insensetive. + The default value is + <literal>/^[a-z0-9._@$][a-z0-9._@$ \\~-]+[a-z0-9._@$~-]$/i</literal> + </para> + </listitem> + </varlistentry> + <varlistentry id="pam_authz_search"> <term><option>pam_authz_search</option> <replaceable>FILTER</replaceable></term> diff --git a/nslcd/cfg.c b/nslcd/cfg.c index 1b286b7..1191f77 100644 --- a/nslcd/cfg.c +++ b/nslcd/cfg.c @@ -5,7 +5,7 @@ Copyright (C) 1997-2005 Luke Howard Copyright (C) 2007 West Consulting - Copyright (C) 2007, 2008, 2009, 2010 Arthur de Jong + Copyright (C) 2007, 2008, 2009, 2010, 2011 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 @@ -75,6 +75,11 @@ struct ldap_config *nslcd_cfg=NULL; exit(EXIT_FAILURE); \ } +/* prototype for parse_validnames_statement() because it is used in + cfg_defaults() */ +static void parse_validnames_statement(const char *filename,int lnr, + const char *keyword,char *line,struct ldap_config *cfg); + /* set the configuration information to the defaults */ static void cfg_defaults(struct ldap_config *cfg) { @@ -121,6 +126,8 @@ static void cfg_defaults(struct ldap_config *cfg) cfg->ldc_nss_initgroups_ignoreusers=NULL; cfg->ldc_pam_authz_search=NULL; cfg->ldc_nss_min_uid=0; + parse_validnames_statement(__FILE__,__LINE__,"", + "/^[a-z0-9._@$][a-z0-9._@$ \\~-]+[a-z0-9._@$~-]$/i",cfg); } /* simple strdup wrapper */ @@ -568,6 +575,52 @@ static void set_base(const char *filename,int lnr, *var=xstrdup(value); } +/* parse the validnames statement */ +static void parse_validnames_statement(const char *filename,int lnr, + const char *keyword,char *line,struct ldap_config *cfg) +{ + char *value=NULL; + int i,l; + int flags=REG_EXTENDED|REG_NOSUB; + /* the rest of the line should be a regular expression */ + get_restdup(filename,lnr,keyword,&line,&value); + /* check formatting and update flags */ + if (value[0]!='/') + { + log_log(LOG_ERR,"%s:%d: regular expression incorrectly delimited",filename,lnr); + exit(EXIT_FAILURE); + } + l=strlen(value); + if (value[l-1]=='i') + { + value[l-1]='\0'; + l--; + flags|=REG_ICASE; + } + if (value[l-1]!='/') + { + log_log(LOG_ERR,"%s:%d: regular expression incorrectly delimited",filename,lnr); + exit(EXIT_FAILURE); + } + value[l-1]='\0'; + /* compile the regular expression */ + if ((i=regcomp(&cfg->validnames,value+1,flags))!= 0) + { + /* get the error message */ + l=regerror(i,&cfg->validnames,NULL,0); + value=malloc(l); + if (value==NULL) + log_log(LOG_ERR,"%s:%d: invalid regular expression",filename,lnr); + else + { + regerror(i,&cfg->validnames,value,l); + log_log(LOG_ERR,"%s:%d: invalid regular expression: %s",filename,lnr, + value); + } + exit(EXIT_FAILURE); + } +} + static void parse_base_statement(const char *filename,int lnr, const char *keyword,char *line, struct ldap_config *cfg) @@ -1013,6 +1066,10 @@ static void cfg_read(const char *filename,struct ldap_config *cfg) get_uid(filename,lnr,keyword,&line,&cfg->ldc_nss_min_uid); get_eol(filename,lnr,keyword,&line); } + else if (strcasecmp(keyword,"validnames")==0) + { + parse_validnames_statement(filename,lnr,keyword,line,cfg); + } #ifdef ENABLE_CONFIGFILE_CHECKING /* fallthrough */ else diff --git a/nslcd/cfg.h b/nslcd/cfg.h index a44d5d2..3a9b66b 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 Arthur de Jong + Copyright (C) 2007, 2008, 2009, 2010, 2011 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 @@ -30,6 +30,7 @@ #include <sys/types.h> #include <lber.h> #include <ldap.h> +#include <regex.h> #include "compat/attrs.h" #include "common/set.h" @@ -139,6 +140,8 @@ struct ldap_config char *ldc_pam_authz_search; /* minimum uid for users retreived from LDAP */ uid_t ldc_nss_min_uid; + /* the regular expression to determine valid names */ + regex_t validnames; }; /* this is a pointer to the global configuration, it should be available diff --git a/nslcd/common.c b/nslcd/common.c index a4b0445..54a0f1a 100644 --- a/nslcd/common.c +++ b/nslcd/common.c @@ -33,11 +33,13 @@ #include <limits.h> #include <netdb.h> #include <string.h> +#include <regex.h> #include "nslcd.h" #include "common.h" #include "log.h" #include "attmap.h" +#include "cfg.h" /* simple wrapper around snptintf() to return non-0 in case of any failure (but always keep string 0-terminated) */ @@ -140,48 +142,10 @@ const char *get_userpassword(MYLDAP_ENTRY *entry,const char *attr,char *buffer,s (any code for this is more than welcome) */ } -/* - Checks to see if the specified name seems to be a valid user or group name. - - This test is based on the definition from POSIX (IEEE Std 1003.1, 2004, - 3.426 User Name, 3.189 Group Name and 3.276 Portable Filename Character Set): - http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_426 - http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_189 - http://www.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap03.html#tag_03_276 - - The standard defines user names valid if they contain characters from - the set [A-Za-z0-9._-] where the hyphen should not be used as first - character. As an extension this test allows some more characters. -*/ +/* Checks if the specified name seems to be a valid user or group name. */ int isvalidname(const char *name) { - int i; - if ((name==NULL)||(name[0]=='\0')) - return 0; - /* check characters */ - for (i=0;name[i]!='\0';i++) - { -#ifdef LOGIN_NAME_MAX - if (i>=LOGIN_NAME_MAX) - return 0; -#endif /* LOGIN_NAME_MAX */ - /* characters supported everywhere in the name */ - if ( (name[i]>='@' && name[i] <= 'Z') || - (name[i]>='a' && name[i] <= 'z') || - (name[i]>='0' && name[i] <= '9') || - name[i]=='.' || name[i]=='_' || name[i]=='$' ) - continue; - /* characters that may be anywhere except as first character */ - if ( i>0 && ( name[i]=='-' || name[i]=='~' ) ) - continue; - /* characters that may not be the first or last character */ - if ( ( i>0 && name[i+1]!='\0' ) && ( name[i]=='\\' || name[i]==' ') ) - continue; - /* anything else is bad */ - return 0; - } - /* no test failed so it must be good */ - return -1; + return regexec(&nslcd_cfg->validnames,name,0,NULL,0)==0; } /* this writes a single address to the stream */ diff --git a/tests/Makefile.am b/tests/Makefile.am index 272ce04..f132208 100644 --- a/tests/Makefile.am +++ b/tests/Makefile.am @@ -73,7 +73,7 @@ test_getpeercred_SOURCES = test_getpeercred.c test_getpeercred_LDADD = ../compat/libcompat.a test_common_SOURCES = test_common.c -test_common_LDADD = ../nslcd/log.o ../nslcd/common.o ../nslcd/cfg.o \ +test_common_LDADD = ../nslcd/log.o ../nslcd/common.o \ ../nslcd/alias.o ../nslcd/ether.o ../nslcd/group.o \ ../nslcd/host.o ../nslcd/netgroup.o ../nslcd/network.o \ ../nslcd/passwd.o ../nslcd/protocol.o ../nslcd/rpc.o \ diff --git a/tests/test_common.c b/tests/test_common.c index 092867b..ee96733 100644 --- a/tests/test_common.c +++ b/tests/test_common.c @@ -26,6 +26,11 @@ #include <assert.h> #include "nslcd/common.h" +#include "nslcd/cfg.h" + +/* we include nslcd/cfg.c here to use cfg_defaults() to set the default + regular expression used in test_isvalidname() */ +#include "nslcd/cfg.c" static void test_isvalidname(void) { @@ -41,6 +46,8 @@ static void test_isvalidname(void) /* the main program... */ int main(int UNUSED(argc),char UNUSED(*argv[])) { + nslcd_cfg=(struct ldap_config *)malloc(sizeof(struct ldap_config)); + cfg_defaults(nslcd_cfg); test_isvalidname(); return 0; } |