]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/nssov/shadow.c
ITS#5801
[openldap] / contrib / slapd-modules / nssov / shadow.c
1 /* shadow.c - shadow account lookup routines */
2 /* $OpenLDAP$ */
3 /*
4  * Copyright 2008 by Howard Chu, Symas Corp.
5  * All rights reserved.
6  *
7  * Redistribution and use in source and binary forms, with or without
8  * modification, are permitted only as authorized by the OpenLDAP
9  * Public License.
10  *
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>.
14  */
15 /*
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.
19  */
20
21 #include "nssov.h"
22
23 /* ( nisSchema.2.1 NAME 'shadowAccount' SUP top AUXILIARY
24  *       DESC 'Additional attributes for shadow passwords'
25  *       MUST uid
26  *       MAY ( userPassword $ shadowLastChange $ shadowMin
27  *                               shadowMax $ shadowWarning $ shadowInactive $
28  *                               shadowExpire $ shadowFlag $ description ) )
29  */
30
31 /* the basic search filter for searches */
32 static struct berval shadow_filter = BER_BVC("(objectClass=shadowAccount)");
33
34 /* the attributes to request with searches */
35 static struct berval shadow_keys[] = {
36         BER_BVC("uid"),
37         BER_BVC("userPassword"),
38         BER_BVC("shadowLastChange"),
39         BER_BVC("shadowMin"),
40         BER_BVC("shadowMax"),
41         BER_BVC("shadowWarning"),
42         BER_BVC("shadowInactive"),
43         BER_BVC("shadowExpire"),
44         BER_BVC("shadowFlag"),
45         BER_BVNULL
46 };
47
48 #define UID_KEY 0
49 #define PWD_KEY 1
50 #define CHG_KEY 2
51 #define MIN_KEY 3
52 #define MAX_KEY 4
53 #define WRN_KEY 5
54 #define INA_KEY 6
55 #define EXP_KEY 7
56 #define FLG_KEY 8
57
58 /* default values for attributes */
59 static struct berval default_shadow_userPassword                 = BER_BVC("*"); /* unmatchable */
60 static int default_nums[] = { 0,0,
61         -1, /* LastChange */
62         -1, /* Min */
63         -1, /* Max */
64         -1, /* Warning */
65         -1, /* Inactive */
66         -1, /* Expire */
67         0 /* Flag */
68 };
69
70 NSSOV_INIT(shadow)
71
72 static long to_date(struct berval *date,AttributeDescription *attr)
73 {
74         long value;
75         char *tmp;
76         /* do some special handling for date values on AD */
77         if (strcasecmp(attr->ad_cname.bv_val,"pwdLastSet")==0)
78         {
79                 char buffer[8];
80                 size_t l;
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 */
86                 l=date->bv_len-9;
87                 if (l<1 || l>(sizeof(buffer)-1))
88                         return 0; /* error */
89                 strncpy(buffer,date->bv_val,l);
90                 buffer[l]='\0';
91                 value=strtol(buffer,&tmp,0);
92                 if ((buffer[0]=='\0')||(*tmp!='\0'))
93                 {
94                         Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value",
95                                 attr->ad_cname.bv_val,0,0);
96                         return 0;
97                 }
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 */
101         }
102         value=strtol(date->bv_val,&tmp,0);
103         if ((date->bv_val[0]=='\0')||(*tmp!='\0'))
104         {
105                 Debug(LDAP_DEBUG_ANY,"shadow entry contains non-numeric %s value",
106                         attr->ad_cname.bv_val,0,0);
107                 return 0;
108         }
109         return value;
110 }
111
112 #ifndef UF_DONT_EXPIRE_PASSWD
113 #define UF_DONT_EXPIRE_PASSWD 0x10000
114 #endif
115
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]; \
120         else \
121         { \
122                 if (a->a_numvals > 1) \
123                 { \
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); \
126                 } \
127                 var=strtol(a->a_vals[0].bv_val,&tmp,0); \
128                 if ((a->a_vals[0].bv_val[0]=='\0')||(*tmp!='\0')) \
129                 { \
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); \
132                         return 0; \
133                 } \
134         }
135
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]; \
140         else \
141         { \
142                 if (a->a_numvals > 1) \
143                 { \
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); \
146                 } \
147                 var=to_date(&a->a_vals[0],cbp->mi->mi_attrs[key].an_desc); \
148         }
149
150 NSSOV_CBPRIV(shadow,
151         char buf[256];
152         struct berval name;);
153
154 static int write_shadow(nssov_shadow_cbp *cbp,Entry *entry)
155 {
156         struct berval tmparr[2];
157         struct berval *names;
158         Attribute *a;
159         char *tmp;
160         struct berval passwd = {0};
161         long lastchangedate;
162         long mindays;
163         long maxdays;
164         long warndays;
165         long inactdays;
166         long expiredate;
167         unsigned long flag;
168         int i;
169         int32_t tmpint32;
170         /* get username */
171         if (BER_BVISNULL(&cbp->name))
172         {
173                 a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[UID_KEY].an_desc);
174                 if (!a)
175                 {
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);
178                         return 0;
179                 }
180                 names = a->a_vals;
181         }
182         else
183         {
184                 names=tmparr;
185                 names[0]=cbp->name;
186                 BER_BVZERO(&names[1]);
187         }
188         /* get password */
189         a = attr_find(entry->e_attrs, cbp->mi->mi_attrs[PWD_KEY].an_desc);
190         if ( a )
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);
196         /* get mindays */
197         GET_OPTIONAL_LONG(mindays,MIN_KEY);
198         /* get maxdays */
199         GET_OPTIONAL_LONG(maxdays,MAX_KEY);
200         /* get warndays */
201         GET_OPTIONAL_LONG(warndays,WRN_KEY);
202         /* get inactdays */
203         GET_OPTIONAL_LONG(inactdays,INA_KEY);
204         /* get expire date */
205         GET_OPTIONAL_LONG(expiredate,EXP_KEY);
206         /* get flag */
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)
210         {
211                 if (flag&UF_DONT_EXPIRE_PASSWD)
212                         maxdays=99999;
213                 flag=0;
214         }
215         /* write the entries */
216         for (i=0;!BER_BVISNULL(&names[i]);i++)
217         {
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);
228         }
229         return 0;
230 }
231
232 NSSOV_CB(shadow)
233
234 NSSOV_HANDLE(
235         shadow,byname,
236         char fbuf[1024];
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)
245 )
246
247 NSSOV_HANDLE(
248         shadow,all,
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)
255 )