diff options
author | Arthur de Jong <arthur@arthurdejong.org> | 2011-04-15 21:16:33 +0000 |
---|---|---|
committer | Arthur de Jong <arthur@arthurdejong.org> | 2011-04-15 21:16:33 +0000 |
commit | 4f235daac0131942dd5c882b80f114ba64f92152 (patch) | |
tree | 6fb02deadb3b00a07e9700abc184cb25a4dd1459 | |
parent | 984cee3efe542f992e64d57660e842065a5cf018 (diff) |
support using the objectSid attribute to provide numeric user and group ids, based on a patch by Wesley Mason
git-svn-id: http://arthurdejong.org/svn/nss-pam-ldapd/nss-pam-ldapd@1425 ef36b2f9-881f-0410-afb5-c4e39611909c
-rw-r--r-- | man/nslcd.conf.5.xml | 9 | ||||
-rw-r--r-- | nslcd/common.c | 57 | ||||
-rw-r--r-- | nslcd/common.h | 8 | ||||
-rw-r--r-- | nslcd/group.c | 47 | ||||
-rw-r--r-- | nslcd/passwd.c | 103 |
5 files changed, 189 insertions, 35 deletions
diff --git a/man/nslcd.conf.5.xml b/man/nslcd.conf.5.xml index 4c5d51f..febd92c 100644 --- a/man/nslcd.conf.5.xml +++ b/man/nslcd.conf.5.xml @@ -388,7 +388,7 @@ the supported maps below. The <replaceable>ATTRIBUTE</replaceable> is the one as used in <acronym>RFC</acronym> 2307 (e.g. <literal>userPassword</literal>, - <literal>ipProtocolNumber</literal> or <literal>macAddress</literal>). + <literal>ipProtocolNumber</literal>, <literal>macAddress</literal>, etc.). The <replaceable>NEWATTRIBUTE</replaceable> may be any attribute as it is available in the directory. </para> @@ -415,6 +415,13 @@ <literal>shadowExpire</literal> and <literal>shadowFlag</literal>. </para> <para> + The <literal>uidNumber</literal> and <literal>gidNumber</literal> + attributes in the <literal>passwd</literal> and <literal>group</literal> + maps may be mapped to the <literal>objectSid</literal> followed by + the domain SID to derive numeric user and group ids from the SID + (e.g. <literal>objectSid:S-1-5-21-3623811015-3361044348-30300820</literal>). + </para> + <para> By default all <literal>userPassword</literal> attributes are mapped to the unmatchable password ("*") to avoid accidentally leaking password information. diff --git a/nslcd/common.c b/nslcd/common.c index 54a0f1a..921976c 100644 --- a/nslcd/common.c +++ b/nslcd/common.c @@ -34,6 +34,7 @@ #include <netdb.h> #include <string.h> #include <regex.h> +#include <stdlib.h> #include "nslcd.h" #include "common.h" @@ -212,3 +213,59 @@ int read_address(TFILE *fp,char *addr,int *addrlen,int *af) /* we're done */ return 0; } + +/* convert the provided string representation of a sid + (e.g. S-1-5-21-1936905831-823966427-12391542-23578) + to a format that can be used to search the objectSid property with */ +char *sid2search(const char *sid) +{ + const char *tmpsid=sid; + char *res,*tmp; + int i=0; + long int l; + /* check the beginning of the string */ + if (strncasecmp(sid,"S-",2)!=0) + { + log_log(LOG_ERR,"error in SID %s",sid); + exit(EXIT_FAILURE); + } + /* count the number of dashes in the sid */ + while (tmpsid!=NULL) + { + i++; + tmpsid=strchr(tmpsid+1,'-'); + } + i-=2; /* number of security ids plus one because we add the uid later */ + /* allocate memory */ + res=malloc(3+3+6*3+i*4*3+1); + if (res==NULL) + { + log_log(LOG_CRIT,"malloc() failed to allocate memory"); + exit(1); + } + /* build the first part */ + l=strtol(sid+2,&tmp,10); + sprintf(res,"\\%02x\\%02x",(int)l&0xff,(int)i); + /* build authority part (we only handle 32 of the 48 bits) */ + l=strtol(tmp+1,&tmp,10); + sprintf(res+strlen(res),"\\00\\00\\%02x\\%02x\\%02x\\%02x", + (int)((l>>24)&0xff),(int)((l>>16)&0xff),(int)((l>>8)&0xff),(int)(l&0xff)); + /* go over the rest of the bits */ + while (*tmp!='\0') + { + l=strtol(tmp+1,&tmp,10); + sprintf(res+strlen(res),"\\%02x\\%02x\\%02x\\%02x", + (int)(l&0xff),(int)((l>>8)&0xff),(int)((l>>16)&0xff),(int)((l>>24)&0xff)); + } + return res; +} + +/* return the last security identifier of the binary sid */ +long int binsid2id(const char *binsid) +{ + int i; + /* find the position of the last security id */ + i=2+6+((((int)binsid[1])&0xff)-1)*4; + return (((long int)binsid[i])&0xff)|((((long int)binsid[i+1])&0xff)<<8)| + ((((long int)binsid[i+2])&0xff)<<16)|((((long int)binsid[i+3])&0xff)<<24); +} diff --git a/nslcd/common.h b/nslcd/common.h index 9247911..3527434 100644 --- a/nslcd/common.h +++ b/nslcd/common.h @@ -84,6 +84,14 @@ int read_address(TFILE *fp,char *addr,int *addrlen,int *af); if (read_address(fp,addr,&(len),&(af))) \ return -1; +/* convert the provided string representation of a sid + (e.g. S-1-5-21-1936905831-823966427-12391542-23578) + to a format that can be used to search the objectSid property with */ +MUST_USE char *sid2search(const char *sid); + +/* return the last security identifier of the binary sid */ +MUST_USE long int binsid2id(const char *binsid); + /* checks to see if the specified string is a valid user or group name */ MUST_USE int isvalidname(const char *name); diff --git a/nslcd/group.c b/nslcd/group.c index 8813755..f320828 100644 --- a/nslcd/group.c +++ b/nslcd/group.c @@ -5,7 +5,7 @@ Copyright (C) 1997-2006 Luke Howard Copyright (C) 2006 West Consulting - Copyright (C) 2006, 2007, 2008, 2009, 2010 Arthur de Jong + Copyright (C) 2006, 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 @@ -66,6 +66,10 @@ const char *attmap_group_gidNumber = "gidNumber"; const char *attmap_group_memberUid = "memberUid"; const char *attmap_group_uniqueMember = "uniqueMember"; +/* special property for objectSid-based searches + (these are already LDAP-escaped strings) */ +static char *gidSid=NULL; + /* default values for attributes */ static const char *default_group_userPassword = "*"; /* unmatchable */ @@ -93,10 +97,22 @@ static int mkfilter_group_byname(const char *name, static int mkfilter_group_bygid(gid_t gid, char *buffer,size_t buflen) { - return mysnprintf(buffer,buflen, - "(&%s(%s=%d))", - group_filter, - attmap_group_gidNumber,(int)gid); + if (gidSid!=NULL) + { + return mysnprintf(buffer,buflen, + "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))", + group_filter, + attmap_group_gidNumber,gidSid, + (int)(gid&0xff),(int)((gid>>8)&0xff), + (int)((gid>>16)&0xff),(int)((gid>>24)&0xff)); + } + else + { + return mysnprintf(buffer,buflen, + "(&%s(%s=%d))", + group_filter, + attmap_group_gidNumber,(int)gid); + } } /* create a search filter for searching a group entry @@ -139,6 +155,12 @@ void group_init(void) /* set up scope */ if (group_scope==LDAP_SCOPE_DEFAULT) group_scope=nslcd_cfg->ldc_scope; + /* special case when gidNumber references objectSid */ + if (strncasecmp(attmap_group_gidNumber,"objectSid:",10)==0) + { + gidSid=sid2search(attmap_group_gidNumber+10); + attmap_group_gidNumber=strndup(attmap_group_gidNumber,9); + } /* set up attribute list */ set=set_new(); attmap_add_attributes(set,attmap_group_cn); @@ -253,12 +275,17 @@ static int write_group(TFILE *fp,MYLDAP_ENTRY *entry,const char *reqname, } for (numgids=0;(gidvalues[numgids]!=NULL)&&(numgids<MAXGIDS_PER_ENTRY);numgids++) { - gids[numgids]=(gid_t)strtol(gidvalues[numgids],&tmp,0); - if ((*(gidvalues[numgids])=='\0')||(*tmp!='\0')) + if (gidSid!=NULL) + gids[numgids]=(gid_t)binsid2id(gidvalues[numgids]); + else { - log_log(LOG_WARNING,"group entry %s contains non-numeric %s value", - myldap_get_dn(entry),attmap_group_gidNumber); - return 0; + gids[numgids]=(gid_t)strtol(gidvalues[numgids],&tmp,0); + if ((*(gidvalues[numgids])=='\0')||(*tmp!='\0')) + { + log_log(LOG_WARNING,"group entry %s contains non-numeric %s value", + myldap_get_dn(entry),attmap_group_gidNumber); + return 0; + } } } } diff --git a/nslcd/passwd.c b/nslcd/passwd.c index 1aa91a0..5f02486 100644 --- a/nslcd/passwd.c +++ b/nslcd/passwd.c @@ -63,6 +63,11 @@ const char *attmap_passwd_gecos = "\"${gecos:-$cn}\""; const char *attmap_passwd_homeDirectory = "homeDirectory"; const char *attmap_passwd_loginShell = "loginShell"; +/* special properties for objectSid-based searches + (these are already LDAP-escaped strings) */ +static char *uidSid=NULL; +static char *gidSid=NULL; + /* default values for attributes */ static const char *default_passwd_userPassword = "*"; /* unmatchable */ @@ -97,10 +102,22 @@ static int mkfilter_passwd_byname(const char *name, static int mkfilter_passwd_byuid(uid_t uid, char *buffer,size_t buflen) { - return mysnprintf(buffer,buflen, - "(&%s(%s=%d))", - passwd_filter, - attmap_passwd_uidNumber,(int)uid); + if (uidSid!=NULL) + { + return mysnprintf(buffer,buflen, + "(&%s(%s=%s\\%02x\\%02x\\%02x\\%02x))", + passwd_filter, + attmap_passwd_uidNumber,uidSid, + (int)(uid&0xff),(int)((uid>>8)&0xff), + (int)((uid>>16)&0xff),(int)((uid>>24)&0xff)); + } + else + { + return mysnprintf(buffer,buflen, + "(&%s(%s=%d))", + passwd_filter, + attmap_passwd_uidNumber,(int)uid); + } } void passwd_init(void) @@ -114,6 +131,17 @@ void passwd_init(void) /* set up scope */ if (passwd_scope==LDAP_SCOPE_DEFAULT) passwd_scope=nslcd_cfg->ldc_scope; + /* special case when uidNumber or gidNumber reference objectSid */ + if (strncasecmp(attmap_passwd_uidNumber,"objectSid:",10)==0) + { + uidSid=sid2search(attmap_passwd_uidNumber+10); + attmap_passwd_uidNumber=strndup(attmap_passwd_uidNumber,9); + } + if (strncasecmp(attmap_passwd_gidNumber,"objectSid:",10)==0) + { + gidSid=sid2search(attmap_passwd_gidNumber+10); + attmap_passwd_gidNumber=strndup(attmap_passwd_gidNumber,9); + } /* set up attribute list */ set=set_new(); attmap_add_attributes(set,"objectClass"); /* for testing shadowAccount */ @@ -160,11 +188,19 @@ static int entry_has_valid_uid(MYLDAP_ENTRY *entry) /* check if there is a uidNumber attributes >= min_uid */ for (i=0;values[i]!=NULL;i++) { - uid=(uid_t)strtol(values[i],&tmp,0); - if ((*(values[i])=='\0')||(*tmp!='\0')) - log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value", - myldap_get_dn(entry),attmap_passwd_uidNumber); - else if (uid>=nslcd_cfg->ldc_nss_min_uid) + if (uidSid!=NULL) + uid=(uid_t)binsid2id(values[i]); + else + { + uid=(uid_t)strtol(values[i],&tmp,0); + if ((*(values[i])=='\0')||(*tmp!='\0')) + { + log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value", + myldap_get_dn(entry),attmap_passwd_uidNumber); + continue; + } + } + if (uid>=nslcd_cfg->ldc_nss_min_uid) return 1; } /* nothing found */ @@ -397,29 +433,48 @@ static int write_passwd(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser, } for (numuids=0;(numuids<MAXUIDS_PER_ENTRY)&&(tmpvalues[numuids]!=NULL);numuids++) { - uids[numuids]=(uid_t)strtol(tmpvalues[numuids],&tmp,0); - if ((*(tmpvalues[numuids])=='\0')||(*tmp!='\0')) + if (uidSid!=NULL) + uids[numuids]=(uid_t)binsid2id(tmpvalues[numuids]); + else { - log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value", - myldap_get_dn(entry),attmap_passwd_uidNumber); - return 0; + uids[numuids]=(uid_t)strtol(tmpvalues[numuids],&tmp,0); + if ((*(tmpvalues[numuids])=='\0')||(*tmp!='\0')) + { + log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value", + myldap_get_dn(entry),attmap_passwd_uidNumber); + return 0; + } } } } /* get the gid for this entry */ - attmap_get_value(entry,attmap_passwd_gidNumber,gidbuf,sizeof(gidbuf)); - if (gidbuf[0]=='\0') + if (gidSid!=NULL) { - log_log(LOG_WARNING,"passwd entry %s does not contain %s value", - myldap_get_dn(entry),attmap_passwd_gidNumber); - return 0; + tmpvalues=myldap_get_values(entry,attmap_passwd_gidNumber); + if ((tmpvalues==NULL)||(tmpvalues[0]==NULL)) + { + log_log(LOG_WARNING,"passwd entry %s does not contain %s value", + myldap_get_dn(entry),attmap_passwd_gidNumber); + return 0; + } + gid=(gid_t)binsid2id(tmpvalues[0]); } - gid=(gid_t)strtol(gidbuf,&tmp,0); - if ((gidbuf[0]=='\0')||(*tmp!='\0')) + else { - log_log(LOG_WARNING,"passwd entry %s contains non-numeric %s value", - myldap_get_dn(entry),attmap_passwd_gidNumber); - return 0; + 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; + } + 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 */ attmap_get_value(entry,attmap_passwd_gecos,gecos,sizeof(gecos)); |