]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/nssov/nss-ldapd/nslcd/shadow.c
nss overlay
[openldap] / contrib / slapd-modules / nssov / nss-ldapd / nslcd / shadow.c
1 /*
2    shadow.c - service entry lookup routines
3    Parts of this file were part of the nss_ldap library (as ldap-spwd.c)
4    which has been forked into the nss-ldapd library.
5
6    Copyright (C) 1997-2005 Luke Howard
7    Copyright (C) 2006 West Consulting
8    Copyright (C) 2006, 2007, 2008 Arthur de Jong
9
10    This library is free software; you can redistribute it and/or
11    modify it under the terms of the GNU Lesser General Public
12    License as published by the Free Software Foundation; either
13    version 2.1 of the License, or (at your option) any later version.
14
15    This library is distributed in the hope that it will be useful,
16    but WITHOUT ANY WARRANTY; without even the implied warranty of
17    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
18    Lesser General Public License for more details.
19
20    You should have received a copy of the GNU Lesser General Public
21    License along with this library; if not, write to the Free Software
22    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
23    02110-1301 USA
24 */
25
26 #include "config.h"
27
28 #include <stdio.h>
29 #include <stdlib.h>
30 #include <string.h>
31
32 #include "common.h"
33 #include "log.h"
34 #include "myldap.h"
35 #include "cfg.h"
36 #include "attmap.h"
37
38 /* ( nisSchema.2.1 NAME 'shadowAccount' SUP top AUXILIARY
39  *   DESC 'Additional attributes for shadow passwords'
40  *   MUST uid
41  *   MAY ( userPassword $ shadowLastChange $ shadowMin
42  *         shadowMax $ shadowWarning $ shadowInactive $
43  *         shadowExpire $ shadowFlag $ description ) )
44  */
45
46 /* the search base for searches */
47 const char *shadow_base = NULL;
48
49 /* the search scope for searches */
50 int shadow_scope = LDAP_SCOPE_DEFAULT;
51
52 /* the basic search filter for searches */
53 const char *shadow_filter = "(objectClass=shadowAccount)";
54
55 /* the attributes to request with searches */
56 const char *attmap_shadow_uid              = "uid";
57 const char *attmap_shadow_userPassword     = "userPassword";
58 const char *attmap_shadow_shadowLastChange = "shadowLastChange";
59 const char *attmap_shadow_shadowMin        = "shadowMin";
60 const char *attmap_shadow_shadowMax        = "shadowMax";
61 const char *attmap_shadow_shadowWarning    = "shadowWarning";
62 const char *attmap_shadow_shadowInactive   = "shadowInactive";
63 const char *attmap_shadow_shadowExpire     = "shadowExpire";
64 const char *attmap_shadow_shadowFlag       = "shadowFlag";
65
66 /* default values for attributes */
67 static const char *default_shadow_userPassword     = "*"; /* unmatchable */
68 static const char *default_shadow_shadowLastChange = "-1";
69 static const char *default_shadow_shadowMin        = "-1";
70 static const char *default_shadow_shadowMax        = "-1";
71 static const char *default_shadow_shadowWarning    = "-1";
72 static const char *default_shadow_shadowInactive   = "-1";
73 static const char *default_shadow_shadowExpire     = "-1";
74 static const char *default_shadow_shadowFlag       = "0";
75
76 /* the attribute list to request with searches */
77 static const char *shadow_attrs[10];
78
79 static int mkfilter_shadow_byname(const char *name,
80                                   char *buffer,size_t buflen)
81 {
82   char buf2[1024];
83   /* escape attribute */
84   if(myldap_escape(name,buf2,sizeof(buf2)))
85     return -1;
86   /* build filter */
87   return mysnprintf(buffer,buflen,
88                     "(&%s(%s=%s))",
89                     shadow_filter,
90                     attmap_shadow_uid,buf2);
91 }
92
93 static void shadow_init(void)
94 {
95   /* set up base */
96   if (shadow_base==NULL)
97     shadow_base=nslcd_cfg->ldc_base;
98   /* set up scope */
99   if (shadow_scope==LDAP_SCOPE_DEFAULT)
100     shadow_scope=nslcd_cfg->ldc_scope;
101   /* set up attribute list */
102   shadow_attrs[0]=attmap_shadow_uid;
103   shadow_attrs[1]=attmap_shadow_userPassword;
104   shadow_attrs[2]=attmap_shadow_shadowLastChange;
105   shadow_attrs[3]=attmap_shadow_shadowMax;
106   shadow_attrs[4]=attmap_shadow_shadowMin;
107   shadow_attrs[5]=attmap_shadow_shadowWarning;
108   shadow_attrs[6]=attmap_shadow_shadowInactive;
109   shadow_attrs[7]=attmap_shadow_shadowExpire;
110   shadow_attrs[8]=attmap_shadow_shadowFlag;
111   shadow_attrs[9]=NULL;
112 }
113
114 static long to_date(const char *date,const char *attr)
115 {
116   char buffer[8];
117   long value;
118   char *tmp;
119   size_t l;
120   /* do some special handling for date values on AD */
121   if (strcasecmp(attr,"pwdLastSet")==0)
122   {
123     /* we expect an AD 64-bit datetime value;
124        we should do date=date/864000000000-134774
125        but that causes problems on 32-bit platforms,
126        first we devide by 1000000000 by stripping the
127        last 9 digits from the string and going from there */
128     l=strlen(date)-9;
129     if (l>(sizeof(buffer)-1))
130       return 0; /* error */
131     strncpy(buffer,date,l);
132     buffer[l]='\0';
133     value=strtol(date,&tmp,0);
134     if ((*date=='\0')||(*tmp!='\0'))
135     {
136       log_log(LOG_WARNING,"shadow entry contains non-numeric %s value",attr);
137       return 0;
138     }
139     return value/864-134774;
140     /* note that AD does not have expiry dates but a lastchangeddate
141        and some value that needs to be added */
142   }
143   value=strtol(date,&tmp,0);
144   if ((*date=='\0')||(*tmp!='\0'))
145   {
146     log_log(LOG_WARNING,"shadow entry contains non-numeric %s value",attr);
147     return 0;
148   }
149   return value;
150 }
151
152 #ifndef UF_DONT_EXPIRE_PASSWD
153 #define UF_DONT_EXPIRE_PASSWD 0x10000
154 #endif
155
156 #define GET_OPTIONAL_LONG(var,att) \
157   tmpvalues=myldap_get_values(entry,attmap_shadow_##att); \
158   if ((tmpvalues==NULL)||(tmpvalues[0]==NULL)) \
159     var=strtol(default_shadow_##att,NULL,0); \
160   else \
161   { \
162     if (tmpvalues[1]!=NULL) \
163     { \
164       log_log(LOG_WARNING,"shadow entry %s contains multiple %s values", \
165                           myldap_get_dn(entry),attmap_shadow_##att); \
166     } \
167     var=strtol(tmpvalues[0],&tmp,0); \
168     if ((*(tmpvalues[0])=='\0')||(*tmp!='\0')) \
169     { \
170       log_log(LOG_WARNING,"shadow entry %s contains non-numeric %s value", \
171                           myldap_get_dn(entry),attmap_shadow_##att); \
172       return 0; \
173     } \
174   }
175
176 #define GET_OPTIONAL_DATE(var,att) \
177   tmpvalues=myldap_get_values(entry,attmap_shadow_##att); \
178   if ((tmpvalues==NULL)||(tmpvalues[0]==NULL)) \
179     var=to_date(default_shadow_##att,attmap_shadow_##att); \
180   else \
181   { \
182     if (tmpvalues[1]!=NULL) \
183     { \
184       log_log(LOG_WARNING,"shadow entry %s contains multiple %s values", \
185                           myldap_get_dn(entry),attmap_shadow_##att); \
186     } \
187     var=to_date(tmpvalues[0],attmap_shadow_##att); \
188   }
189
190 static int write_shadow(TFILE *fp,MYLDAP_ENTRY *entry,const char *requser)
191 {
192   int32_t tmpint32;
193   const char *tmparr[2];
194   const char **tmpvalues;
195   char *tmp;
196   const char **usernames;
197   const char *passwd;
198   long lastchangedate;
199   long mindays;
200   long maxdays;
201   long warndays;
202   long inactdays;
203   long expiredate;
204   unsigned long flag;
205   int i;
206   /* get username */
207   if (requser!=NULL)
208   {
209     usernames=tmparr;
210     usernames[0]=requser;
211     usernames[1]=NULL;
212   }
213   else
214   {
215     usernames=myldap_get_values(entry,attmap_shadow_uid);
216     if ((usernames==NULL)||(usernames[0]==NULL))
217     {
218       log_log(LOG_WARNING,"passwd entry %s does not contain %s value",
219                           myldap_get_dn(entry),attmap_shadow_uid);
220       return 0;
221     }
222   }
223   /* get password */
224   passwd=get_userpassword(entry,attmap_shadow_userPassword);
225   if (passwd==NULL)
226     passwd=default_shadow_userPassword;
227   /* get lastchange date */
228   GET_OPTIONAL_DATE(lastchangedate,shadowLastChange);
229   /* get mindays */
230   GET_OPTIONAL_LONG(mindays,shadowMin);
231   /* get maxdays */
232   GET_OPTIONAL_LONG(maxdays,shadowMax);
233   /* get warndays */
234   GET_OPTIONAL_LONG(warndays,shadowWarning);
235   /* get inactdays */
236   GET_OPTIONAL_LONG(inactdays,shadowInactive);
237   /* get expire date */
238   GET_OPTIONAL_LONG(expiredate,shadowExpire);
239   /* get flag */
240   GET_OPTIONAL_LONG(flag,shadowFlag);
241   /* if we're using AD handle the flag specially */
242   if (strcasecmp(attmap_shadow_shadowLastChange,"pwdLastSet")==0)
243   {
244     if (flag&UF_DONT_EXPIRE_PASSWD)
245       maxdays=99999;
246     flag=0;
247   }
248   /* write the entries */
249   for (i=0;usernames[i]!=NULL;i++)
250   {
251     WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
252     WRITE_STRING(fp,usernames[i]);
253     WRITE_STRING(fp,passwd);
254     WRITE_INT32(fp,lastchangedate);
255     WRITE_INT32(fp,mindays);
256     WRITE_INT32(fp,maxdays);
257     WRITE_INT32(fp,warndays);
258     WRITE_INT32(fp,inactdays);
259     WRITE_INT32(fp,expiredate);
260     WRITE_INT32(fp,flag);
261   }
262   return 0;
263 }
264
265 NSLCD_HANDLE(
266   shadow,byname,
267   char name[256];
268   char filter[1024];
269   READ_STRING_BUF2(fp,name,sizeof(name));,
270   log_log(LOG_DEBUG,"nslcd_shadow_byname(%s)",name);,
271   NSLCD_ACTION_SHADOW_BYNAME,
272   mkfilter_shadow_byname(name,filter,sizeof(filter)),
273   write_shadow(fp,entry,name)
274 )
275
276 NSLCD_HANDLE(
277   shadow,all,
278   const char *filter;
279   /* no parameters to read */,
280   log_log(LOG_DEBUG,"nslcd_shadow_all()");,
281   NSLCD_ACTION_SHADOW_ALL,
282   (filter=shadow_filter,0),
283   write_shadow(fp,entry,NULL)
284 )