diff options
Diffstat (limited to 'nslcd')
-rw-r--r-- | nslcd/Makefile.am | 2 | ||||
-rw-r--r-- | nslcd/attmap.c | 86 | ||||
-rw-r--r-- | nslcd/attmap.h | 18 | ||||
-rw-r--r-- | nslcd/cfg.c | 12 | ||||
-rw-r--r-- | nslcd/passwd.c | 104 | ||||
-rw-r--r-- | nslcd/shadow.c | 89 |
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)) |