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