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