1 /* pam.c - pam processing routines */
3 /* This work is part of OpenLDAP Software <http://www.openldap.org/>.
5 * Copyright 2008-2015 The OpenLDAP Foundation.
6 * Portions Copyright 2008 by Howard Chu, Symas Corp.
7 * Portions Copyright 2013 by Ted C. Cheng, Symas Corp.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted only as authorized by the OpenLDAP
14 * A copy of this license is available in the file LICENSE in the
15 * top-level directory of the distribution or, alternatively, at
16 * <http://www.OpenLDAP.org/license.html>.
22 static int ppolicy_cid;
23 static AttributeDescription *ad_loginStatus;
35 static int pam_bindcb(
36 Operation *op, SlapReply *rs)
38 struct paminfo *pi = op->o_callback->sc_private;
39 LDAPControl *ctrl = ldap_control_find(LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
43 ber_int_t expire, grace;
44 LDAPPasswordPolicyError error;
48 int rc = ldap_parse_passwordpolicy_control(ld,ctrl,
49 &expire,&grace,&error);
50 if (rc == LDAP_SUCCESS) {
52 char *unit = "seconds";
65 #if 0 /* Who warns about expiration so far in advance? */
79 pi->msg.bv_len = sprintf(pi->msg.bv_val,
80 "\nWARNING: Password expires in %d %s\n", expire, unit);
81 } else if (grace > 0) {
82 pi->msg.bv_len = sprintf(pi->msg.bv_val,
83 "Password expired; %d grace logins remaining",
85 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
86 } else if (error != PP_noError) {
87 ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0,
90 case PP_passwordExpired:
91 /* report this during authz */
92 rs->sr_err = LDAP_SUCCESS;
94 case PP_changeAfterReset:
95 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
99 ldap_ld_free(ld,0,NULL,NULL);
105 static int pam_uid2dn(nssov_info *ni, Operation *op,
112 if (!isvalidusername(&pi->uid)) {
113 Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n",
114 pi->uid.bv_val ? pi->uid.bv_val : "NULL",0,0);
115 return NSLCD_PAM_USER_UNKNOWN;
118 if (ni->ni_pam_opts & NI_PAM_SASL2DN) {
119 int hlen = global_host_bv.bv_len;
121 /* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */
122 sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen +
123 STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" );
124 sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx );
125 sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth",
126 pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val);
127 slap_sasl2dn(op, &sdn, &pi->dn, 0);
128 op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx );
131 /* If no luck, do a basic uid search */
132 if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) {
133 nssov_uid2dn(op, ni, &pi->uid, &pi->dn);
134 if (!BER_BVISEMPTY(&pi->dn)) {
136 dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx );
139 if (BER_BVISEMPTY(&pi->dn)) {
140 return NSLCD_PAM_USER_UNKNOWN;
145 int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op,
149 slap_callback cb = {0};
150 SlapReply rs = {REP_RESULT};
152 pi->msg.bv_val = pi->pwd.bv_val;
154 pi->authz = NSLCD_PAM_SUCCESS;
159 rc = pam_uid2dn(ni, op, pi);
162 if (BER_BVISEMPTY(&pi->pwd)) {
163 rc = NSLCD_PAM_PERM_DENIED;
167 /* Should only need to do this once at open time, but there's always
168 * the possibility that ppolicy will get loaded later.
171 rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
174 /* of course, 0 is a valid cid, but it won't be ppolicy... */
176 op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
180 cb.sc_response = pam_bindcb;
182 op->o_callback = &cb;
183 op->o_dn.bv_val[0] = 0;
185 op->o_ndn.bv_val[0] = 0;
186 op->o_ndn.bv_len = 0;
187 op->o_tag = LDAP_REQ_BIND;
188 op->o_protocol = LDAP_VERSION3;
189 op->orb_method = LDAP_AUTH_SIMPLE;
190 op->orb_cred = pi->pwd;
191 op->o_req_dn = pi->dn;
192 op->o_req_ndn = pi->dn;
193 slap_op_time( &op->o_time, &op->o_tincr );
194 rc = op->o_bd->be_bind( op, &rs );
195 memset(pi->pwd.bv_val,0,pi->pwd.bv_len);
196 /* quirk: on successful bind, caller has to send result. we need
197 * to make sure callbacks run.
199 if (rc == LDAP_SUCCESS)
200 send_ldap_result(op, &rs);
202 case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break;
203 case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break;
204 default: rc = NSLCD_PAM_AUTH_ERR; break;
207 Debug(LDAP_DEBUG_ANY,"pam_do_bind (%s): rc (%d)\n",
208 pi->dn.bv_val ? pi->dn.bv_val : "NULL", rc, 0);
212 int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
216 slap_callback cb = {0};
221 struct berval sdn, dn;
225 READ_STRING(fp,uidc);
226 pi.uid.bv_val = uidc;
227 pi.uid.bv_len = tmpint32;
230 pi.dn.bv_len = tmpint32;
231 READ_STRING(fp,svcc);
232 pi.svc.bv_val = svcc;
233 pi.svc.bv_len = tmpint32;
234 READ_STRING(fp,pwdc);
235 pi.pwd.bv_val = pwdc;
236 pi.pwd.bv_len = tmpint32;
238 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",
239 pi.uid.bv_val ? pi.uid.bv_val : "NULL",0,0);
243 /* if service is "passwd" and "nssov-pam-password-prohibit-message */
244 /* is set, deny the auth request */
245 if (!strcmp(svcc, "passwd") &&
246 !BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
247 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(): %s (%s)\n",
248 "password_prohibit_message for passwd",
249 ni->ni_pam_password_prohibit_message.bv_val,0);
250 ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg);
251 pi.authz = NSLCD_PAM_PERM_DENIED;
252 rc = NSLCD_PAM_PERM_DENIED;
256 /* if username is null, pwdmgr password preliminary check */
257 if (BER_BVISEMPTY(&pi.uid)) {
258 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) {
259 /* pwdmgr dn not configured */
260 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
261 "pwdmgr dn not configured", 0, 0);
262 ber_str2bv("pwdmgr dn not configured", 0, 0, &pi.msg);
263 pi.authz = NSLCD_PAM_PERM_DENIED;
264 rc = NSLCD_PAM_PERM_DENIED;
268 ber_str2bv(ni->ni_pam_pwdmgr_dn.bv_val, 0, 0, &pi.dn);
271 /* use pwdmgr pwd if configured */
272 if (BER_BVISEMPTY(&pi.pwd)) {
273 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_pwd)) {
274 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
275 "no pwdmgr pwd", 0, 0);
276 ber_str2bv("pwdmgr pwd not configured", 0, 0, &pi.msg);
277 pi.authz = NSLCD_PAM_PERM_DENIED;
278 rc = NSLCD_PAM_PERM_DENIED;
281 /* use configured pwdmgr pwd */
282 memset((void *) pwdc, 0, 256);
283 strncpy(pi.pwd.bv_val, ni->ni_pam_pwdmgr_pwd.bv_val,
284 ni->ni_pam_pwdmgr_pwd.bv_len);
285 pi.pwd.bv_len = ni->ni_pam_pwdmgr_pwd.bv_len;
291 rc = pam_do_bind(ni, fp, op, &pi);
294 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s): rc (%d)\n",
295 pi.dn.bv_val ? pi.dn.bv_val : "NULL",rc,0);
296 WRITE_INT32(fp,NSLCD_VERSION);
297 WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
298 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
299 WRITE_BERVAL(fp,&pi.uid);
300 WRITE_BERVAL(fp,&pi.dn);
302 WRITE_INT32(fp,pi.authz); /* authz */
303 WRITE_BERVAL(fp,&pi.msg); /* authzmsg */
307 static struct berval grpmsg =
308 BER_BVC("Access denied by group check");
309 static struct berval hostmsg =
310 BER_BVC("Access denied for this host");
311 static struct berval svcmsg =
312 BER_BVC("Access denied for this service");
313 static struct berval uidmsg =
314 BER_BVC("Access denied by UID check");
316 static int pam_compare_cb(Operation *op, SlapReply *rs)
318 if (rs->sr_err == LDAP_COMPARE_TRUE)
319 op->o_callback->sc_private = (void *)1;
323 int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
325 struct berval dn, uid, svc, ruser, rhost, tty;
326 struct berval authzmsg = BER_BVNULL;
337 slap_callback cb = {0};
339 READ_STRING(fp,uidc);
341 uid.bv_len = tmpint32;
344 dn.bv_len = tmpint32;
345 READ_STRING(fp,svcc);
347 svc.bv_len = tmpint32;
348 READ_STRING(fp,ruserc);
349 ruser.bv_val = ruserc;
350 ruser.bv_len = tmpint32;
351 READ_STRING(fp,rhostc);
352 rhost.bv_val = rhostc;
353 rhost.bv_len = tmpint32;
354 READ_STRING(fp,ttyc);
356 tty.bv_len = tmpint32;
358 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",
359 dn.bv_val ? dn.bv_val : "NULL",0,0);
361 /* If we didn't do authc, we don't have a DN yet */
362 if (BER_BVISEMPTY(&dn)) {
367 rc = pam_uid2dn(ni, op, &pi);
372 /* See if they have access to the host and service */
373 if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) {
374 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
375 struct berval hostdn = BER_BVNULL;
376 struct berval odn = op->o_ndn;
377 SlapReply rs = {REP_RESULT};
381 nssov_mapinfo *mi = &ni->ni_maps[NM_host];
383 struct berval filter = {sizeof(fbuf),fbuf};
384 SlapReply rs2 = {REP_RESULT};
386 /* Lookup the host entry */
387 nssov_filter_byname(mi,0,&global_host_bv,&filter);
388 cb.sc_private = &hostdn;
389 cb.sc_response = nssov_name2dn_cb;
390 op->o_callback = &cb;
391 op->o_req_dn = mi->mi_base;
392 op->o_req_ndn = mi->mi_base;
393 op->ors_scope = mi->mi_scope;
394 op->ors_filterstr = filter;
395 op->ors_filter = str2filter_x(op, filter.bv_val);
396 op->ors_attrs = slap_anlist_no_attrs;
397 op->ors_tlimit = SLAP_NO_LIMIT;
399 rc = op->o_bd->be_search(op, &rs2);
400 filter_free_x(op, op->ors_filter, 1);
402 if (BER_BVISEMPTY(&hostdn) &&
403 !BER_BVISEMPTY(&ni->ni_pam_defhost)) {
404 filter.bv_len = sizeof(fbuf);
405 filter.bv_val = fbuf;
406 rs_reinit(&rs2, REP_RESULT);
407 nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter);
408 op->ors_filterstr = filter;
409 op->ors_filter = str2filter_x(op, filter.bv_val);
410 rc = op->o_bd->be_search(op, &rs2);
411 filter_free_x(op, op->ors_filter, 1);
414 /* no host entry, no default host -> deny */
415 if (BER_BVISEMPTY(&hostdn)) {
416 rc = NSLCD_PAM_PERM_DENIED;
422 cb.sc_response = pam_compare_cb;
423 cb.sc_private = NULL;
424 op->o_tag = LDAP_REQ_COMPARE;
425 op->o_req_dn = hostdn;
426 op->o_req_ndn = hostdn;
427 ava.aa_desc = nssov_pam_svc_ad;
430 rc = op->o_bd->be_compare( op, &rs );
431 if ( cb.sc_private == NULL ) {
433 rc = NSLCD_PAM_PERM_DENIED;
440 /* See if they're a member of the group */
441 if ((ni->ni_pam_opts & NI_PAM_USERGRP) &&
442 !BER_BVISEMPTY(&ni->ni_pam_group_dn) &&
443 ni->ni_pam_group_ad) {
444 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
445 SlapReply rs = {REP_RESULT};
446 op->o_callback = &cb;
447 cb.sc_response = pam_compare_cb;
448 cb.sc_private = NULL;
449 op->o_tag = LDAP_REQ_COMPARE;
450 op->o_req_dn = ni->ni_pam_group_dn;
451 op->o_req_ndn = ni->ni_pam_group_dn;
452 ava.aa_desc = ni->ni_pam_group_ad;
455 rc = op->o_bd->be_compare( op, &rs );
456 if ( cb.sc_private == NULL ) {
458 rc = NSLCD_PAM_PERM_DENIED;
463 /* We need to check the user's entry for these bits */
464 if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) ||
465 ni->ni_pam_template_ad ||
466 ni->ni_pam_min_uid || ni->ni_pam_max_uid ) {
467 rc = be_entry_get_rw( op, &dn, NULL, NULL, 0, &e );
468 if (rc != LDAP_SUCCESS) {
469 rc = NSLCD_PAM_USER_UNKNOWN;
473 if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) {
474 a = attr_find(e->e_attrs, nssov_pam_host_ad);
475 if (!a || attr_valfind( a,
476 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
477 SLAP_MR_VALUE_OF_SYNTAX,
478 &global_host_bv, NULL, op->o_tmpmemctx )) {
479 rc = NSLCD_PAM_PERM_DENIED;
484 if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) {
485 a = attr_find(e->e_attrs, nssov_pam_svc_ad);
486 if (!a || attr_valfind( a,
487 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
488 SLAP_MR_VALUE_OF_SYNTAX,
489 &svc, NULL, op->o_tmpmemctx )) {
490 rc = NSLCD_PAM_PERM_DENIED;
499 if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) {
502 nssov_mapinfo *mi = &ni->ni_maps[NM_passwd];
503 a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc);
505 rc = NSLCD_PAM_PERM_DENIED;
509 id = (int)strtol(a->a_vals[0].bv_val,&tmp,0);
510 if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') {
511 rc = NSLCD_PAM_PERM_DENIED;
515 if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) ||
516 (ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) {
517 rc = NSLCD_PAM_PERM_DENIED;
523 if (ni->ni_pam_template_ad) {
524 a = attr_find(e->e_attrs, ni->ni_pam_template_ad);
527 else if (!BER_BVISEMPTY(&ni->ni_pam_template))
528 uid = ni->ni_pam_template;
530 rc = NSLCD_PAM_SUCCESS;
533 WRITE_INT32(fp,NSLCD_VERSION);
534 WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
535 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
536 WRITE_BERVAL(fp,&uid);
537 WRITE_BERVAL(fp,&dn);
539 WRITE_BERVAL(fp,&authzmsg);
541 be_entry_release_r(op, e);
544 case NSLCD_PAM_SUCCESS:
545 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): success\n", 0,0,0);
547 case NSLCD_PAM_PERM_DENIED:
548 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): %s\n",
549 authzmsg.bv_val ? authzmsg.bv_val : "NULL",0,0);
552 Debug(LDAP_DEBUG_TRACE,
553 "nssov_pam_authz(): permission denied, rc (%d)\n",
559 static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action)
561 struct berval dn, uid, svc, tty, rhost, ruser;
569 slap_callback cb = {0};
570 SlapReply rs = {REP_RESULT};
571 char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
572 struct berval timestamp, bv[2], *nbv;
578 READ_STRING(fp,uidc);
580 uid.bv_len = tmpint32;
583 dn.bv_len = tmpint32;
584 READ_STRING(fp,svcc);
586 svc.bv_len = tmpint32;
587 READ_STRING(fp,ttyc);
589 tty.bv_len = tmpint32;
590 READ_STRING(fp,rhostc);
591 rhost.bv_val = rhostc;
592 rhost.bv_len = tmpint32;
593 READ_STRING(fp,ruserc);
594 ruser.bv_val = ruserc;
595 ruser.bv_len = tmpint32;
596 READ_INT32(fp,stamp);
598 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n",
599 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0);
602 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(): %s\n",
603 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', "null DN",0);
608 if (!ni->ni_pam_sessions) {
609 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(): %s\n",
610 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
611 "pam session(s) not configured, ignored",0);
618 for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) {
619 if (ni->ni_pam_sessions[i].bv_len != svc.bv_len)
621 if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) {
627 Debug(LDAP_DEBUG_TRACE,
628 "nssov_pam_sess_%c(): service(%s) not configured, ignored\n",
629 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
636 slap_op_time( &op->o_time, &op->o_tincr );
637 timestamp.bv_len = sizeof(timebuf);
638 timestamp.bv_val = timebuf;
639 if (action == NSLCD_ACTION_PAM_SESS_O )
641 slap_timestamp( &stamp, ×tamp );
642 bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len +
643 tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF(" (@)");
644 bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx );
645 sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)",
646 timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val,
647 ruser.bv_val, rhost.bv_val);
649 Debug(LDAP_DEBUG_TRACE, "nssov_pam_sess_%c(): loginStatus (%s) \n",
650 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', bv[0].bv_val,0);
655 attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx );
656 mod.sml_nvalues = nbv;
657 mod.sml_desc = ad_loginStatus;
658 mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD :
660 mod.sml_flags = SLAP_MOD_INTERNAL;
663 cb.sc_response = slap_null_cb;
664 op->o_callback = &cb;
665 op->o_tag = LDAP_REQ_MODIFY;
666 op->o_dn = op->o_bd->be_rootdn;
667 op->o_ndn = op->o_bd->be_rootndn;
668 op->orm_modlist = &mod;
669 op->orm_no_opattrs = 1;
672 if (op->o_bd->be_modify( op, &rs ) != LDAP_SUCCESS) {
673 Debug(LDAP_DEBUG_TRACE,
674 "nssov_pam_sess_%c(): modify op failed\n",
675 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
680 if ( mod.sml_next ) {
681 slap_mods_free( mod.sml_next, 1 );
683 ber_bvarray_free_x( nbv, op->o_tmpmemctx );
688 Debug(LDAP_DEBUG_TRACE,
689 "nssov_pam_sess_%c(): success\n",
690 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
692 sessionID = op->o_time;
694 WRITE_INT32(fp,NSLCD_VERSION);
695 WRITE_INT32(fp,action);
696 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
697 WRITE_INT32(fp,sessionID);
701 int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op)
703 return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_O);
706 int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op)
708 return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_C);
711 int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op)
723 READ_STRING(fp,uidc);
724 pi.uid.bv_val = uidc;
725 pi.uid.bv_len = tmpint32;
728 pi.dn.bv_len = tmpint32;
729 READ_STRING(fp,svcc);
730 pi.svc.bv_val = svcc;
731 pi.svc.bv_len = tmpint32;
732 READ_STRING(fp,opwc);
733 pi.pwd.bv_val = opwc;
734 pi.pwd.bv_len = tmpint32;
735 READ_STRING(fp,npwc);
737 npw.bv_len = tmpint32;
739 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s\n",
740 pi.dn.bv_val ? pi.dn.bv_val : "NULL",
741 pi.uid.bv_val ? pi.uid.bv_val : "NULL" ,0);
746 /* nssov_pam prohibits password mod */
747 if (!BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
748 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(): %s (%s)\n",
749 "password_prohibit_message",
750 ni->ni_pam_password_prohibit_message.bv_val,0);
751 ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg);
752 rc = NSLCD_PAM_PERM_DENIED;
756 if (BER_BVISEMPTY(&pi.dn)) {
757 /* should not be here at all, pam_authc() should have returned */
759 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
760 "prelim checking failed", 0, 0);
761 ber_str2bv("no pwmod requesting dn", 0, 0, &pi.msg);
762 rc = NSLCD_PAM_PERM_DENIED;
766 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) {
767 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
768 "pwdmgr not configured", 0, 0);
769 ber_str2bv("pwdmgr not configured", 0, 0, &pi.msg);
770 rc = NSLCD_PAM_PERM_DENIED;
772 } else if (!ber_bvcmp(&pi.dn, &ni->ni_pam_pwdmgr_dn)) {
773 /* root user requesting pwmod, convert uid to dn */
775 rc = pam_uid2dn(ni, op, &pi);
777 ber_str2bv("unable to convert uid to dn", 0, 0, &pi.msg);
778 rc = NSLCD_PAM_PERM_DENIED;
783 if (!pi.ispwdmgr && BER_BVISEMPTY(&pi.pwd)) {
784 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
785 "not pwdmgr and old pwd empty", 0, 0);
786 ber_str2bv("must provide old password", 0, 0, &pi.msg);
787 rc = NSLCD_PAM_PERM_DENIED;
791 BerElementBuffer berbuf;
792 BerElement *ber = (BerElement *)&berbuf;
794 SlapReply rs = {REP_RESULT};
795 slap_callback cb = {0};
797 ber_init_w_nullc(ber, LBER_USE_DER);
798 ber_printf(ber, "{");
799 if (!BER_BVISEMPTY(&pi.dn))
800 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
802 /* supply old pwd only when end-user changing pwd */
803 if (pi.ispwdmgr == 0)
804 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
806 if (!BER_BVISEMPTY(&npw))
807 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
809 ber_printf(ber, "N}");
810 ber_flatten2(ber, &bv, 0);
811 op->o_tag = LDAP_REQ_EXTENDED;
812 op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
813 op->ore_reqdata = &bv;
816 /* root user changing end-user passwords */
817 op->o_dn = ni->ni_pam_pwdmgr_dn;
818 op->o_ndn = ni->ni_pam_pwdmgr_dn;
820 /* end-user self-pwd-mod */
824 op->o_callback = &cb;
825 op->o_conn->c_authz_backend = op->o_bd;
826 cb.sc_response = slap_null_cb;
827 op->o_bd = frontendDB;
828 rc = op->o_bd->be_extended(op, &rs);
830 ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
831 if (rc == LDAP_SUCCESS)
832 rc = NSLCD_PAM_SUCCESS;
834 rc = NSLCD_PAM_PERM_DENIED;
837 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), rc (%d)\n", rc, 0, 0);
838 WRITE_INT32(fp,NSLCD_VERSION);
839 WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
840 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
841 WRITE_BERVAL(fp,&pi.uid);
842 WRITE_BERVAL(fp,&pi.dn);
844 WRITE_BERVAL(fp,&pi.msg);
853 code = slap_str2ad("loginStatus", &ad_loginStatus, &text);