Arthur de Jong

Open Source / Free Software developer

summaryrefslogtreecommitdiffstats
path: root/nslcd
diff options
context:
space:
mode:
Diffstat (limited to 'nslcd')
-rw-r--r--nslcd/Makefile.am2
-rw-r--r--nslcd/attmap.c86
-rw-r--r--nslcd/attmap.h18
-rw-r--r--nslcd/cfg.c12
-rw-r--r--nslcd/passwd.c104
-rw-r--r--nslcd/shadow.c89
6 files changed, 168 insertions, 143 deletions
diff --git a/nslcd/Makefile.am b/nslcd/Makefile.am
index bdf3150..3989c4a 100644
--- a/nslcd/Makefile.am
+++ b/nslcd/Makefile.am
@@ -33,4 +33,4 @@ nslcd_SOURCES = nslcd.c ../nslcd.h ../common/nslcd-prot.h \
alias.c ether.c group.c host.c netgroup.c network.c \
passwd.c protocol.c rpc.c service.c shadow.c pam.c
nslcd_LDADD = @nslcd_LIBS@ ../common/libtio.a ../common/libdict.a \
- ../compat/libcompat.a
+ ../common/libexpr.a ../compat/libcompat.a
diff --git a/nslcd/attmap.c b/nslcd/attmap.c
index 765d178..f703345 100644
--- a/nslcd/attmap.c
+++ b/nslcd/attmap.c
@@ -26,8 +26,8 @@
#include <strings.h>
#include "attmap.h"
-
-const char *attmap_objectClass = "objectClass";
+#include "log.h"
+#include "common/expr.h"
/* these are the bases that are defined per database */
extern const char *alias_bases[];
@@ -172,7 +172,6 @@ const char **attmap_get_var(enum ldap_map_selector map,const char *name)
if (strcasecmp(name,"uidNumber")==0) return &attmap_passwd_uidNumber;
if (strcasecmp(name,"gidNumber")==0) return &attmap_passwd_gidNumber;
if (strcasecmp(name,"gecos")==0) return &attmap_passwd_gecos;
- if (strcasecmp(name,"cn")==0) return &attmap_passwd_cn;
if (strcasecmp(name,"homeDirectory")==0) return &attmap_passwd_homeDirectory;
if (strcasecmp(name,"loginShell")==0) return &attmap_passwd_loginShell;
}
@@ -206,3 +205,84 @@ const char **attmap_get_var(enum ldap_map_selector map,const char *name)
}
return NULL;
}
+
+const char *attmap_set_mapping(const char **var,const char *value)
+{
+ /* check if we are setting an expression */
+ if (value[0]=='"')
+ {
+ /* these attributes may contain an expression
+ (note that this needs to match the functionality in the specific
+ lookup module) */
+ if ( (var!=&attmap_passwd_gidNumber) &&
+ (var!=&attmap_passwd_gecos) &&
+ (var!=&attmap_passwd_homeDirectory) &&
+ (var!=&attmap_passwd_loginShell) &&
+ (var!=&attmap_shadow_shadowLastChange) &&
+ (var!=&attmap_shadow_shadowMin) &&
+ (var!=&attmap_shadow_shadowMax) &&
+ (var!=&attmap_shadow_shadowWarning) &&
+ (var!=&attmap_shadow_shadowInactive) &&
+ (var!=&attmap_shadow_shadowExpire) &&
+ (var!=&attmap_shadow_shadowFlag) )
+ return NULL;
+ }
+ /* check if the value will be changed */
+ if ( (*var==NULL) || (strcmp(*var,value)!=0) )
+ *var=strdup(value);
+ return *var;
+}
+
+static const char *entry_expand(const char *name,void *expander_attr)
+{
+ MYLDAP_ENTRY *entry=(MYLDAP_ENTRY *)expander_attr;
+ const char **values;
+ if (strcasecmp(name,"dn")==0)
+ return myldap_get_dn(entry);
+ values=myldap_get_values(entry,name);
+ if (values==NULL)
+ return "";
+ /* TODO: handle userPassword attribute specially */
+ if ((values[0]!=NULL)&&(values[1]!=NULL))
+ {
+ log_log(LOG_WARNING,"entry %s contains multiple %s values",
+ myldap_get_dn(entry),name);
+ }
+ return values[0];
+}
+
+MUST_USE const char *attmap_get_value(MYLDAP_ENTRY *entry,const char *attr,char *buffer,size_t buflen)
+{
+ const char **values;
+ /* for simple values just return the attribute */
+ if (attr[0]!='"')
+ {
+ values=myldap_get_values(entry,attr);
+ if (values==NULL)
+ return NULL;
+ strncpy(buffer,values[0],buflen);
+ buffer[buflen-1]='\0';
+ return buffer;
+ /* TODO: maybe warn when multiple values are found */
+ }
+ if ( (attr[strlen(attr)-1]!='"') ||
+ (expr_parse(attr+1,buffer,buflen,entry_expand,(void *)entry)==NULL) )
+ {
+ log_log(LOG_ERR,"attribute mapping %s is invalid",attr);
+ buffer[0]='\0';
+ return NULL;
+ }
+ /* strip trailing " */
+ if (buffer[strlen(buffer)-1]=='"')
+ buffer[strlen(buffer)-1]='\0';
+ return buffer;
+}
+
+SET *attmap_add_attributes(SET *set,const char *attr)
+{
+ if (attr[0]!='\"')
+ set_add(set,attr);
+ else
+ expr_vars(attr,set);
+ return set;
+}
diff --git a/nslcd/attmap.h b/nslcd/attmap.h
index 7ec9177..48578c1 100644
--- a/nslcd/attmap.h
+++ b/nslcd/attmap.h
@@ -2,7 +2,7 @@
attmap.h - attribute mapping variables
This file is part of the nss-pam-ldapd library.
- Copyright (C) 2007, 2008 Arthur de Jong
+ Copyright (C) 2007, 2008, 2009 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
@@ -24,6 +24,8 @@
#define _ATTMAP_H 1
#include "cfg.h"
+#include "myldap.h"
+#include "common/set.h"
/* these are the attribute names per database */
extern const char *attmap_alias_cn;
@@ -49,7 +51,6 @@ extern const char *attmap_passwd_userPassword;
extern const char *attmap_passwd_uidNumber;
extern const char *attmap_passwd_gidNumber;
extern const char *attmap_passwd_gecos;
-extern const char *attmap_passwd_cn;
extern const char *attmap_passwd_homeDirectory;
extern const char *attmap_passwd_loginShell;
extern const char *attmap_protocol_cn;
@@ -83,4 +84,17 @@ const char **filter_get_var(enum ldap_map_selector map);
underscode replaced by a dot (e.g passwd.homeDirectory) */
const char **attmap_get_var(enum ldap_map_selector map,const char *name);
+/* Set the attribute mapping of the variable to the value specified.
+ Returns the new value on success. */
+
+const char *attmap_set_mapping(const char **var,const char *value);
+
+/* Return a value for the attribute, handling the case where attr
+ is an expression. */
+const char *attmap_get_value(MYLDAP_ENTRY *entry,const char *attr,char *buffer,size_t buflen);
+
+/* Add the attributes from attr to the set. The attr argumenent
+ can either be an attribute or an attribute expression. */
+SET *attmap_add_attributes(SET *set,const char *attr);
+
#endif /* not _ATTMAP_H */
diff --git a/nslcd/cfg.c b/nslcd/cfg.c
index e8a5408..060b566 100644
--- a/nslcd/cfg.c
+++ b/nslcd/cfg.c
@@ -623,7 +623,7 @@ static void parse_map_statement(const char *filename,int lnr,
{
enum ldap_map_selector map;
const char **var;
- char oldatt[32], newatt[32];
+ char oldatt[32], newatt[1024];
/* get the map */
if ((map=get_map(&line))==LM_NONE)
{
@@ -636,19 +636,17 @@ static void parse_map_statement(const char *filename,int lnr,
(get_token(&line,newatt,sizeof(newatt))!=NULL));
/* check that there are no more tokens left on the line */
get_eol(filename,lnr,keyword,&line);
- /* get the attribute variable to set */
+ /* change attribute mapping */
var=attmap_get_var(map,oldatt);
if (var==NULL)
{
log_log(LOG_ERR,"%s:%d: unknown attribute to map: '%s'",filename,lnr,oldatt);
exit(EXIT_FAILURE);
}
- /* check if the value will be changed */
- if ( (*var==NULL) || (strcmp(*var,newatt)!=0) )
+ if (attmap_set_mapping(var,newatt)==NULL)
{
- /* Note: we have a memory leak here if a single mapping is changed
- multiple times in one config (deemed not a problem) */
- *var=xstrdup(newatt);
+ log_log(LOG_ERR,"%s:%d: attribute %s cannot be an expression",filename,lnr,oldatt);
+ exit(EXIT_FAILURE);
}
}
diff --git a/nslcd/passwd.c b/nslcd/passwd.c
index 63bfce8..a5149f5 100644
--- a/nslcd/passwd.c
+++ b/nslcd/passwd.c
@@ -59,17 +59,14 @@ const char *attmap_passwd_uid = "uid";
const char *attmap_passwd_userPassword = "userPassword";
const char *attmap_passwd_uidNumber = "uidNumber";
const char *attmap_passwd_gidNumber = "gidNumber";
-const char *attmap_passwd_gecos = "gecos";
-const char *attmap_passwd_cn = "cn";
+const char *attmap_passwd_gecos = "\"${gecos:-$cn}\"";
const char *attmap_passwd_homeDirectory = "homeDirectory";
const char *attmap_passwd_loginShell = "loginShell";
/* default values for attributes */
static const char *default_passwd_userPassword = "*"; /* unmatchable */
-static const char *default_passwd_homeDirectory = "";
-static const char *default_passwd_loginShell = "";
-/* Note that the password value should be one of:
+/* Note that the resulting password value should be one of:
<empty> - no password set, allow login without password
* - often used to prevent logins
x - "valid" encrypted password that does not match any valid password
@@ -77,7 +74,7 @@ static const char *default_passwd_loginShell = "";
other - encrypted password, usually in crypt(3) format */
/* the attribute list to request with searches */
-static const char *passwd_attrs[10];
+static const char **passwd_attrs=NULL;
/* create a search filter for searching a passwd entry
by name, return -1 on errors */
@@ -109,6 +106,7 @@ static int mkfilter_passwd_byuid(uid_t uid,
void passwd_init(void)
{
int i;
+ SET *set;
/* set up search bases */
if (passwd_bases[0]==NULL)
for (i=0;i<NSS_LDAP_CONFIG_MAX_BASES;i++)
@@ -117,16 +115,17 @@ void passwd_init(void)
if (passwd_scope==LDAP_SCOPE_DEFAULT)
passwd_scope=nslcd_cfg->ldc_scope;
/* set up attribute list */
- passwd_attrs[0]=attmap_passwd_uid;
- passwd_attrs[1]=attmap_passwd_userPassword;
- passwd_attrs[2]=attmap_passwd_uidNumber;
- passwd_attrs[3]=attmap_passwd_gidNumber;
- passwd_attrs[4]=attmap_passwd_cn;
- passwd_attrs[5]=attmap_passwd_homeDirectory;
- passwd_attrs[6]=attmap_passwd_loginShell;
- passwd_attrs[7]=attmap_passwd_gecos;
- passwd_attrs[8]="objectClass";
- passwd_attrs[9]=NULL;
+ set=set_new();
+ attmap_add_attributes(set,"objectClass"); /* for testing shadowAccount */
+ attmap_add_attributes(set,attmap_passwd_uid);
+ attmap_add_attributes(set,attmap_passwd_userPassword);
+ attmap_add_attributes(set,attmap_passwd_uidNumber);
+ attmap_add_attributes(set,attmap_passwd_gidNumber);
+ attmap_add_attributes(set,attmap_passwd_gecos);
+ attmap_add_attributes(set,attmap_passwd_homeDirectory);
+ attmap_add_attributes(set,attmap_passwd_loginShell);
+ passwd_attrs=set_tolist(set);
+ set_free(set);
}
/* the cache that is used in dn2uid() */
@@ -301,10 +300,11 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser,
const char *passwd;
uid_t uids[MAXUIDS_PER_ENTRY];
int numuids;
+ char gidbuf[10];
gid_t gid;
- const char *gecos;
- const char *homedir;
- const char *shell;
+ char gecos[100];
+ char homedir[100];
+ char shell[100];
int i,j;
/* get the usernames for this entry */
usernames=myldap_get_values(entry,attmap_passwd_uid);
@@ -353,77 +353,29 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser,
}
}
/* get the gid for this entry */
- tmpvalues=myldap_get_values(entry,attmap_passwd_gidNumber);
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL))
+ attmap_get_value(entry,attmap_passwd_gidNumber,gidbuf,sizeof(gidbuf));
+ if (gidbuf[0]=='\0')
{
log_log(LOG_WARNING,"passwd entry %s does not contain %s value",
myldap_get_dn(entry),attmap_passwd_gidNumber);
return 0;
}
- else if (tmpvalues[1]!=NULL)
- {
- log_log(LOG_WARNING,"passwd entry %s contains multiple %s values",
- myldap_get_dn(entry),attmap_passwd_gidNumber);
- }
- gid=(gid_t)strtol(tmpvalues[0],&tmp,0);
- if ((*(tmpvalues[0])=='\0')||(*tmp!='\0'))
+ gid=(gid_t)strtol(gidbuf,&tmp,0);
+ if ((gidbuf[0]=='\0')||(*tmp!='\0'))
{
log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value",
myldap_get_dn(entry),attmap_passwd_gidNumber);
return 0;
}
- /* get the gecos for this entry (fall back to cn) */
- tmpvalues=myldap_get_values(entry,attmap_passwd_gecos);
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL))
- tmpvalues=myldap_get_values(entry,attmap_passwd_cn);
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL))
- {
- log_log(LOG_WARNING,"passwd entry %s does not contain %s or %s value",
- myldap_get_dn(entry),attmap_passwd_gecos,attmap_passwd_cn);
- return 0;
- }
- else if (tmpvalues[1]!=NULL)
- {
- log_log(LOG_WARNING,"passwd entry %s contains multiple %s or %s values",
- myldap_get_dn(entry),attmap_passwd_gecos,attmap_passwd_cn);
- }
- gecos=tmpvalues[0];
+ /* get the gecos for this entry */
+ attmap_get_value(entry,attmap_passwd_gecos,gecos,sizeof(gecos));
/* get the home directory for this entry */
- tmpvalues=myldap_get_values(entry,attmap_passwd_homeDirectory);
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL))
- {
+ attmap_get_value(entry,attmap_passwd_homeDirectory,homedir,sizeof(homedir));
+ if (homedir[0]=='\0')
log_log(LOG_WARNING,"passwd entry %s does not contain %s value",
myldap_get_dn(entry),attmap_passwd_homeDirectory);
- homedir=default_passwd_homeDirectory;
- }
- else
- {
- if (tmpvalues[1]!=NULL)
- {
- log_log(LOG_WARNING,"passwd entry %s contains multiple %s values",
- myldap_get_dn(entry),attmap_passwd_homeDirectory);
- }
- homedir=tmpvalues[0];
- if (*homedir=='\0')
- homedir=default_passwd_homeDirectory;
- }
/* get the shell for this entry */
- tmpvalues=myldap_get_values(entry,attmap_passwd_loginShell);
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL))
- {
- shell=default_passwd_loginShell;
- }
- else
- {
- if (tmpvalues[1]!=NULL)
- {
- log_log(LOG_WARNING,"passwd entry %s contains multiple %s values",
- myldap_get_dn(entry),attmap_passwd_loginShell);
- }
- shell=tmpvalues[0];
- if (*shell=='\0')
- shell=default_passwd_loginShell;
- }
+ attmap_get_value(entry,attmap_passwd_loginShell,shell,sizeof(shell));
/* write the entries */
for (i=0;usernames[i]!=NULL;i++)
if ((requser==NULL)||(strcmp(requser,usernames[i])==0))
diff --git a/nslcd/shadow.c b/nslcd/shadow.c
index ac00bda..4cb7067 100644
--- a/nslcd/shadow.c
+++ b/nslcd/shadow.c
@@ -55,26 +55,19 @@ const char *shadow_filter = "(objectClass=shadowAccount)";
/* the attributes to request with searches */
const char *attmap_shadow_uid = "uid";
const char *attmap_shadow_userPassword = "userPassword";
-const char *attmap_shadow_shadowLastChange = "shadowLastChange";
-const char *attmap_shadow_shadowMin = "shadowMin";
-const char *attmap_shadow_shadowMax = "shadowMax";
-const char *attmap_shadow_shadowWarning = "shadowWarning";
-const char *attmap_shadow_shadowInactive = "shadowInactive";
-const char *attmap_shadow_shadowExpire = "shadowExpire";
-const char *attmap_shadow_shadowFlag = "shadowFlag";
+const char *attmap_shadow_shadowLastChange = "\"${shadowLastChange:--1}\"";
+const char *attmap_shadow_shadowMin = "\"${shadowMin:--1}\"";
+const char *attmap_shadow_shadowMax = "\"${shadowMax:--1}\"";
+const char *attmap_shadow_shadowWarning = "\"${shadowWarning:--1}\"";
+const char *attmap_shadow_shadowInactive = "\"${shadowInactive:--1}\"";
+const char *attmap_shadow_shadowExpire = "\"${shadowExpire:--1}\"";
+const char *attmap_shadow_shadowFlag = "\"${shadowFlag:-0}\"";
/* default values for attributes */
static const char *default_shadow_userPassword = "*"; /* unmatchable */
-static const char *default_shadow_shadowLastChange = "-1";
-static const char *default_shadow_shadowMin = "-1";
-static const char *default_shadow_shadowMax = "-1";
-static const char *default_shadow_shadowWarning = "-1";
-static const char *default_shadow_shadowInactive = "-1";
-static const char *default_shadow_shadowExpire = "-1";
-static const char *default_shadow_shadowFlag = "0";
/* the attribute list to request with searches */
-static const char *shadow_attrs[10];
+static const char **shadow_attrs=NULL;
static int mkfilter_shadow_byname(const char *name,
char *buffer,size_t buflen)
@@ -93,6 +86,7 @@ static int mkfilter_shadow_byname(const char *name,
void shadow_init(void)
{
int i;
+ SET *set;
/* set up search bases */
if (shadow_bases[0]==NULL)
for (i=0;i<NSS_LDAP_CONFIG_MAX_BASES;i++)
@@ -101,16 +95,18 @@ void shadow_init(void)
if (shadow_scope==LDAP_SCOPE_DEFAULT)
shadow_scope=nslcd_cfg->ldc_scope;
/* set up attribute list */
- shadow_attrs[0]=attmap_shadow_uid;
- shadow_attrs[1]=attmap_shadow_userPassword;
- shadow_attrs[2]=attmap_shadow_shadowLastChange;
- shadow_attrs[3]=attmap_shadow_shadowMax;
- shadow_attrs[4]=attmap_shadow_shadowMin;
- shadow_attrs[5]=attmap_shadow_shadowWarning;
- shadow_attrs[6]=attmap_shadow_shadowInactive;
- shadow_attrs[7]=attmap_shadow_shadowExpire;
- shadow_attrs[8]=attmap_shadow_shadowFlag;
- shadow_attrs[9]=NULL;
+ set=set_new();
+ attmap_add_attributes(set,attmap_shadow_uid);
+ attmap_add_attributes(set,attmap_shadow_userPassword);
+ attmap_add_attributes(set,attmap_shadow_shadowLastChange);
+ attmap_add_attributes(set,attmap_shadow_shadowMax);
+ attmap_add_attributes(set,attmap_shadow_shadowMin);
+ attmap_add_attributes(set,attmap_shadow_shadowWarning);
+ attmap_add_attributes(set,attmap_shadow_shadowInactive);
+ attmap_add_attributes(set,attmap_shadow_shadowExpire);
+ attmap_add_attributes(set,attmap_shadow_shadowFlag);
+ shadow_attrs=set_tolist(set);
+ set_free(set);
}
static long to_date(const char *date,const char *attr)
@@ -156,43 +152,27 @@ static long to_date(const char *date,const char *attr)
#endif
#define GET_OPTIONAL_LONG(var,att) \
- tmpvalues=myldap_get_values(entry,attmap_shadow_##att); \
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL)) \
- var=strtol(default_shadow_##att,NULL,0); \
- else \
+ tmpvalue=attmap_get_value(entry,attmap_shadow_##att,buffer,sizeof(buffer)); \
+ if (tmpvalue==NULL) \
+ tmpvalue=""; \
+ var=strtol(tmpvalue,&tmp,0); \
+ if ((*(tmpvalue)=='\0')||(*tmp!='\0')) \
{ \
- if (tmpvalues[1]!=NULL) \
- { \
- log_log(LOG_WARNING,"shadow entry %s contains multiple %s values", \
- myldap_get_dn(entry),attmap_shadow_##att); \
- } \
- var=strtol(tmpvalues[0],&tmp,0); \
- if ((*(tmpvalues[0])=='\0')||(*tmp!='\0')) \
- { \
- log_log(LOG_WARNING,"shadow entry %s contains non-numeric %s value", \
- myldap_get_dn(entry),attmap_shadow_##att); \
- return 0; \
- } \
+ log_log(LOG_WARNING,"shadow entry %s contains non-numeric %s value", \
+ myldap_get_dn(entry),attmap_shadow_##att); \
+ return 0; \
}
#define GET_OPTIONAL_DATE(var,att) \
- tmpvalues=myldap_get_values(entry,attmap_shadow_##att); \
- if ((tmpvalues==NULL)||(tmpvalues[0]==NULL)) \
- var=to_date(default_shadow_##att,attmap_shadow_##att); \
- else \
- { \
- if (tmpvalues[1]!=NULL) \
- { \
- log_log(LOG_WARNING,"shadow entry %s contains multiple %s values", \
- myldap_get_dn(entry),attmap_shadow_##att); \
- } \
- var=to_date(tmpvalues[0],attmap_shadow_##att); \
- }
+ tmpvalue=attmap_get_value(entry,attmap_shadow_##att,buffer,sizeof(buffer)); \
+ if (tmpvalue==NULL) \
+ tmpvalue=""; \
+ var=to_date(tmpvalue,attmap_shadow_##att);
static int write_shadow(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser)
{
int32_t tmpint32;
- const char **tmpvalues;
+ const char *tmpvalue;
char *tmp;
const char **usernames;
const char *passwd;
@@ -204,6 +184,7 @@ static int write_shadow(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser)
long expiredate;
unsigned long flag;
int i;
+ char buffer[80];
/* get username */
usernames=myldap_get_values(entry,attmap_shadow_uid);
if ((usernames==NULL)||(usernames[0]==NULL))