1 /* shadow.c - shadow account lookup routines */
4 * Copyright 2008 by Howard Chu, Symas Corp.
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted only as authorized by the OpenLDAP
11 * A copy of this license is available in the file LICENSE in the
12 * top-level directory of the distribution or, alternatively, at
13 * <http://www.OpenLDAP.org/license.html>.
16 * This code references portions of the nss-ldapd package
17 * written by Arthur de Jong. The nss-ldapd code was forked
18 * from the nss-ldap library written by Luke Howard.
23 /* ( nisSchema.2.1 NAME 'shadowAccount' SUP top AUXILIARY
24 * DESC 'Additional attributes for shadow passwords'
26 * MAY ( userPassword $ shadowLastChange $ shadowMin
27 * shadowMax $ shadowWarning $ shadowInactive $
28 * shadowExpire $ shadowFlag $ description ) )
31 /* the basic search filter for searches */
32 static struct berval shadow_filter = BER_BVC("(objectClass=shadowAccount)");
34 /* the attributes to request with searches */
35 static struct berval shadow_keys[] = {
37 BER_BVC("userPassword"),
38 BER_BVC("shadowLastChange"),
41 BER_BVC("shadowWarning"),
42 BER_BVC("shadowInactive"),
43 BER_BVC("shadowExpire"),
44 BER_BVC("shadowFlag"),
58 /* default values for attributes */
59 static struct berval default_shadow_userPassword = BER_BVC("*"); /* unmatchable */
60 static int default_nums[] = { 0,0,
72 static long to_date(struct berval *date,AttributeDescription *attr)
76 /* do some special handling for date values on AD */
77 if (strcasecmp(attr->ad_cname.bv_val,"pwdLastSet")==0)
81 /* we expect an AD 64-bit datetime value;
82 we should do date=date/864000000000-134774
83 but that causes problems on 32-bit platforms,
84 first we devide by 1000000000 by stripping the
85 last 9 digits from the string and going from there */
87 if (l<1 || l>(sizeof(buffer)-1))
89 strncpy(buffer,date->bv_val,l);
91 value=strtol(buffer,&tmp,0);
92 if ((buffer[0]=='\0')||(*tmp!='\0'))
94 Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value",
95 attr->ad_cname.bv_val,0,0);
98 return value/864-134774;
99 /* note that AD does not have expiry dates but a lastchangeddate
100 and some value that needs to be added */
102 value=strtol(date->bv_val,&tmp,0);
103 if ((date->bv_val[0]=='\0')||(*tmp!='\0'))
105 Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value",
106 attr->ad_cname.bv_val,0,0);
112 #ifndef UF_DONT_EXPIRE_PASSWD
113 #define UF_DONT_EXPIRE_PASSWD 0x10000
116 #define GET_OPTIONAL_LONG(var,key) \
117 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
118 if ( !a || BER_BVISNULL(&a->a_vals[0])) \
119 var = default_nums[key]; \
122 if (a->a_numvals > 1) \
124 Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values", \
125 entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
127 var=strtol(a->a_vals[0].bv_val,&tmp,0); \
128 if ((a->a_vals[0].bv_val[0]=='\0')||(*tmp!='\0')) \
130 Debug(LDAP_DEBUG_ANY,"shadow entry %s contains non-numeric %s value", \
131 entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
136 #define GET_OPTIONAL_DATE(var,key) \
137 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[key].an_desc); \
138 if ( !a || BER_BVISNULL(&a->a_vals[0])) \
139 var = default_nums[key]; \
142 if (a->a_numvals > 1) \
144 Debug(LDAP_DEBUG_ANY,"shadow entry %s contains multiple %s values", \
145 entry->e_name.bv_val, cbp->mi->mi_attrs[key].an_desc->ad_cname.bv_val,0); \
147 var=to_date(&a->a_vals[0],cbp->mi->mi_attrs[key].an_desc); \
152 struct berval name;);
154 static int write_shadow(nssov_shadow_cbp *cbp,Entry *entry)
156 struct berval tmparr[2];
157 struct berval *names;
160 struct berval passwd = {0};
171 if (BER_BVISNULL(&cbp->name))
173 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[UID_KEY].an_desc);
176 Debug(LDAP_DEBUG_ANY,"shadow entry %s does not contain %s value",
177 entry->e_name.bv_val, cbp->mi->mi_attrs[UID_KEY].an_desc->ad_cname.bv_val,0);
186 BER_BVZERO(&names[1]);
189 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);
191 get_userpassword(&a->a_vals[0], &passwd);
192 if (BER_BVISNULL(&passwd))
193 passwd=default_shadow_userPassword;
194 /* get lastchange date */
195 GET_OPTIONAL_DATE(lastchangedate,CHG_KEY);
197 GET_OPTIONAL_LONG(mindays,MIN_KEY);
199 GET_OPTIONAL_LONG(maxdays,MAX_KEY);
201 GET_OPTIONAL_LONG(warndays,WRN_KEY);
203 GET_OPTIONAL_LONG(inactdays,INA_KEY);
204 /* get expire date */
205 GET_OPTIONAL_LONG(expiredate,EXP_KEY);
207 GET_OPTIONAL_LONG(flag,FLG_KEY);
208 /* if we're using AD handle the flag specially */
209 if (strcasecmp(cbp->mi->mi_attrs[CHG_KEY].an_desc->ad_cname.bv_val,"pwdLastSet")==0)
211 if (flag&UF_DONT_EXPIRE_PASSWD)
215 /* write the entries */
216 for (i=0;!BER_BVISNULL(&names[i]);i++)
218 WRITE_INT32(cbp->fp,NSLCD_RESULT_SUCCESS);
219 WRITE_BERVAL(cbp->fp,&names[i]);
220 WRITE_BERVAL(cbp->fp,&passwd);
221 WRITE_INT32(cbp->fp,lastchangedate);
222 WRITE_INT32(cbp->fp,mindays);
223 WRITE_INT32(cbp->fp,maxdays);
224 WRITE_INT32(cbp->fp,warndays);
225 WRITE_INT32(cbp->fp,inactdays);
226 WRITE_INT32(cbp->fp,expiredate);
227 WRITE_INT32(cbp->fp,flag);
237 struct berval filter = {sizeof(fbuf)};
238 filter.bv_val = fbuf;
239 READ_STRING_BUF2(fp,cbp.buf,sizeof(cbp.buf));,
240 cbp.name.bv_len = tmpint32;
241 cbp.name.bv_val = cbp.buf;
242 Debug(LDAP_DEBUG_ANY,"nssov_shadow_byname(%s)",cbp.name.bv_val,0,0);,
243 NSLCD_ACTION_SHADOW_BYNAME,
244 nssov_filter_byname(cbp.mi,UID_KEY,&cbp.name,&filter)
249 struct berval filter;
250 /* no parameters to read */
251 BER_BVZERO(&cbp.name);,
252 Debug(LDAP_DEBUG_ANY,"nssov_shadow_all()",0,0,0);,
253 NSLCD_ACTION_SHADOW_ALL,
254 (filter=cbp.mi->mi_filter,0)