1 /* $NetBSD: pam.c,v 1.1.1.5 2018/02/06 01:53:06 christos Exp $ */ 2 3 /* pam.c - pam processing routines */ 4 /* $OpenLDAP$ */ 5 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 6 * 7 * Copyright 2008-2017 The OpenLDAP Foundation. 8 * Portions Copyright 2008 by Howard Chu, Symas Corp. 9 * Portions Copyright 2013 by Ted C. Cheng, Symas Corp. 10 * All rights reserved. 11 * 12 * Redistribution and use in source and binary forms, with or without 13 * modification, are permitted only as authorized by the OpenLDAP 14 * Public License. 15 * 16 * A copy of this license is available in the file LICENSE in the 17 * top-level directory of the distribution or, alternatively, at 18 * <http://www.OpenLDAP.org/license.html>. 19 */ 20 21 #include "nssov.h" 22 #include "lutil.h" 23 24 #undef ldap_debug /* silence a warning in ldap-int.h */ 25 #include "../../../libraries/libldap/ldap-int.h" /* for ldap_ld_free */ 26 27 static int ppolicy_cid; 28 static AttributeDescription *ad_loginStatus; 29 30 struct paminfo { 31 struct berval uid; 32 struct berval dn; 33 struct berval svc; 34 struct berval ruser; 35 struct berval rhost; 36 struct berval tty; 37 struct berval pwd; 38 int authz; 39 struct berval msg; 40 int ispwdmgr; 41 }; 42 43 static int pam_bindcb( 44 Operation *op, SlapReply *rs) 45 { 46 struct paminfo *pi = op->o_callback->sc_private; 47 LDAPControl *ctrl = ldap_control_find(LDAP_CONTROL_PASSWORDPOLICYRESPONSE, 48 rs->sr_ctrls, NULL); 49 if (ctrl) { 50 LDAP *ld; 51 ber_int_t expire, grace; 52 LDAPPasswordPolicyError error; 53 54 ldap_create(&ld); 55 if (ld) { 56 int rc = ldap_parse_passwordpolicy_control(ld,ctrl, 57 &expire,&grace,&error); 58 if (rc == LDAP_SUCCESS) { 59 if (expire >= 0) { 60 char *unit = "seconds"; 61 if (expire > 60) { 62 expire /= 60; 63 unit = "minutes"; 64 } 65 if (expire > 60) { 66 expire /= 60; 67 unit = "hours"; 68 } 69 if (expire > 24) { 70 expire /= 24; 71 unit = "days"; 72 } 73 #if 0 /* Who warns about expiration so far in advance? */ 74 if (expire > 7) { 75 expire /= 7; 76 unit = "weeks"; 77 } 78 if (expire > 4) { 79 expire /= 4; 80 unit = "months"; 81 } 82 if (expire > 12) { 83 expire /= 12; 84 unit = "years"; 85 } 86 #endif 87 pi->msg.bv_len = sprintf(pi->msg.bv_val, 88 "\nWARNING: Password expires in %d %s\n", expire, unit); 89 } else if (grace > 0) { 90 pi->msg.bv_len = sprintf(pi->msg.bv_val, 91 "Password expired; %d grace logins remaining", 92 grace); 93 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD; 94 } else if (error != PP_noError) { 95 ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0, 96 &pi->msg); 97 switch (error) { 98 case PP_passwordExpired: 99 /* report this during authz */ 100 rs->sr_err = LDAP_SUCCESS; 101 /* fallthru */ 102 case PP_changeAfterReset: 103 pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD; 104 } 105 } 106 } 107 ldap_ld_free(ld,0,NULL,NULL); 108 } 109 } 110 return LDAP_SUCCESS; 111 } 112 113 static int pam_uid2dn(nssov_info *ni, Operation *op, 114 struct paminfo *pi) 115 { 116 struct berval sdn; 117 118 BER_BVZERO(&pi->dn); 119 120 if (!isvalidusername(&pi->uid)) { 121 Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n", 122 pi->uid.bv_val ? pi->uid.bv_val : "NULL",0,0); 123 return NSLCD_PAM_USER_UNKNOWN; 124 } 125 126 if (ni->ni_pam_opts & NI_PAM_SASL2DN) { 127 int hlen = global_host_bv.bv_len; 128 129 /* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */ 130 sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen + 131 STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" ); 132 sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx ); 133 sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth", 134 pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val); 135 slap_sasl2dn(op, &sdn, &pi->dn, 0); 136 op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx ); 137 } 138 139 /* If no luck, do a basic uid search */ 140 if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) { 141 nssov_uid2dn(op, ni, &pi->uid, &pi->dn); 142 if (!BER_BVISEMPTY(&pi->dn)) { 143 sdn = pi->dn; 144 dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx ); 145 } 146 } 147 if (BER_BVISEMPTY(&pi->dn)) { 148 return NSLCD_PAM_USER_UNKNOWN; 149 } 150 return 0; 151 } 152 153 int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op, 154 struct paminfo *pi) 155 { 156 int rc; 157 slap_callback cb = {0}; 158 SlapReply rs = {REP_RESULT}; 159 160 pi->msg.bv_val = pi->pwd.bv_val; 161 pi->msg.bv_len = 0; 162 pi->authz = NSLCD_PAM_SUCCESS; 163 164 if (!pi->ispwdmgr) { 165 166 rc = pam_uid2dn(ni, op, pi); 167 if (rc) goto finish; 168 169 if (BER_BVISEMPTY(&pi->pwd)) { 170 rc = NSLCD_PAM_PERM_DENIED; 171 goto finish; 172 } 173 174 /* Should only need to do this once at open time, but there's always 175 * the possibility that ppolicy will get loaded later. 176 */ 177 if (!ppolicy_cid) { 178 rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST, 179 &ppolicy_cid); 180 } 181 /* of course, 0 is a valid cid, but it won't be ppolicy... */ 182 if (ppolicy_cid) { 183 op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL; 184 } 185 } 186 187 cb.sc_response = pam_bindcb; 188 cb.sc_private = pi; 189 op->o_callback = &cb; 190 op->o_dn.bv_val[0] = 0; 191 op->o_dn.bv_len = 0; 192 op->o_ndn.bv_val[0] = 0; 193 op->o_ndn.bv_len = 0; 194 op->o_tag = LDAP_REQ_BIND; 195 op->o_protocol = LDAP_VERSION3; 196 op->orb_method = LDAP_AUTH_SIMPLE; 197 op->orb_cred = pi->pwd; 198 op->o_req_dn = pi->dn; 199 op->o_req_ndn = pi->dn; 200 slap_op_time( &op->o_time, &op->o_tincr ); 201 rc = op->o_bd->be_bind( op, &rs ); 202 memset(pi->pwd.bv_val,0,pi->pwd.bv_len); 203 /* quirk: on successful bind, caller has to send result. we need 204 * to make sure callbacks run. 205 */ 206 if (rc == LDAP_SUCCESS) 207 send_ldap_result(op, &rs); 208 switch(rs.sr_err) { 209 case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break; 210 case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break; 211 default: rc = NSLCD_PAM_AUTH_ERR; break; 212 } 213 finish: 214 Debug(LDAP_DEBUG_ANY,"pam_do_bind (%s): rc (%d)\n", 215 pi->dn.bv_val ? pi->dn.bv_val : "NULL", rc, 0); 216 return rc; 217 } 218 219 int pam_authc(nssov_info *ni,TFILE *fp,Operation *op,uid_t calleruid) 220 { 221 int32_t tmpint32; 222 int rc; 223 char uidc[32]; 224 char svcc[256]; 225 char ruserc[32]; 226 char rhostc[256]; 227 char ttyc[256]; 228 char pwdc[256]; 229 struct paminfo pi; 230 231 232 READ_STRING(fp,uidc); 233 pi.uid.bv_val = uidc; 234 pi.uid.bv_len = tmpint32; 235 READ_STRING(fp,svcc); 236 pi.svc.bv_val = svcc; 237 pi.svc.bv_len = tmpint32; 238 READ_STRING(fp,ruserc); 239 pi.ruser.bv_val = ruserc; 240 pi.ruser.bv_len = tmpint32; 241 READ_STRING(fp,rhostc); 242 pi.rhost.bv_val = rhostc; 243 pi.rhost.bv_len = tmpint32; 244 READ_STRING(fp,ttyc); 245 pi.tty.bv_val = ttyc; 246 pi.tty.bv_len = tmpint32; 247 READ_STRING(fp,pwdc); 248 pi.pwd.bv_val = pwdc; 249 pi.pwd.bv_len = tmpint32; 250 251 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n", 252 pi.uid.bv_val ? pi.uid.bv_val : "NULL",0,0); 253 254 BER_BVZERO(&pi.msg); 255 pi.ispwdmgr = 0; 256 257 /* if service is "passwd" and "nssov-pam-password-prohibit-message */ 258 /* is set, deny the auth request */ 259 if (!strcmp(svcc, "passwd") && 260 !BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) { 261 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(): %s (%s)\n", 262 "password_prohibit_message for passwd", 263 ni->ni_pam_password_prohibit_message.bv_val,0); 264 ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg); 265 pi.authz = NSLCD_PAM_PERM_DENIED; 266 rc = NSLCD_PAM_PERM_DENIED; 267 goto finish; 268 } 269 270 /* if username is null, pwdmgr password preliminary check */ 271 if (BER_BVISEMPTY(&pi.uid)) { 272 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) { 273 /* pwdmgr dn not configured */ 274 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n", 275 "pwdmgr dn not configured", 0, 0); 276 ber_str2bv("pwdmgr dn not configured", 0, 0, &pi.msg); 277 pi.authz = NSLCD_PAM_PERM_DENIED; 278 rc = NSLCD_PAM_PERM_DENIED; 279 goto finish; 280 } else if (calleruid != 0) { 281 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n", 282 "caller is not root", 0, 0); 283 ber_str2bv("only root may do that", 0, 0, &pi.msg); 284 pi.authz = NSLCD_PAM_PERM_DENIED; 285 rc = NSLCD_PAM_PERM_DENIED; 286 goto finish; 287 } else { 288 /* use pwdmgr dn */ 289 ber_str2bv(ni->ni_pam_pwdmgr_dn.bv_val, 0, 0, &pi.dn); 290 } 291 292 /* use pwdmgr pwd if configured */ 293 if (BER_BVISEMPTY(&pi.pwd)) { 294 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_pwd)) { 295 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(prelim check): %s\n", 296 "no pwdmgr pwd", 0, 0); 297 ber_str2bv("pwdmgr pwd not configured", 0, 0, &pi.msg); 298 pi.authz = NSLCD_PAM_PERM_DENIED; 299 rc = NSLCD_PAM_PERM_DENIED; 300 goto finish; 301 } 302 /* use configured pwdmgr pwd */ 303 memset((void *) pwdc, 0, 256); 304 strncpy(pi.pwd.bv_val, ni->ni_pam_pwdmgr_pwd.bv_val, 305 ni->ni_pam_pwdmgr_pwd.bv_len); 306 pi.pwd.bv_len = ni->ni_pam_pwdmgr_pwd.bv_len; 307 } 308 pi.ispwdmgr = 1; 309 } 310 311 312 rc = pam_do_bind(ni, fp, op, &pi); 313 314 finish: 315 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s): rc (%d)\n", 316 pi.dn.bv_val ? pi.dn.bv_val : "NULL",rc,0); 317 WRITE_INT32(fp,NSLCD_VERSION); 318 WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC); 319 WRITE_INT32(fp,NSLCD_RESULT_BEGIN); 320 WRITE_INT32(fp,rc); 321 WRITE_BERVAL(fp,&pi.uid); 322 WRITE_INT32(fp,pi.authz); /* authz */ 323 WRITE_BERVAL(fp,&pi.msg); /* authzmsg */ 324 WRITE_INT32(fp,NSLCD_RESULT_END); 325 return 0; 326 } 327 328 static struct berval grpmsg = 329 BER_BVC("Access denied by group check"); 330 static struct berval hostmsg = 331 BER_BVC("Access denied for this host"); 332 static struct berval svcmsg = 333 BER_BVC("Access denied for this service"); 334 static struct berval uidmsg = 335 BER_BVC("Access denied by UID check"); 336 337 static int pam_compare_cb(Operation *op, SlapReply *rs) 338 { 339 if (rs->sr_err == LDAP_COMPARE_TRUE) 340 op->o_callback->sc_private = (void *)1; 341 return LDAP_SUCCESS; 342 } 343 344 int pam_authz(nssov_info *ni,TFILE *fp,Operation *op) 345 { 346 struct berval authzmsg = BER_BVNULL; 347 int32_t tmpint32; 348 char uidc[32]; 349 char svcc[256]; 350 char ruserc[32]; 351 char rhostc[256]; 352 char ttyc[256]; 353 int rc; 354 struct paminfo pi; 355 Entry *e = NULL; 356 Attribute *a; 357 slap_callback cb = {0}; 358 359 READ_STRING(fp,uidc); 360 pi.uid.bv_val = uidc; 361 pi.uid.bv_len = tmpint32; 362 READ_STRING(fp,svcc); 363 pi.svc.bv_val = svcc; 364 pi.svc.bv_len = tmpint32; 365 READ_STRING(fp,ruserc); 366 pi.ruser.bv_val = ruserc; 367 pi.ruser.bv_len = tmpint32; 368 READ_STRING(fp,rhostc); 369 pi.rhost.bv_val = rhostc; 370 pi.rhost.bv_len = tmpint32; 371 READ_STRING(fp,ttyc); 372 pi.tty.bv_val = ttyc; 373 pi.tty.bv_len = tmpint32; 374 375 rc = pam_uid2dn(ni, op, &pi); 376 if (rc) goto finish; 377 378 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n", 379 pi.dn.bv_val ? pi.dn.bv_val : "NULL",0,0); 380 381 /* See if they have access to the host and service */ 382 if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) { 383 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT; 384 struct berval hostdn = BER_BVNULL; 385 struct berval odn = op->o_ndn; 386 SlapReply rs = {REP_RESULT}; 387 op->o_dn = pi.dn; 388 op->o_ndn = pi.dn; 389 { 390 nssov_mapinfo *mi = &ni->ni_maps[NM_host]; 391 char fbuf[1024]; 392 struct berval filter = {sizeof(fbuf),fbuf}; 393 SlapReply rs2 = {REP_RESULT}; 394 395 /* Lookup the host entry */ 396 nssov_filter_byname(mi,0,&global_host_bv,&filter); 397 cb.sc_private = &hostdn; 398 cb.sc_response = nssov_name2dn_cb; 399 op->o_callback = &cb; 400 op->o_req_dn = mi->mi_base; 401 op->o_req_ndn = mi->mi_base; 402 op->ors_scope = mi->mi_scope; 403 op->ors_filterstr = filter; 404 op->ors_filter = str2filter_x(op, filter.bv_val); 405 op->ors_attrs = slap_anlist_no_attrs; 406 op->ors_tlimit = SLAP_NO_LIMIT; 407 op->ors_slimit = 2; 408 rc = op->o_bd->be_search(op, &rs2); 409 filter_free_x(op, op->ors_filter, 1); 410 411 if (BER_BVISEMPTY(&hostdn) && 412 !BER_BVISEMPTY(&ni->ni_pam_defhost)) { 413 filter.bv_len = sizeof(fbuf); 414 filter.bv_val = fbuf; 415 rs_reinit(&rs2, REP_RESULT); 416 nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter); 417 op->ors_filterstr = filter; 418 op->ors_filter = str2filter_x(op, filter.bv_val); 419 rc = op->o_bd->be_search(op, &rs2); 420 filter_free_x(op, op->ors_filter, 1); 421 } 422 423 /* no host entry, no default host -> deny */ 424 if (BER_BVISEMPTY(&hostdn)) { 425 rc = NSLCD_PAM_PERM_DENIED; 426 authzmsg = hostmsg; 427 goto finish; 428 } 429 } 430 431 cb.sc_response = pam_compare_cb; 432 cb.sc_private = NULL; 433 op->o_tag = LDAP_REQ_COMPARE; 434 op->o_req_dn = hostdn; 435 op->o_req_ndn = hostdn; 436 ava.aa_desc = nssov_pam_svc_ad; 437 ava.aa_value = pi.svc; 438 op->orc_ava = &ava; 439 rc = op->o_bd->be_compare( op, &rs ); 440 if ( cb.sc_private == NULL ) { 441 authzmsg = svcmsg; 442 rc = NSLCD_PAM_PERM_DENIED; 443 goto finish; 444 } 445 op->o_dn = odn; 446 op->o_ndn = odn; 447 } 448 449 /* See if they're a member of the group */ 450 if ((ni->ni_pam_opts & NI_PAM_USERGRP) && 451 !BER_BVISEMPTY(&ni->ni_pam_group_dn) && 452 ni->ni_pam_group_ad) { 453 AttributeAssertion ava = ATTRIBUTEASSERTION_INIT; 454 SlapReply rs = {REP_RESULT}; 455 op->o_callback = &cb; 456 cb.sc_response = pam_compare_cb; 457 cb.sc_private = NULL; 458 op->o_tag = LDAP_REQ_COMPARE; 459 op->o_req_dn = ni->ni_pam_group_dn; 460 op->o_req_ndn = ni->ni_pam_group_dn; 461 ava.aa_desc = ni->ni_pam_group_ad; 462 ava.aa_value = pi.dn; 463 op->orc_ava = &ava; 464 rc = op->o_bd->be_compare( op, &rs ); 465 if ( cb.sc_private == NULL ) { 466 authzmsg = grpmsg; 467 rc = NSLCD_PAM_PERM_DENIED; 468 goto finish; 469 } 470 } 471 472 /* We need to check the user's entry for these bits */ 473 if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) || 474 ni->ni_pam_template_ad || 475 ni->ni_pam_min_uid || ni->ni_pam_max_uid ) { 476 rc = be_entry_get_rw( op, &pi.dn, NULL, NULL, 0, &e ); 477 if (rc != LDAP_SUCCESS) { 478 rc = NSLCD_PAM_USER_UNKNOWN; 479 goto finish; 480 } 481 } 482 if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) { 483 a = attr_find(e->e_attrs, nssov_pam_host_ad); 484 if (!a || attr_valfind( a, 485 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | 486 SLAP_MR_VALUE_OF_SYNTAX, 487 &global_host_bv, NULL, op->o_tmpmemctx )) { 488 rc = NSLCD_PAM_PERM_DENIED; 489 authzmsg = hostmsg; 490 goto finish; 491 } 492 } 493 if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) { 494 a = attr_find(e->e_attrs, nssov_pam_svc_ad); 495 if (!a || attr_valfind( a, 496 SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH | 497 SLAP_MR_VALUE_OF_SYNTAX, 498 &pi.svc, NULL, op->o_tmpmemctx )) { 499 rc = NSLCD_PAM_PERM_DENIED; 500 authzmsg = svcmsg; 501 goto finish; 502 } 503 } 504 505 /* from passwd.c */ 506 #define UIDN_KEY 2 507 508 if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) { 509 int id; 510 char *tmp; 511 nssov_mapinfo *mi = &ni->ni_maps[NM_passwd]; 512 a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc); 513 if (!a) { 514 rc = NSLCD_PAM_PERM_DENIED; 515 authzmsg = uidmsg; 516 goto finish; 517 } 518 id = (int)strtol(a->a_vals[0].bv_val,&tmp,0); 519 if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') { 520 rc = NSLCD_PAM_PERM_DENIED; 521 authzmsg = uidmsg; 522 goto finish; 523 } 524 if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) || 525 (ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) { 526 rc = NSLCD_PAM_PERM_DENIED; 527 authzmsg = uidmsg; 528 goto finish; 529 } 530 } 531 532 if (ni->ni_pam_template_ad) { 533 a = attr_find(e->e_attrs, ni->ni_pam_template_ad); 534 if (a) 535 pi.uid = a->a_vals[0]; 536 else if (!BER_BVISEMPTY(&ni->ni_pam_template)) 537 pi.uid = ni->ni_pam_template; 538 } 539 rc = NSLCD_PAM_SUCCESS; 540 541 finish: 542 WRITE_INT32(fp,NSLCD_VERSION); 543 WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ); 544 WRITE_INT32(fp,NSLCD_RESULT_BEGIN); 545 WRITE_INT32(fp,rc); 546 WRITE_BERVAL(fp,&authzmsg); 547 WRITE_INT32(fp,NSLCD_RESULT_END); 548 if (e) { 549 be_entry_release_r(op, e); 550 } 551 switch (rc) { 552 case NSLCD_PAM_SUCCESS: 553 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): success\n", 0,0,0); 554 break; 555 case NSLCD_PAM_PERM_DENIED: 556 Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(): %s\n", 557 authzmsg.bv_val ? authzmsg.bv_val : "NULL",0,0); 558 break; 559 default: 560 Debug(LDAP_DEBUG_TRACE, 561 "nssov_pam_authz(): permission denied, rc (%d)\n", 562 rc, 0, 0); 563 } 564 return 0; 565 } 566 567 static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action) 568 { 569 int32_t tmpint32; 570 char svcc[256]; 571 char uidc[32]; 572 char ttyc[32]; 573 char rhostc[256]; 574 char ruserc[32]; 575 char sessionID[64]; 576 struct paminfo pi; 577 slap_callback cb = {0}; 578 SlapReply rs = {REP_RESULT}; 579 char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE]; 580 struct berval timestamp, bv[2], *nbv; 581 time_t stamp; 582 Modifications mod; 583 int rc = 0; 584 585 READ_STRING(fp,uidc); 586 pi.uid.bv_val = uidc; 587 pi.uid.bv_len = tmpint32; 588 READ_STRING(fp,svcc); 589 pi.svc.bv_val = svcc; 590 pi.svc.bv_len = tmpint32; 591 READ_STRING(fp,ruserc); 592 pi.ruser.bv_val = ruserc; 593 pi.ruser.bv_len = tmpint32; 594 READ_STRING(fp,rhostc); 595 pi.rhost.bv_val = rhostc; 596 pi.rhost.bv_len = tmpint32; 597 READ_STRING(fp,ttyc); 598 pi.tty.bv_val = ttyc; 599 pi.tty.bv_len = tmpint32; 600 601 if (action==NSLCD_ACTION_PAM_SESS_O) { 602 slap_op_time( &op->o_time, &op->o_tincr ); 603 timestamp.bv_len = sizeof(timebuf); 604 timestamp.bv_val = timebuf; 605 stamp = op->o_time; 606 slap_timestamp( &stamp, ×tamp ); 607 } else { 608 READ_STRING(fp,sessionID); 609 timestamp.bv_val = sessionID; 610 timestamp.bv_len = tmpint32; 611 } 612 613 rc = pam_uid2dn(ni, op, &pi); 614 if (rc) goto done; 615 616 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n", 617 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', pi.dn.bv_val,0); 618 619 if (!ni->ni_pam_sessions) { 620 Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(): %s\n", 621 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', 622 "pam session(s) not configured, ignored",0); 623 rc = -1; 624 goto done; 625 } 626 627 { 628 int i, found=0; 629 for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) { 630 if (ni->ni_pam_sessions[i].bv_len != pi.svc.bv_len) 631 continue; 632 if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, pi.svc.bv_val)) { 633 found = 1; 634 break; 635 } 636 } 637 if (!found) { 638 Debug(LDAP_DEBUG_TRACE, 639 "nssov_pam_sess_%c(): service(%s) not configured, ignored\n", 640 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', 641 pi.svc.bv_val,0); 642 rc = -1; 643 goto done; 644 } 645 } 646 647 bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + pi.svc.bv_len + 648 pi.tty.bv_len + pi.ruser.bv_len + pi.rhost.bv_len + STRLENOF(" (@)"); 649 bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx ); 650 sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)", 651 timestamp.bv_val, global_host_bv.bv_val, pi.svc.bv_val, pi.tty.bv_val, 652 pi.ruser.bv_val, pi.rhost.bv_val); 653 654 Debug(LDAP_DEBUG_TRACE, "nssov_pam_sess_%c(): loginStatus (%s) \n", 655 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', bv[0].bv_val,0); 656 657 mod.sml_numvals = 1; 658 mod.sml_values = bv; 659 BER_BVZERO(&bv[1]); 660 attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx ); 661 mod.sml_nvalues = nbv; 662 mod.sml_desc = ad_loginStatus; 663 mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD : 664 LDAP_MOD_DELETE; 665 mod.sml_flags = SLAP_MOD_INTERNAL; 666 mod.sml_next = NULL; 667 668 cb.sc_response = slap_null_cb; 669 op->o_callback = &cb; 670 op->o_tag = LDAP_REQ_MODIFY; 671 op->o_dn = op->o_bd->be_rootdn; 672 op->o_ndn = op->o_bd->be_rootndn; 673 op->orm_modlist = &mod; 674 op->orm_no_opattrs = 1; 675 op->o_req_dn = pi.dn; 676 op->o_req_ndn = pi.dn; 677 if (op->o_bd->be_modify( op, &rs ) != LDAP_SUCCESS) { 678 Debug(LDAP_DEBUG_TRACE, 679 "nssov_pam_sess_%c(): modify op failed\n", 680 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', 681 0,0); 682 rc = -1; 683 } 684 685 if ( mod.sml_next ) { 686 slap_mods_free( mod.sml_next, 1 ); 687 } 688 ber_bvarray_free_x( nbv, op->o_tmpmemctx ); 689 690 done:; 691 692 if (rc == 0) { 693 Debug(LDAP_DEBUG_TRACE, 694 "nssov_pam_sess_%c(): success\n", 695 action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', 696 0,0); 697 } 698 WRITE_INT32(fp,NSLCD_VERSION); 699 WRITE_INT32(fp,action); 700 WRITE_INT32(fp,NSLCD_RESULT_BEGIN); 701 if (action==NSLCD_ACTION_PAM_SESS_O) 702 WRITE_STRING(fp,timestamp.bv_val); 703 WRITE_INT32(fp,NSLCD_RESULT_END); 704 return 0; 705 } 706 707 int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op) 708 { 709 return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_O); 710 } 711 712 int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op) 713 { 714 return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_C); 715 } 716 717 int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op,uid_t calleruid) 718 { 719 struct berval npw; 720 int32_t tmpint32; 721 char uidc[32]; 722 char svcc[256]; 723 char ruserc[32]; 724 char rhostc[256]; 725 char ttyc[256]; 726 int asroot; 727 char opwc[256]; 728 char npwc[256]; 729 struct paminfo pi; 730 int rc; 731 732 READ_STRING(fp,uidc); 733 pi.uid.bv_val = uidc; 734 pi.uid.bv_len = tmpint32; 735 READ_STRING(fp,svcc); 736 pi.svc.bv_val = svcc; 737 pi.svc.bv_len = tmpint32; 738 READ_STRING(fp,ruserc); 739 pi.ruser.bv_val = svcc; 740 pi.ruser.bv_len = tmpint32; 741 READ_STRING(fp,rhostc); 742 pi.rhost.bv_val = svcc; 743 pi.rhost.bv_len = tmpint32; 744 READ_STRING(fp,ttyc); 745 pi.tty.bv_val = svcc; 746 pi.tty.bv_len = tmpint32; 747 READ_INT32(fp, asroot); 748 READ_STRING(fp,opwc); 749 pi.pwd.bv_val = opwc; 750 pi.pwd.bv_len = tmpint32; 751 READ_STRING(fp,npwc); 752 npw.bv_val = npwc; 753 npw.bv_len = tmpint32; 754 755 rc = pam_uid2dn(ni, op, &pi); 756 if (rc) goto done; 757 758 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s %s\n", 759 pi.dn.bv_val ? pi.dn.bv_val : "NULL", 760 pi.uid.bv_val ? pi.uid.bv_val : "NULL", 761 asroot ? "as root" : "as user"); 762 763 BER_BVZERO(&pi.msg); 764 pi.ispwdmgr = 0; 765 766 /* nssov_pam prohibits password mod */ 767 if (!BER_BVISEMPTY(&ni->ni_pam_password_prohibit_message)) { 768 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(): %s (%s)\n", 769 "password_prohibit_message", 770 ni->ni_pam_password_prohibit_message.bv_val,0); 771 ber_str2bv(ni->ni_pam_password_prohibit_message.bv_val, 0, 0, &pi.msg); 772 rc = NSLCD_PAM_PERM_DENIED; 773 goto done; 774 } 775 776 if (asroot) { 777 if (BER_BVISEMPTY(&ni->ni_pam_pwdmgr_dn)) { 778 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n", 779 "pwdmgr not configured", 0, 0); 780 ber_str2bv("pwdmgr not configured", 0, 0, &pi.msg); 781 rc = NSLCD_PAM_PERM_DENIED; 782 goto done; 783 } 784 if (calleruid != 0) { 785 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(): %s\n", 786 "caller is not root", 0, 0); 787 ber_str2bv("only root may do that", 0, 0, &pi.msg); 788 rc = NSLCD_PAM_PERM_DENIED; 789 goto done; 790 } 791 /* root user requesting pwmod */ 792 pi.ispwdmgr = 1; 793 } 794 795 if (!pi.ispwdmgr && BER_BVISEMPTY(&pi.pwd)) { 796 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), %s\n", 797 "not pwdmgr and old pwd empty", 0, 0); 798 ber_str2bv("must provide old password", 0, 0, &pi.msg); 799 rc = NSLCD_PAM_PERM_DENIED; 800 goto done; 801 } 802 803 BerElementBuffer berbuf; 804 BerElement *ber = (BerElement *)&berbuf; 805 struct berval bv; 806 SlapReply rs = {REP_RESULT}; 807 slap_callback cb = {0}; 808 809 ber_init_w_nullc(ber, LBER_USE_DER); 810 ber_printf(ber, "{"); 811 if (!BER_BVISEMPTY(&pi.dn)) 812 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_ID, 813 &pi.dn); 814 /* supply old pwd whenever it's given */ 815 if (!BER_BVISEMPTY(&pi.pwd)) 816 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD, 817 &pi.pwd); 818 if (!BER_BVISEMPTY(&npw)) 819 ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW, 820 &npw); 821 ber_printf(ber, "N}"); 822 ber_flatten2(ber, &bv, 0); 823 op->o_tag = LDAP_REQ_EXTENDED; 824 op->ore_reqoid = slap_EXOP_MODIFY_PASSWD; 825 op->ore_reqdata = &bv; 826 827 if (pi.ispwdmgr) { 828 /* root user changing end-user passwords */ 829 op->o_dn = ni->ni_pam_pwdmgr_dn; 830 op->o_ndn = ni->ni_pam_pwdmgr_dn; 831 } else { 832 /* end-user self-pwd-mod */ 833 op->o_dn = pi.dn; 834 op->o_ndn = pi.dn; 835 } 836 op->o_callback = &cb; 837 op->o_conn->c_authz_backend = op->o_bd; 838 cb.sc_response = slap_null_cb; 839 op->o_bd = frontendDB; 840 rc = op->o_bd->be_extended(op, &rs); 841 if (rs.sr_text) 842 ber_str2bv(rs.sr_text, 0, 0, &pi.msg); 843 if (rc == LDAP_SUCCESS) 844 rc = NSLCD_PAM_SUCCESS; 845 else 846 rc = NSLCD_PAM_PERM_DENIED; 847 848 done:; 849 Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(), rc (%d)\n", rc, 0, 0); 850 WRITE_INT32(fp,NSLCD_VERSION); 851 WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD); 852 WRITE_INT32(fp,NSLCD_RESULT_BEGIN); 853 WRITE_INT32(fp,rc); 854 WRITE_BERVAL(fp,&pi.msg); 855 return 0; 856 } 857 858 int nssov_pam_init() 859 { 860 int code = 0; 861 const char *text; 862 if (!ad_loginStatus) 863 code = slap_str2ad("loginStatus", &ad_loginStatus, &text); 864 865 return code; 866 } 867