summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorArthur de Jong <arthur@arthurdejong.org>2011-03-25 13:30:46 +0000
committerArthur de Jong <arthur@arthurdejong.org>2011-03-25 13:30:46 +0000
commit72c4709eefbfac429eca3ed8fb66decd03ed098d (patch)
treea4fdb41fba9ba7af21955457cc6dc229b3e5e8fb
parent1fb820314c4b6f720bfca5ce5bfbc32183e3c3af (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.ac2
-rw-r--r--man/nslcd.conf.5.xml19
-rw-r--r--nslcd/cfg.c59
-rw-r--r--nslcd/cfg.h5
-rw-r--r--nslcd/common.c44
-rw-r--r--tests/Makefile.am2
-rw-r--r--tests/test_common.c7
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;
}