1 /* shadow.c - shadow account lookup routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2008-2010 The OpenLDAP Foundation.
6 * Portions Copyright 2008 by Howard Chu, Symas Corp.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted only as authorized by the OpenLDAP
13 * A copy of this license is available in the file LICENSE in the
14 * top-level directory of the distribution or, alternatively, at
15 * <http://www.OpenLDAP.org/license.html>.
18 * This code references portions of the nss-ldapd package
19 * written by Arthur de Jong. The nss-ldapd code was forked
20 * from the nss-ldap library written by Luke Howard.
25 /* ( nisSchema.2.1 NAME 'shadowAccount' SUP top AUXILIARY
26 * DESC 'Additional attributes for shadow passwords'
28 * MAY ( userPassword $ shadowLastChange $ shadowMin
29 * shadowMax $ shadowWarning $ shadowInactive $
30 * shadowExpire $ shadowFlag $ description ) )
33 /* the basic search filter for searches */
34 static struct berval shadow_filter = BER_BVC("(objectClass=shadowAccount)");
36 /* the attributes to request with searches */
37 static struct berval shadow_keys[] = {
39 BER_BVC("userPassword"),
40 BER_BVC("shadowLastChange"),
43 BER_BVC("shadowWarning"),
44 BER_BVC("shadowInactive"),
45 BER_BVC("shadowExpire"),
46 BER_BVC("shadowFlag"),
60 /* default values for attributes */
61 static struct berval default_shadow_userPassword = BER_BVC("*"); /* unmatchable */
62 static int default_nums[] = { 0,0,
74 static long to_date(struct berval *date,AttributeDescription *attr)
78 /* do some special handling for date values on AD */
79 if (strcasecmp(attr->ad_cname.bv_val,"pwdLastSet")==0)
83 /* we expect an AD 64-bit datetime value;
84 we should do date=date/864000000000-134774
85 but that causes problems on 32-bit platforms,
86 first we devide by 1000000000 by stripping the
87 last 9 digits from the string and going from there */
89 if (l<1 || l>(sizeof(buffer)-1))
91 strncpy(buffer,date->bv_val,l);
93 value=strtol(buffer,&tmp,0);
94 if ((buffer[0]=='\0')||(*tmp!='\0'))
96 Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
97 attr->ad_cname.bv_val,0,0);
100 return value/864-134774;
101 /* note that AD does not have expiry dates but a lastchangeddate
102 and some value that needs to be added */
104 value=strtol(date->bv_val,&tmp,0);
105 if ((date->bv_val[0]=='\0')||(*tmp!='\0'))
107 Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value\n",
108 attr->ad_cname.bv_val,0,0);
114 #ifndef UF_DONT_EXPIRE_PASSWD
115 #define UF_DONT_EXPIRE_PASSWD 0x10000
118 #define GET_OPTIONAL_LONG(var,key) \
119 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
120 if ( !a || BER_BVISNULL(&a->a_vals[0])) \
121 var = default_nums[key]; \
124 if (a->a_numvals > 1) \
126 Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
127 entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
129 var=strtol(a->a_vals[0].bv_val,&tmp,0); \
130 if ((a->a_vals[0].bv_val[0]=='\0')||(*tmp!='\0')) \
132 Debug(LDAP_DEBUG_ANY,"shadow entry %s contains non-numeric %s value\n", \
133 entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
138 #define GET_OPTIONAL_DATE(var,key) \
139 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
140 if ( !a || BER_BVISNULL(&a->a_vals[0])) \
141 var = default_nums[key]; \
144 if (a->a_numvals > 1) \
146 Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values\n", \
147 entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
149 var=to_date(&a->a_vals[0],cbp->mi->mi_attrs[key].an_desc); \
154 struct berval name;);
156 static int write_shadow(nssov_shadow_cbp *cbp,Entry *entry)
158 struct berval tmparr[2];
159 struct berval *names;
162 struct berval passwd = {0};
173 if (BER_BVISNULL(&cbp->name))
175 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[UID_KEY].an_desc);
178 Debug(LDAP_DEBUG_ANY,"shadow entry %s does not contain %s value\n",
179 entry->e_name.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val,0);
188 BER_BVZERO(&names[1]);
191 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);
193 get_userpassword(&a->a_vals[0], &passwd);
194 if (BER_BVISNULL(&passwd))
195 passwd=default_shadow_userPassword;
196 /* get lastchange date */
197 GET_OPTIONAL_DATE(lastchangedate,CHG_KEY);
199 GET_OPTIONAL_LONG(mindays,MIN_KEY);
201 GET_OPTIONAL_LONG(maxdays,MAX_KEY);
203 GET_OPTIONAL_LONG(warndays,WRN_KEY);
205 GET_OPTIONAL_LONG(inactdays,INA_KEY);
206 /* get expire date */
207 GET_OPTIONAL_LONG(expiredate,EXP_KEY);
209 GET_OPTIONAL_LONG(flag,FLG_KEY);
210 /* if we're using AD handle the flag specially */
211 if (strcasecmp(cbp->mi->mi_attrs[CHG_KEY].an_desc->ad_cname.bv_val,"pwdLastSet")==0)
213 if (flag&UF_DONT_EXPIRE_PASSWD)
217 /* write the entries */
218 for (i=0;!BER_BVISNULL(&names[i]);i++)
220 WRITE_INT32(cbp->fp,NSLCD_RESULT_BEGIN);
221 WRITE_BERVAL(cbp->fp,&names[i]);
222 WRITE_BERVAL(cbp->fp,&passwd);
223 WRITE_INT32(cbp->fp,lastchangedate);
224 WRITE_INT32(cbp->fp,mindays);
225 WRITE_INT32(cbp->fp,maxdays);
226 WRITE_INT32(cbp->fp,warndays);
227 WRITE_INT32(cbp->fp,inactdays);
228 WRITE_INT32(cbp->fp,expiredate);
229 WRITE_INT32(cbp->fp,flag);
239 struct berval filter = {sizeof(fbuf)};
240 filter.bv_val = fbuf;
241 READ_STRING(fp,cbp.buf);,
242 cbp.name.bv_len = tmpint32;
243 cbp.name.bv_val = cbp.buf;
244 Debug(LDAP_DEBUG_ANY,"nssov_shadow_byname(%s)\n",cbp.name.bv_val,0,0);,
245 NSLCD_ACTION_SHADOW_BYNAME,
246 nssov_filter_byname(cbp.mi,UID_KEY,&cbp.name,&filter)
251 struct berval filter;
252 /* no parameters to read */
253 BER_BVZERO(&cbp.name);,
254 Debug(LDAP_DEBUG_ANY,"nssov_shadow_all()\n",0,0,0);,
255 NSLCD_ACTION_SHADOW_ALL,
256 (filter=cbp.mi->mi_filter,0)