]> git.sur5r.net Git - openldap/blob - contrib/slapd-modules/nssov/pam.c
Fix compare checking in pam_authz
[openldap] / contrib / slapd-modules / nssov / pam.c
1 /* pam.c - pam processing routines */
2 /* $OpenLDAP$ */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 
4  *
5  * Copyright 2008-2009 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
18 #include "nssov.h"
19 #include "lutil.h"
20
21 static int ppolicy_cid;
22 static AttributeDescription *ad_loginStatus;
23
24 struct paminfo {
25         struct berval uid;
26         struct berval dn;
27         struct berval svc;
28         struct berval pwd;
29         int authz;
30         struct berval msg;
31 };
32
33 static int pam_bindcb(
34         Operation *op, SlapReply *rs)
35 {
36         struct paminfo *pi = op->o_callback->sc_private;
37         LDAPControl *ctrl = ldap_control_find(LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
38                 rs->sr_ctrls, NULL);
39         if (ctrl) {
40                 LDAP *ld;
41                 ber_int_t expire, grace;
42                 LDAPPasswordPolicyError error;
43
44                 ldap_create(&ld);
45                 if (ld) {
46                         int rc = ldap_parse_passwordpolicy_control(ld,ctrl,
47                                 &expire,&grace,&error);
48                         if (rc == LDAP_SUCCESS) {
49                                 if (expire >= 0) {
50                                         char *unit = "seconds";
51                                         if (expire > 60) {
52                                                 expire /= 60;
53                                                 unit = "minutes";
54                                         }
55                                         if (expire > 60) {
56                                                 expire /= 60;
57                                                 unit = "hours";
58                                         }
59                                         if (expire > 24) {
60                                                 expire /= 24;
61                                                 unit = "days";
62                                         }
63 #if 0   /* Who warns about expiration so far in advance? */
64                                         if (expire > 7) {
65                                                 expire /= 7;
66                                                 unit = "weeks";
67                                         }
68                                         if (expire > 4) {
69                                                 expire /= 4;
70                                                 unit = "months";
71                                         }
72                                         if (expire > 12) {
73                                                 expire /= 12;
74                                                 unit = "years";
75                                         }
76 #endif
77                                         pi->msg.bv_len = sprintf(pi->msg.bv_val,
78                                                 "\nWARNING: Password expires in %d %s\n", expire, unit);
79                                 } else if (grace > 0) {
80                                         pi->msg.bv_len = sprintf(pi->msg.bv_val,
81                                                 "Password expired; %d grace logins remaining",
82                                                 grace);
83                                         pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
84                                 } else if (error != PP_noError) {
85                                         ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0,
86                                                 &pi->msg);
87                                         switch (error) {
88                                         case PP_passwordExpired:
89                                                 /* report this during authz */
90                                                 rs->sr_err = LDAP_SUCCESS;
91                                                 /* fallthru */
92                                         case PP_changeAfterReset:
93                                                 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
94                                         }
95                                 }
96                         }
97                         ldap_ld_free(ld,0,NULL,NULL);
98                 }
99         }
100         return LDAP_SUCCESS;
101 }
102
103 static int pam_uid2dn(nssov_info *ni, Operation *op,
104         struct paminfo *pi)
105 {
106         struct berval sdn;
107
108         BER_BVZERO(&pi->dn);
109
110         if (!isvalidusername(&pi->uid)) {
111                 Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n",
112                         pi->uid.bv_val,0,0);
113                 return NSLCD_PAM_USER_UNKNOWN;
114         }
115
116         if (ni->ni_pam_opts & NI_PAM_SASL2DN) {
117                 int hlen = global_host_bv.bv_len;
118
119                 /* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */
120                 sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen +
121                         STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" );
122                 sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx );
123                 sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth",
124                         pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val);
125                 slap_sasl2dn(op, &sdn, &pi->dn, 0);
126                 op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx );
127         }
128
129         /* If no luck, do a basic uid search */
130         if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) {
131                 nssov_uid2dn(op, ni, &pi->uid, &pi->dn);
132                 if (!BER_BVISEMPTY(&pi->dn)) {
133                         sdn = pi->dn;
134                         dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx );
135                 }
136         }
137         if (BER_BVISEMPTY(&pi->dn)) {
138                 return NSLCD_PAM_USER_UNKNOWN;
139         }
140         return 0;
141 }
142
143 int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op,
144         struct paminfo *pi)
145 {
146         int rc;
147         slap_callback cb = {0};
148         SlapReply rs = {REP_RESULT};
149
150         pi->msg.bv_val = pi->pwd.bv_val;
151         pi->msg.bv_len = 0;
152         pi->authz = NSLCD_PAM_SUCCESS;
153         BER_BVZERO(&pi->dn);
154
155         rc = pam_uid2dn(ni, op, pi);
156         if (rc) goto finish;
157
158         if (BER_BVISEMPTY(&pi->pwd)) {
159                 rc = NSLCD_PAM_IGNORE;
160                 goto finish;
161         }
162
163         /* Should only need to do this once at open time, but there's always
164          * the possibility that ppolicy will get loaded later.
165          */
166         if (!ppolicy_cid) {
167                 rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
168                         &ppolicy_cid);
169         }
170         /* of course, 0 is a valid cid, but it won't be ppolicy... */
171         if (ppolicy_cid) {
172                 op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
173         }
174         cb.sc_response = pam_bindcb;
175         cb.sc_private = pi;
176         op->o_callback = &cb;
177         op->o_dn.bv_val[0] = 0;
178         op->o_dn.bv_len = 0;
179         op->o_ndn.bv_val[0] = 0;
180         op->o_ndn.bv_len = 0;
181         op->o_tag = LDAP_REQ_BIND;
182         op->o_protocol = LDAP_VERSION3;
183         op->orb_method = LDAP_AUTH_SIMPLE;
184         op->orb_cred = pi->pwd;
185         op->o_req_dn = pi->dn;
186         op->o_req_ndn = pi->dn;
187         slap_op_time( &op->o_time, &op->o_tincr );
188         rc = op->o_bd->be_bind( op, &rs );
189         memset(pi->pwd.bv_val,0,pi->pwd.bv_len);
190         /* quirk: on successful bind, caller has to send result. we need
191          * to make sure callbacks run.
192          */
193         if (rc == LDAP_SUCCESS)
194                 send_ldap_result(op, &rs);
195         switch(rs.sr_err) {
196         case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break;
197         case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break;
198         default: rc = NSLCD_PAM_AUTH_ERR; break;
199         }
200 finish:
201         return rc;
202 }
203
204 int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
205 {
206         int32_t tmpint32;
207         int rc;
208         slap_callback cb = {0};
209         SlapReply rs = {REP_RESULT};
210         char dnc[1024];
211         char uidc[32];
212         char svcc[256];
213         char pwdc[256];
214         struct berval sdn, dn;
215         struct paminfo pi;
216
217
218         READ_STRING_BUF2(fp,uidc,sizeof(uidc));
219         pi.uid.bv_val = uidc;
220         pi.uid.bv_len = tmpint32;
221         READ_STRING_BUF2(fp,dnc,sizeof(dnc));
222         pi.dn.bv_val = dnc;
223         pi.dn.bv_len = tmpint32;
224         READ_STRING_BUF2(fp,svcc,sizeof(svcc));
225         pi.svc.bv_val = svcc;
226         pi.svc.bv_len = tmpint32;
227         READ_STRING_BUF2(fp,pwdc,sizeof(pwdc));
228         pi.pwd.bv_val = pwdc;
229         pi.pwd.bv_len = tmpint32;
230
231         Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",pi.uid.bv_val,0,0);
232
233         rc = pam_do_bind(ni, fp, op, &pi);
234
235 finish:
236         WRITE_INT32(fp,NSLCD_VERSION);
237         WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
238         WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
239         WRITE_BERVAL(fp,&pi.uid);
240         WRITE_BERVAL(fp,&pi.dn);
241         WRITE_INT32(fp,rc);
242         WRITE_INT32(fp,pi.authz);       /* authz */
243         WRITE_BERVAL(fp,&pi.msg);       /* authzmsg */
244         return 0;
245 }
246
247 static struct berval grpmsg =
248         BER_BVC("Access denied by group check");
249 static struct berval hostmsg =
250         BER_BVC("Access denied for this host");
251 static struct berval svcmsg =
252         BER_BVC("Access denied for this service");
253 static struct berval uidmsg =
254         BER_BVC("Access denied by UID check");
255
256 static int pam_compare_cb(Operation *op, SlapReply *rs)
257 {
258         if (rs->sr_err == LDAP_COMPARE_TRUE)
259                 op->o_callback->sc_private = (void *)1;
260         return LDAP_SUCCESS;
261 }
262
263 int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
264 {
265         struct berval dn, uid, svc, ruser, rhost, tty;
266         struct berval authzmsg = BER_BVNULL;
267         int32_t tmpint32;
268         char dnc[1024];
269         char uidc[32];
270         char svcc[256];
271         char ruserc[32];
272         char rhostc[256];
273         char ttyc[256];
274         int rc;
275         Entry *e = NULL;
276         Attribute *a;
277         SlapReply rs = {REP_RESULT};
278         slap_callback cb = {0};
279
280         READ_STRING_BUF2(fp,uidc,sizeof(uidc));
281         uid.bv_val = uidc;
282         uid.bv_len = tmpint32;
283         READ_STRING_BUF2(fp,dnc,sizeof(dnc));
284         dn.bv_val = dnc;
285         dn.bv_len = tmpint32;
286         READ_STRING_BUF2(fp,svcc,sizeof(svcc));
287         svc.bv_val = svcc;
288         svc.bv_len = tmpint32;
289         READ_STRING_BUF2(fp,ruserc,sizeof(ruserc));
290         ruser.bv_val = ruserc;
291         ruser.bv_len = tmpint32;
292         READ_STRING_BUF2(fp,rhostc,sizeof(rhostc));
293         rhost.bv_val = rhostc;
294         rhost.bv_len = tmpint32;
295         READ_STRING_BUF2(fp,ttyc,sizeof(ttyc));
296         tty.bv_val = ttyc;
297         tty.bv_len = tmpint32;
298
299         Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0);
300
301         /* If we didn't do authc, we don't have a DN yet */
302         if (BER_BVISEMPTY(&dn)) {
303                 struct paminfo pi;
304                 pi.uid = uid;
305                 pi.svc = svc;
306
307                 rc = pam_uid2dn(ni, op, &pi);
308                 if (rc) goto finish;
309                 dn = pi.dn;
310         }
311
312         /* See if they have access to the host and service */
313         if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) {
314                 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
315                 struct berval hostdn = BER_BVNULL;
316                 struct berval odn = op->o_ndn;
317                 op->o_dn = dn;
318                 op->o_ndn = dn;
319                 {
320                         nssov_mapinfo *mi = &ni->ni_maps[NM_host];
321                         char fbuf[1024];
322                         struct berval filter = {sizeof(fbuf),fbuf};
323                         SlapReply rs2 = {REP_RESULT};
324
325                         /* Lookup the host entry */
326                         nssov_filter_byname(mi,0,&global_host_bv,&filter);
327                         cb.sc_private = &hostdn;
328                         cb.sc_response = nssov_name2dn_cb;
329                         op->o_callback = &cb;
330                         op->o_req_dn = mi->mi_base;
331                         op->o_req_ndn = mi->mi_base;
332                         op->ors_scope = mi->mi_scope;
333                         op->ors_filterstr = filter;
334                         op->ors_filter = str2filter_x(op, filter.bv_val);
335                         op->ors_attrs = slap_anlist_no_attrs;
336                         op->ors_tlimit = SLAP_NO_LIMIT;
337                         op->ors_slimit = 2;
338                         rc = op->o_bd->be_search(op, &rs2);
339                         filter_free_x(op, op->ors_filter, 1);
340
341                         if (BER_BVISEMPTY(&hostdn) &&
342                                 !BER_BVISEMPTY(&ni->ni_pam_defhost)) {
343                                 filter.bv_len = sizeof(fbuf);
344                                 filter.bv_val = fbuf;
345                                 memset(&rs2, 0, sizeof(rs2));
346                                 rs2.sr_type = REP_RESULT;
347                                 nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter);
348                                 op->ors_filterstr = filter;
349                                 op->ors_filter = str2filter_x(op, filter.bv_val);
350                                 rc = op->o_bd->be_search(op, &rs2);
351                                 filter_free_x(op, op->ors_filter, 1);
352                         }
353
354                         /* no host entry, no default host -> deny */
355                         if (BER_BVISEMPTY(&hostdn)) {
356                                 rc = NSLCD_PAM_PERM_DENIED;
357                                 authzmsg = hostmsg;
358                                 goto finish;
359                         }
360                 }
361
362                 cb.sc_response = pam_compare_cb;
363                 cb.sc_private = NULL;
364                 op->o_tag = LDAP_REQ_COMPARE;
365                 op->o_req_dn = hostdn;
366                 op->o_req_ndn = hostdn;
367                 ava.aa_desc = nssov_pam_svc_ad;
368                 ava.aa_value = svc;
369                 op->orc_ava = &ava;
370                 rc = op->o_bd->be_compare( op, &rs );
371                 if ( cb.sc_private == NULL ) {
372                         authzmsg = svcmsg;
373                         rc = NSLCD_PAM_PERM_DENIED;
374                         goto finish;
375                 }
376                 op->o_dn = odn;
377                 op->o_ndn = odn;
378         }
379
380         /* See if they're a member of the group */
381         if ((ni->ni_pam_opts & NI_PAM_USERGRP) &&
382                 !BER_BVISEMPTY(&ni->ni_pam_group_dn) &&
383                 ni->ni_pam_group_ad) {
384                 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
385                 op->o_callback = &cb;
386                 cb.sc_response = slap_null_cb;
387                 op->o_tag = LDAP_REQ_COMPARE;
388                 op->o_req_dn = ni->ni_pam_group_dn;
389                 op->o_req_ndn = ni->ni_pam_group_dn;
390                 ava.aa_desc = ni->ni_pam_group_ad;
391                 ava.aa_value = dn;
392                 op->orc_ava = &ava;
393                 rc = op->o_bd->be_compare( op, &rs );
394                 if ( rs.sr_err != LDAP_COMPARE_TRUE ) {
395                         authzmsg = grpmsg;
396                         rc = NSLCD_PAM_PERM_DENIED;
397                         goto finish;
398                 }
399         }
400
401         /* We need to check the user's entry for these bits */
402         if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) ||
403                 ni->ni_pam_template_ad ||
404                 ni->ni_pam_min_uid || ni->ni_pam_max_uid ) {
405                 rc = be_entry_get_rw( op, &dn, NULL, NULL, 0, &e );
406                 if (rc != LDAP_SUCCESS) {
407                         rc = NSLCD_PAM_USER_UNKNOWN;
408                         goto finish;
409                 }
410         }
411         if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) {
412                 a = attr_find(e->e_attrs, nssov_pam_host_ad);
413                 if (!a || attr_valfind( a,
414                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
415                         SLAP_MR_VALUE_OF_SYNTAX,
416                         &global_host_bv, NULL, op->o_tmpmemctx )) {
417                         rc = NSLCD_PAM_PERM_DENIED;
418                         authzmsg = hostmsg;
419                         goto finish;
420                 }
421         }
422         if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) {
423                 a = attr_find(e->e_attrs, nssov_pam_svc_ad);
424                 if (!a || attr_valfind( a,
425                         SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
426                         SLAP_MR_VALUE_OF_SYNTAX,
427                         &svc, NULL, op->o_tmpmemctx )) {
428                         rc = NSLCD_PAM_PERM_DENIED;
429                         authzmsg = svcmsg;
430                         goto finish;
431                 }
432         }
433
434 /* from passwd.c */
435 #define UIDN_KEY        2
436
437         if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) {
438                 int id;
439                 char *tmp;
440                 nssov_mapinfo *mi = &ni->ni_maps[NM_passwd];
441                 a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc);
442                 if (!a) {
443                         rc = NSLCD_PAM_PERM_DENIED;
444                         authzmsg = uidmsg;
445                         goto finish;
446                 }
447                 id = (int)strtol(a->a_vals[0].bv_val,&tmp,0);
448                 if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') {
449                         rc = NSLCD_PAM_PERM_DENIED;
450                         authzmsg = uidmsg;
451                         goto finish;
452                 }
453                 if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) ||
454                         (ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) {
455                         rc = NSLCD_PAM_PERM_DENIED;
456                         authzmsg = uidmsg;
457                         goto finish;
458                 }
459         }
460
461         if (ni->ni_pam_template_ad) {
462                 a = attr_find(e->e_attrs, ni->ni_pam_template_ad);
463                 if (a)
464                         uid = a->a_vals[0];
465                 else if (!BER_BVISEMPTY(&ni->ni_pam_template))
466                         uid = ni->ni_pam_template;
467         }
468         rc = NSLCD_PAM_SUCCESS;
469
470 finish:
471         WRITE_INT32(fp,NSLCD_VERSION);
472         WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
473         WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
474         WRITE_BERVAL(fp,&uid);
475         WRITE_BERVAL(fp,&dn);
476         WRITE_INT32(fp,rc);
477         WRITE_BERVAL(fp,&authzmsg);
478         if (e) {
479                 be_entry_release_r(op, e);
480         }
481         return 0;
482 }
483
484 static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action)
485 {
486         struct berval dn, uid, svc, tty, rhost, ruser;
487         int32_t tmpint32;
488         char dnc[1024];
489         char svcc[256];
490         char uidc[32];
491         char ttyc[32];
492         char rhostc[256];
493         char ruserc[32];
494         slap_callback cb = {0};
495         SlapReply rs = {REP_RESULT};
496         char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
497         struct berval timestamp, bv[2], *nbv;
498         time_t stamp;
499         Modifications mod;
500
501         READ_STRING_BUF2(fp,uidc,sizeof(uidc));
502         uid.bv_val = uidc;
503         uid.bv_len = tmpint32;
504         READ_STRING_BUF2(fp,dnc,sizeof(dnc));
505         dn.bv_val = dnc;
506         dn.bv_len = tmpint32;
507         READ_STRING_BUF2(fp,svcc,sizeof(svcc));
508         svc.bv_val = svcc;
509         svc.bv_len = tmpint32;
510         READ_STRING_BUF2(fp,ttyc,sizeof(ttyc));
511         tty.bv_val = ttyc;
512         tty.bv_len = tmpint32;
513         READ_STRING_BUF2(fp,rhostc,sizeof(rhostc));
514         rhost.bv_val = rhostc;
515         rhost.bv_len = tmpint32;
516         READ_STRING_BUF2(fp,ruserc,sizeof(ruserc));
517         ruser.bv_val = ruserc;
518         ruser.bv_len = tmpint32;
519         READ_INT32(fp,stamp);
520
521         Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n",
522                 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0);
523
524         if (!dn.bv_len || !ni->ni_pam_sessions) return 0;
525
526         {
527                 int i, found=0;
528                 for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) {
529                         if (ni->ni_pam_sessions[i].bv_len != svc.bv_len)
530                                 continue;
531                         if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) {
532                                 found = 1;
533                                 break;
534                         }
535                 }
536                 if (!found) return 0;
537         }
538
539         slap_op_time( &op->o_time, &op->o_tincr );
540         timestamp.bv_len = sizeof(timebuf);
541         timestamp.bv_val = timebuf;
542         if (action == NSLCD_ACTION_PAM_SESS_O )
543                 stamp = op->o_time;
544         slap_timestamp( &stamp, &timestamp );
545         bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len +
546                 tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF("    (@)");
547         bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx );
548         sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)",
549                 timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val,
550                 ruser.bv_val, rhost.bv_val);
551         
552         mod.sml_numvals = 1;
553         mod.sml_values = bv;
554         BER_BVZERO(&bv[1]);
555         attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx );
556         mod.sml_nvalues = nbv;
557         mod.sml_desc = ad_loginStatus;
558         mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD :
559                 LDAP_MOD_DELETE;
560         mod.sml_flags = SLAP_MOD_INTERNAL;
561         mod.sml_next = NULL;
562
563         cb.sc_response = slap_null_cb;
564         op->o_callback = &cb;
565         op->o_tag = LDAP_REQ_MODIFY;
566         op->o_dn = op->o_bd->be_rootdn;
567         op->o_ndn = op->o_bd->be_rootndn;
568         op->orm_modlist = &mod;
569         op->orm_no_opattrs = 1;
570         op->o_req_dn = dn;
571         op->o_req_ndn = dn;
572         op->o_bd->be_modify( op, &rs );
573         if ( mod.sml_next ) {
574                 slap_mods_free( mod.sml_next, 1 );
575         }
576         ber_bvarray_free_x( nbv, op->o_tmpmemctx );
577
578         WRITE_INT32(fp,NSLCD_VERSION);
579         WRITE_INT32(fp,action);
580         WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
581         WRITE_INT32(fp,op->o_time);
582         return 0;
583 }
584
585 int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op)
586 {
587         return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_O);
588 }
589
590 int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op)
591 {
592         return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_C);
593 }
594
595 int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op)
596 {
597         struct berval npw;
598         int32_t tmpint32;
599         char dnc[1024];
600         char uidc[32];
601         char opwc[256];
602         char npwc[256];
603         char svcc[256];
604         struct paminfo pi;
605         int rc;
606
607         READ_STRING_BUF2(fp,uidc,sizeof(uidc));
608         pi.uid.bv_val = uidc;
609         pi.uid.bv_len = tmpint32;
610         READ_STRING_BUF2(fp,dnc,sizeof(dnc));
611         pi.dn.bv_val = dnc;
612         pi.dn.bv_len = tmpint32;
613         READ_STRING_BUF2(fp,svcc,sizeof(svcc));
614         pi.svc.bv_val = svcc;
615         pi.svc.bv_len = tmpint32;
616         READ_STRING_BUF2(fp,opwc,sizeof(opwc));
617         pi.pwd.bv_val = opwc;
618         pi.pwd.bv_len = tmpint32;
619         READ_STRING_BUF2(fp,npwc,sizeof(npwc));
620         npw.bv_val = npwc;
621         npw.bv_len = tmpint32;
622
623         Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s\n",
624                 pi.dn.bv_val,pi.uid.bv_val,0);
625
626         BER_BVZERO(&pi.msg);
627
628         /* This is a prelim check */
629         if (BER_BVISEMPTY(&pi.dn)) {
630                 rc = pam_do_bind(ni,fp,op,&pi);
631                 if (rc == NSLCD_PAM_IGNORE)
632                         rc = NSLCD_PAM_SUCCESS;
633         } else {
634                 BerElementBuffer berbuf;
635                 BerElement *ber = (BerElement *)&berbuf;
636                 struct berval bv;
637                 SlapReply rs = {REP_RESULT};
638                 slap_callback cb = {0};
639
640                 ber_init_w_nullc(ber, LBER_USE_DER);
641                 ber_printf(ber, "{");
642                 if (!BER_BVISEMPTY(&pi.pwd))
643                         ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
644                                 &pi.pwd);
645                 if (!BER_BVISEMPTY(&npw))
646                         ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
647                                 &npw);
648                 ber_printf(ber, "N}");
649                 ber_flatten2(ber, &bv, 0);
650                 op->o_tag = LDAP_REQ_EXTENDED;
651                 op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
652                 op->ore_reqdata = &bv;
653                 op->o_dn = pi.dn;
654                 op->o_ndn = pi.dn;
655                 op->o_callback = &cb;
656                 op->o_conn->c_authz_backend = op->o_bd;
657                 cb.sc_response = slap_null_cb;
658                 op->o_bd = frontendDB;
659                 rc = op->o_bd->be_extended(op, &rs);
660                 if (rs.sr_text)
661                         ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
662                 if (rc == LDAP_SUCCESS)
663                         rc = NSLCD_PAM_SUCCESS;
664                 else
665                         rc = NSLCD_PAM_PERM_DENIED;
666         }
667         WRITE_INT32(fp,NSLCD_VERSION);
668         WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
669         WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
670         WRITE_BERVAL(fp,&pi.uid);
671         WRITE_BERVAL(fp,&pi.dn);
672         WRITE_INT32(fp,rc);
673         WRITE_BERVAL(fp,&pi.msg);
674         return 0;
675 }
676
677 int nssov_pam_init()
678 {
679         int code = 0;
680         const char *text;
681         if (!ad_loginStatus)
682                 code = slap_str2ad("loginStatus", &ad_loginStatus, &text);
683
684         return code;
685 }