Blob Blame History Raw
Pulled from SVN, then tweaked to apply to 0.7.5, with the man page sections
added because we don't regenerate them, and with the defaults changed to allow
opening and closing parentheses everywhere.  Defaults changed again to make
characters after the first optional, then tweaked to apply to 0.7.13.

Index: tests/test_common.c
===================================================================
--- tests/test_common.c	(revision 1410)
+++ tests/test_common.c	(revision 1411)
@@ -26,15 +26,14 @@
 #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"
+#include "common/expr.c"
+#include "nslcd/attmap.c"
+
-/* this is a simple way to get this into an executable */
-const char **base_get_var(int UNUSED(map)) {return NULL;}
-int *scope_get_var(int UNUSED(map)) {return NULL;}
-const char **filter_get_var(int UNUSED(map)) {return NULL;}
-const char **attmap_get_var(int UNUSED(map),const char UNUSED(*name)) {return NULL;}
-const char *attmap_get_value(MYLDAP_ENTRY UNUSED(*entry),const char UNUSED(*attr),char UNUSED(*buffer),size_t UNUSED(buflen)) {return "";}
-void *attmap_add_attributes(void UNUSED(*set),const char UNUSED(*attr)) {return NULL;}
-const char *attmap_set_mapping(const char UNUSED(**var),const char UNUSED(*value)) {return NULL;}

 static void test_isvalidname(void)
 {
@@ -44,12 +43,15 @@ static void test_isvalidname(void)
   assert(isvalidname("sambamachine$"));
   assert(isvalidname("foo\\bar"));
   assert(!isvalidname("\\foo\\bar"));
-  assert(!isvalidname("foo\\bar\\"));
+  assert(isvalidname("foo\\bar"));
+  assert(isvalidname("foo\\bar\\"));
 }
 
 /* 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;
 }
Index: tests/Makefile.am
===================================================================
--- tests/Makefile.am	(revision 1410)
+++ tests/Makefile.am	(revision 1411)
@@ -73,7 +73,7 @@
 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 \
Index: nslcd/cfg.c
===================================================================
--- nslcd/cfg.c	(revision 1410)
+++ nslcd/cfg.c	(revision 1411)
@@ -75,6 +75,11 @@
     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 @@
   cfg->ldc_pagesize=0;
   cfg->ldc_nss_initgroups_ignoreusers=NULL;
   cfg->ldc_pam_authz_search=NULL;
+  parse_validnames_statement(__FILE__,__LINE__,"",
+                "/^[a-z0-9._@$()][a-z0-9._@$() \\~-]*[a-z0-9._@$()~-]?$/i",cfg);
 }
 
 /* simple strdup wrapper */
@@ -568,6 +575,52 @@
   *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 @@
       check_argumentcount(filename,lnr,keyword,(line!=NULL)&&(*line!='\0'));
       cfg->ldc_pam_authz_search=xstrdup(line);
     }
+    else if (strcasecmp(keyword,"validnames")==0)
+    {
+      parse_validnames_statement(filename,lnr,keyword,line,cfg);
+    }
 #ifdef ENABLE_CONFIGFILE_CHECKING
     /* fallthrough */
     else
Index: nslcd/cfg.h
===================================================================
--- nslcd/cfg.h	(revision 1410)
+++ nslcd/cfg.h	(revision 1411)
@@ -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 @@
   SET *ldc_nss_initgroups_ignoreusers;
   /* the search that should be performed to do autorisation checks */
   char *ldc_pam_authz_search;
+  /* the regular expression to determine valid names */
+  regex_t validnames;
 };
 
 /* this is a pointer to the global configuration, it should be available
Index: nslcd/common.c
===================================================================
--- nslcd/common.c	(revision 1410)
+++ nslcd/common.c	(revision 1411)
@@ -33,10 +33,12 @@
 #include <arpa/inet.h>
 #include <strings.h>
 #include <limits.h>
+#include <regex.h>
 
 #include "nslcd.h"
 #include "common.h"
 #include "log.h"
+#include "cfg.h"
 
 /* simple wrapper around snptintf() to return non-0 in case
    of any failure (but always keep string 0-terminated) */
@@ -140,41 +142,10 @@
     (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 */
-    if ( ! ( ( (i!=0) && (name[i]=='-') ) ||
-             ( (i!=0) && (name[i]=='\\') && name[i+1]!='\0' ) ||
-             (name[i]>='@' && name[i] <= 'Z') ||
-             (name[i]>='a' && name[i] <= 'z') ||
-             (name[i]>='0' && name[i] <= '9') ||
-             name[i]=='.' || name[i]=='_'  || name[i]=='$' || name[i]==' ') )
-      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 */
Index: configure.ac
===================================================================
--- configure.ac	(revision 1410)
+++ configure.ac	(revision 1411)
@@ -549,6 +549,8 @@
   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 @@
   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)
Index: man/nslcd.conf.5.xml
===================================================================
--- man/nslcd.conf.5.xml	(revision 1410)
+++ man/nslcd.conf.5.xml	(revision 1411)
@@ -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>
      <term><option>pam_authz_search</option>
            <replaceable>FILTER</replaceable></term>
--- man/nslcd.conf.5	2010-05-14 16:48:18.000000000 -0400
+++ man/nslcd.conf.5	2011-03-29 12:02:56.209777493 -0400
@@ -265,6 +265,20 @@ This option may be specified multiple ti
 Alternatively, the value \*(T<ALLLOCAL\*(T> may be
 used. With that value nslcd builds a full list of
 non-LDAP users on startup.
+.TP
+\*(T<\fBvalidnames\fR\*(T> \fIREGEX\fR
+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 LDAP.
+
+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-insensitive.
+
+The default value is
+ \*(T</^[a-z0-9._@$()][a-z0-9._@$() \\~-]*[a-z0-9._@$()~-]?$/i\*(T>
+
 .TP 
 \*(T<\fBpam_authz_search\fR\*(T> \fIFILTER\fR
 This option allows flexible fine tuning of the authorisation check that