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;
38 static int pam_bindcb(
39 Operation *op, SlapReply *rs)
41 struct paminfo *pi = op->o_callback->sc_private;
42 LDAPControl *ctrl = ldap_control_find(LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
46 ber_int_t expire, grace;
47 LDAPPasswordPolicyError error;
51 int rc = ldap_parse_passwordpolicy_control(ld,ctrl,
52 &expire,&grace,&error);
53 if (rc == LDAP_SUCCESS) {
55 char *unit = "seconds";
68 #if 0 /* Who warns about expiration so far in advance? */
82 pi->msg.bv_len = sprintf(pi->msg.bv_val,
83 "\nWARNING: Password expires in %d %s\n", expire, unit);
84 } else if (grace > 0) {
85 pi->msg.bv_len = sprintf(pi->msg.bv_val,
86 "Password expired; %d grace logins remaining",
88 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
89 } else if (error != PP_noError) {
90 ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0,
93 case PP_passwordExpired:
94 /* report this during authz */
95 rs->sr_err = LDAP_SUCCESS;
97 case PP_changeAfterReset:
98 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
102 ldap_ld_free(ld,0,NULL,NULL);
108 static int pam_uid2dn(nssov_info *ni, Operation *op,
115 if (!isvalidusername(&pi->uid)) {
116 Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n",
117 pi->uid.bv_val ? pi->uid.bv_val : "NULL",0,0);
118 return NSLCD_PAM_USER_UNKNOWN;
121 if (ni->ni_pam_opts & NI_PAM_SASL2DN) {
122 int hlen = global_host_bv.bv_len;
124 /* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */
125 sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen +
126 STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" );
127 sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx );
128 sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth",
129 pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val);
130 slap_sasl2dn(op, &sdn, &pi->dn, 0);
131 op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx );
134 /* If no luck, do a basic uid search */
135 if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) {
136 nssov_uid2dn(op, ni, &pi->uid, &pi->dn);
137 if (!BER_BVISEMPTY(&pi->dn)) {
139 dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx );
142 if (BER_BVISEMPTY(&pi->dn)) {
143 return NSLCD_PAM_USER_UNKNOWN;
148 int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op,
152 slap_callback cb = {0};
153 SlapReply rs = {REP_RESULT};
155 pi->msg.bv_val = pi->pwd.bv_val;
157 pi->authz = NSLCD_PAM_SUCCESS;
161 rc = pam_uid2dn(ni, op, pi);
164 if (BER_BVISEMPTY(&pi->pwd)) {
165 rc = NSLCD_PAM_PERM_DENIED;
169 /* Should only need to do this once at open time, but there's always
170 * the possibility that ppolicy will get loaded later.
173 rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
176 /* of course, 0 is a valid cid, but it won't be ppolicy... */
178 op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
182 cb.sc_response = pam_bindcb;
184 op->o_callback = &cb;
185 op->o_dn.bv_val[0] = 0;
187 op->o_ndn.bv_val[0] = 0;
188 op->o_ndn.bv_len = 0;
189 op->o_tag = LDAP_REQ_BIND;
190 op->o_protocol = LDAP_VERSION3;
191 op->orb_method = LDAP_AUTH_SIMPLE;
192 op->orb_cred = pi->pwd;
193 op->o_req_dn = pi->dn;
194 op->o_req_ndn = pi->dn;
195 slap_op_time( &op->o_time, &op->o_tincr );
196 rc = op->o_bd->be_bind( op, &rs );
197 memset(pi->pwd.bv_val,0,pi->pwd.bv_len);
198 /* quirk: on successful bind, caller has to send result. we need
199 * to make sure callbacks run.
201 if (rc == LDAP_SUCCESS)
202 send_ldap_result(op, &rs);
204 case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break;
205 case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break;
206 default: rc = NSLCD_PAM_AUTH_ERR; break;
209 Debug(LDAP_DEBUG_ANY,"pam_do_bind (%s): rc (%d)\n",
210 pi->dn.bv_val ? pi->dn.bv_val : "NULL", rc, 0);
214 int pam_authc(nssov_info *ni,TFILE *fp,Operation *op,uid_t calleruid)
227 READ_STRING(fp,uidc);
228 pi.uid.bv_val = uidc;
229 pi.uid.bv_len = tmpint32;
230 READ_STRING(fp,svcc);
231 pi.svc.bv_val = svcc;
232 pi.svc.bv_len = tmpint32;
233 READ_STRING(fp,ruserc);
234 pi.ruser.bv_val = ruserc;
235 pi.ruser.bv_len = tmpint32;
236 READ_STRING(fp,rhostc);
237 pi.rhost.bv_val = rhostc;
238 pi.rhost.bv_len = tmpint32;
239 READ_STRING(fp,ttyc);
240 pi.tty.bv_val = ttyc;
241 pi.tty.bv_len = tmpint32;
242 READ_STRING(fp,pwdc);
243 pi.pwd.bv_val = pwdc;
244 pi.pwd.bv_len = tmpint32;
246 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",
247 pi.uid.bv_val ? pi.uid.bv_val : "NULL",0,0);
252 /* if service is "passwd" and "nssov-pam-password-prohibit-message */
253 /* is set, deny the auth request */
254 if (!strcmp(svcc, "passwd") &&
255 !BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
256 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(): %s (%s)\n",
257 "password_prohibit_message for passwd",
258 ni->ni_pam_password_prohibit_message.bv_val,0);
259 ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg);
260 pi.authz = NSLCD_PAM_PERM_DENIED;
261 rc = NSLCD_PAM_PERM_DENIED;
265 /* if username is null, pwdmgr password preliminary check */
266 if (BER_BVISEMPTY(&pi.uid)) {
267 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) {
268 /* pwdmgr dn not configured */
269 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
270 "pwdmgr dn not configured", 0, 0);
271 ber_str2bv("pwdmgr dn not configured", 0, 0, &pi.msg);
272 pi.authz = NSLCD_PAM_PERM_DENIED;
273 rc = NSLCD_PAM_PERM_DENIED;
275 } else if (calleruid != 0) {
276 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
277 "caller is not root", 0, 0);
278 ber_str2bv("only root may do that", 0, 0, &pi.msg);
279 pi.authz = NSLCD_PAM_PERM_DENIED;
280 rc = NSLCD_PAM_PERM_DENIED;
284 ber_str2bv(ni->ni_pam_pwdmgr_dn.bv_val, 0, 0, &pi.dn);
287 /* use pwdmgr pwd if configured */
288 if (BER_BVISEMPTY(&pi.pwd)) {
289 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_pwd)) {
290 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n",
291 "no pwdmgr pwd", 0, 0);
292 ber_str2bv("pwdmgr pwd not configured", 0, 0, &pi.msg);
293 pi.authz = NSLCD_PAM_PERM_DENIED;
294 rc = NSLCD_PAM_PERM_DENIED;
297 /* use configured pwdmgr pwd */
298 memset((void *) pwdc, 0, 256);
299 strncpy(pi.pwd.bv_val, ni->ni_pam_pwdmgr_pwd.bv_val,
300 ni->ni_pam_pwdmgr_pwd.bv_len);
301 pi.pwd.bv_len = ni->ni_pam_pwdmgr_pwd.bv_len;
307 rc = pam_do_bind(ni, fp, op, &pi);
310 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s): rc (%d)\n",
311 pi.dn.bv_val ? pi.dn.bv_val : "NULL",rc,0);
312 WRITE_INT32(fp,NSLCD_VERSION);
313 WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
314 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
316 WRITE_BERVAL(fp,&pi.uid);
317 WRITE_INT32(fp,pi.authz); /* authz */
318 WRITE_BERVAL(fp,&pi.msg); /* authzmsg */
319 WRITE_INT32(fp,NSLCD_RESULT_END);
323 static struct berval grpmsg =
324 BER_BVC("Access denied by group check");
325 static struct berval hostmsg =
326 BER_BVC("Access denied for this host");
327 static struct berval svcmsg =
328 BER_BVC("Access denied for this service");
329 static struct berval uidmsg =
330 BER_BVC("Access denied by UID check");
332 static int pam_compare_cb(Operation *op, SlapReply *rs)
334 if (rs->sr_err == LDAP_COMPARE_TRUE)
335 op->o_callback->sc_private = (void *)1;
339 int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
341 struct berval authzmsg = BER_BVNULL;
352 slap_callback cb = {0};
354 READ_STRING(fp,uidc);
355 pi.uid.bv_val = uidc;
356 pi.uid.bv_len = tmpint32;
357 READ_STRING(fp,svcc);
358 pi.svc.bv_val = svcc;
359 pi.svc.bv_len = tmpint32;
360 READ_STRING(fp,ruserc);
361 pi.ruser.bv_val = ruserc;
362 pi.ruser.bv_len = tmpint32;
363 READ_STRING(fp,rhostc);
364 pi.rhost.bv_val = rhostc;
365 pi.rhost.bv_len = tmpint32;
366 READ_STRING(fp,ttyc);
367 pi.tty.bv_val = ttyc;
368 pi.tty.bv_len = tmpint32;
370 rc = pam_uid2dn(ni, op, &pi);
373 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",
374 pi.dn.bv_val ? pi.dn.bv_val : "NULL",0,0);
376 /* See if they have access to the host and service */
377 if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) {
378 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
379 struct berval hostdn = BER_BVNULL;
380 struct berval odn = op->o_ndn;
381 SlapReply rs = {REP_RESULT};
385 nssov_mapinfo *mi = &ni->ni_maps[NM_host];
387 struct berval filter = {sizeof(fbuf),fbuf};
388 SlapReply rs2 = {REP_RESULT};
390 /* Lookup the host entry */
391 nssov_filter_byname(mi,0,&global_host_bv,&filter);
392 cb.sc_private = &hostdn;
393 cb.sc_response = nssov_name2dn_cb;
394 op->o_callback = &cb;
395 op->o_req_dn = mi->mi_base;
396 op->o_req_ndn = mi->mi_base;
397 op->ors_scope = mi->mi_scope;
398 op->ors_filterstr = filter;
399 op->ors_filter = str2filter_x(op, filter.bv_val);
400 op->ors_attrs = slap_anlist_no_attrs;
401 op->ors_tlimit = SLAP_NO_LIMIT;
403 rc = op->o_bd->be_search(op, &rs2);
404 filter_free_x(op, op->ors_filter, 1);
406 if (BER_BVISEMPTY(&hostdn) &&
407 !BER_BVISEMPTY(&ni->ni_pam_defhost)) {
408 filter.bv_len = sizeof(fbuf);
409 filter.bv_val = fbuf;
410 rs_reinit(&rs2, REP_RESULT);
411 nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter);
412 op->ors_filterstr = filter;
413 op->ors_filter = str2filter_x(op, filter.bv_val);
414 rc = op->o_bd->be_search(op, &rs2);
415 filter_free_x(op, op->ors_filter, 1);
418 /* no host entry, no default host -> deny */
419 if (BER_BVISEMPTY(&hostdn)) {
420 rc = NSLCD_PAM_PERM_DENIED;
426 cb.sc_response = pam_compare_cb;
427 cb.sc_private = NULL;
428 op->o_tag = LDAP_REQ_COMPARE;
429 op->o_req_dn = hostdn;
430 op->o_req_ndn = hostdn;
431 ava.aa_desc = nssov_pam_svc_ad;
432 ava.aa_value = pi.svc;
434 rc = op->o_bd->be_compare( op, &rs );
435 if ( cb.sc_private == NULL ) {
437 rc = NSLCD_PAM_PERM_DENIED;
444 /* See if they're a member of the group */
445 if ((ni->ni_pam_opts & NI_PAM_USERGRP) &&
446 !BER_BVISEMPTY(&ni->ni_pam_group_dn) &&
447 ni->ni_pam_group_ad) {
448 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
449 SlapReply rs = {REP_RESULT};
450 op->o_callback = &cb;
451 cb.sc_response = pam_compare_cb;
452 cb.sc_private = NULL;
453 op->o_tag = LDAP_REQ_COMPARE;
454 op->o_req_dn = ni->ni_pam_group_dn;
455 op->o_req_ndn = ni->ni_pam_group_dn;
456 ava.aa_desc = ni->ni_pam_group_ad;
457 ava.aa_value = pi.dn;
459 rc = op->o_bd->be_compare( op, &rs );
460 if ( cb.sc_private == NULL ) {
462 rc = NSLCD_PAM_PERM_DENIED;
467 /* We need to check the user's entry for these bits */
468 if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) ||
469 ni->ni_pam_template_ad ||
470 ni->ni_pam_min_uid || ni->ni_pam_max_uid ) {
471 rc = be_entry_get_rw( op, &pi.dn, NULL, NULL, 0, &e );
472 if (rc != LDAP_SUCCESS) {
473 rc = NSLCD_PAM_USER_UNKNOWN;
477 if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) {
478 a = attr_find(e->e_attrs, nssov_pam_host_ad);
479 if (!a || attr_valfind( a,
480 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
481 SLAP_MR_VALUE_OF_SYNTAX,
482 &global_host_bv, NULL, op->o_tmpmemctx )) {
483 rc = NSLCD_PAM_PERM_DENIED;
488 if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) {
489 a = attr_find(e->e_attrs, nssov_pam_svc_ad);
490 if (!a || attr_valfind( a,
491 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
492 SLAP_MR_VALUE_OF_SYNTAX,
493 &pi.svc, NULL, op->o_tmpmemctx )) {
494 rc = NSLCD_PAM_PERM_DENIED;
503 if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) {
506 nssov_mapinfo *mi = &ni->ni_maps[NM_passwd];
507 a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc);
509 rc = NSLCD_PAM_PERM_DENIED;
513 id = (int)strtol(a->a_vals[0].bv_val,&tmp,0);
514 if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') {
515 rc = NSLCD_PAM_PERM_DENIED;
519 if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) ||
520 (ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) {
521 rc = NSLCD_PAM_PERM_DENIED;
527 if (ni->ni_pam_template_ad) {
528 a = attr_find(e->e_attrs, ni->ni_pam_template_ad);
530 pi.uid = a->a_vals[0];
531 else if (!BER_BVISEMPTY(&ni->ni_pam_template))
532 pi.uid = ni->ni_pam_template;
534 rc = NSLCD_PAM_SUCCESS;
537 WRITE_INT32(fp,NSLCD_VERSION);
538 WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
539 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
541 WRITE_BERVAL(fp,&authzmsg);
542 WRITE_INT32(fp,NSLCD_RESULT_END);
544 be_entry_release_r(op, e);
547 case NSLCD_PAM_SUCCESS:
548 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): success\n", 0,0,0);
550 case NSLCD_PAM_PERM_DENIED:
551 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): %s\n",
552 authzmsg.bv_val ? authzmsg.bv_val : "NULL",0,0);
555 Debug(LDAP_DEBUG_TRACE,
556 "nssov_pam_authz(): permission denied, rc (%d)\n",
562 static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action)
572 slap_callback cb = {0};
573 SlapReply rs = {REP_RESULT};
574 char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
575 struct berval timestamp, bv[2], *nbv;
580 READ_STRING(fp,uidc);
581 pi.uid.bv_val = uidc;
582 pi.uid.bv_len = tmpint32;
583 READ_STRING(fp,svcc);
584 pi.svc.bv_val = svcc;
585 pi.svc.bv_len = tmpint32;
586 READ_STRING(fp,ruserc);
587 pi.ruser.bv_val = ruserc;
588 pi.ruser.bv_len = tmpint32;
589 READ_STRING(fp,rhostc);
590 pi.rhost.bv_val = rhostc;
591 pi.rhost.bv_len = tmpint32;
592 READ_STRING(fp,ttyc);
593 pi.tty.bv_val = ttyc;
594 pi.tty.bv_len = tmpint32;
596 if (action==NSLCD_ACTION_PAM_SESS_O) {
597 slap_op_time( &op->o_time, &op->o_tincr );
598 timestamp.bv_len = sizeof(timebuf);
599 timestamp.bv_val = timebuf;
601 slap_timestamp( &stamp, ×tamp );
603 READ_STRING(fp,sessionID);
604 timestamp.bv_val = sessionID;
605 timestamp.bv_len = tmpint32;
608 rc = pam_uid2dn(ni, op, &pi);
611 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n",
612 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', pi.dn.bv_val,0);
614 if (!ni->ni_pam_sessions) {
615 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(): %s\n",
616 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
617 "pam session(s) not configured, ignored",0);
624 for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) {
625 if (ni->ni_pam_sessions[i].bv_len != pi.svc.bv_len)
627 if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, pi.svc.bv_val)) {
633 Debug(LDAP_DEBUG_TRACE,
634 "nssov_pam_sess_%c(): service(%s) not configured, ignored\n",
635 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c',
642 bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + pi.svc.bv_len +
643 pi.tty.bv_len + pi.ruser.bv_len + pi.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, pi.svc.bv_val, pi.tty.bv_val,
647 pi.ruser.bv_val, pi.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;
670 op->o_req_dn = pi.dn;
671 op->o_req_ndn = pi.dn;
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',
693 WRITE_INT32(fp,NSLCD_VERSION);
694 WRITE_INT32(fp,action);
695 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
696 if (action==NSLCD_ACTION_PAM_SESS_O)
697 WRITE_STRING(fp,timestamp.bv_val);
698 WRITE_INT32(fp,NSLCD_RESULT_END);
702 int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op)
704 return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_O);
707 int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op)
709 return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_C);
712 int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op,uid_t calleruid)
727 READ_STRING(fp,uidc);
728 pi.uid.bv_val = uidc;
729 pi.uid.bv_len = tmpint32;
730 READ_STRING(fp,svcc);
731 pi.svc.bv_val = svcc;
732 pi.svc.bv_len = tmpint32;
733 READ_STRING(fp,ruserc);
734 pi.ruser.bv_val = svcc;
735 pi.ruser.bv_len = tmpint32;
736 READ_STRING(fp,rhostc);
737 pi.rhost.bv_val = svcc;
738 pi.rhost.bv_len = tmpint32;
739 READ_STRING(fp,ttyc);
740 pi.tty.bv_val = svcc;
741 pi.tty.bv_len = tmpint32;
742 READ_INT32(fp, asroot);
743 READ_STRING(fp,opwc);
744 pi.pwd.bv_val = opwc;
745 pi.pwd.bv_len = tmpint32;
746 READ_STRING(fp,npwc);
748 npw.bv_len = tmpint32;
750 rc = pam_uid2dn(ni, op, &pi);
753 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s %s\n",
754 pi.dn.bv_val ? pi.dn.bv_val : "NULL",
755 pi.uid.bv_val ? pi.uid.bv_val : "NULL",
756 asroot ? "as root" : "as user");
761 /* nssov_pam prohibits password mod */
762 if (!BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) {
763 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(): %s (%s)\n",
764 "password_prohibit_message",
765 ni->ni_pam_password_prohibit_message.bv_val,0);
766 ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg);
767 rc = NSLCD_PAM_PERM_DENIED;
772 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) {
773 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
774 "pwdmgr not configured", 0, 0);
775 ber_str2bv("pwdmgr not configured", 0, 0, &pi.msg);
776 rc = NSLCD_PAM_PERM_DENIED;
779 if (calleruid != 0) {
780 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(): %s\n",
781 "caller is not root", 0, 0);
782 ber_str2bv("only root may do that", 0, 0, &pi.msg);
783 rc = NSLCD_PAM_PERM_DENIED;
786 /* root user requesting pwmod */
790 if (!pi.ispwdmgr && BER_BVISEMPTY(&pi.pwd)) {
791 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n",
792 "not pwdmgr and old pwd empty", 0, 0);
793 ber_str2bv("must provide old password", 0, 0, &pi.msg);
794 rc = NSLCD_PAM_PERM_DENIED;
798 BerElementBuffer berbuf;
799 BerElement *ber = (BerElement *)&berbuf;
801 SlapReply rs = {REP_RESULT};
802 slap_callback cb = {0};
804 ber_init_w_nullc(ber, LBER_USE_DER);
805 ber_printf(ber, "{");
806 if (!BER_BVISEMPTY(&pi.dn))
807 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID,
809 /* supply old pwd whenever it's given */
810 if (!BER_BVISEMPTY(&pi.pwd))
811 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
813 if (!BER_BVISEMPTY(&npw))
814 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
816 ber_printf(ber, "N}");
817 ber_flatten2(ber, &bv, 0);
818 op->o_tag = LDAP_REQ_EXTENDED;
819 op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
820 op->ore_reqdata = &bv;
823 /* root user changing end-user passwords */
824 op->o_dn = ni->ni_pam_pwdmgr_dn;
825 op->o_ndn = ni->ni_pam_pwdmgr_dn;
827 /* end-user self-pwd-mod */
831 op->o_callback = &cb;
832 op->o_conn->c_authz_backend = op->o_bd;
833 cb.sc_response = slap_null_cb;
834 op->o_bd = frontendDB;
835 rc = op->o_bd->be_extended(op, &rs);
837 ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
838 if (rc == LDAP_SUCCESS)
839 rc = NSLCD_PAM_SUCCESS;
841 rc = NSLCD_PAM_PERM_DENIED;
844 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), rc (%d)\n", rc, 0, 0);
845 WRITE_INT32(fp,NSLCD_VERSION);
846 WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
847 WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
849 WRITE_BERVAL(fp,&pi.msg);
858 code = slap_str2ad("loginStatus", &ad_loginStatus, &text);