Back to index

openldap  2.4.31
pam.c
Go to the documentation of this file.
00001 /* pam.c - pam processing routines */
00002 /* $OpenLDAP$ */
00003 /* This work is part of OpenLDAP Software <http://www.openldap.org/>. 
00004  *
00005  * Copyright 2008-2012 The OpenLDAP Foundation.
00006  * Portions Copyright 2008 by Howard Chu, Symas Corp.
00007  * All rights reserved.
00008  *
00009  * Redistribution and use in source and binary forms, with or without
00010  * modification, are permitted only as authorized by the OpenLDAP
00011  * Public License.
00012  *
00013  * A copy of this license is available in the file LICENSE in the
00014  * top-level directory of the distribution or, alternatively, at
00015  * <http://www.OpenLDAP.org/license.html>.
00016  */
00017 
00018 #include "nssov.h"
00019 #include "lutil.h"
00020 
00021 static int ppolicy_cid;
00022 static AttributeDescription *ad_loginStatus;
00023 
00024 struct paminfo {
00025        struct berval uid;
00026        struct berval dn;
00027        struct berval svc;
00028        struct berval pwd;
00029        int authz;
00030        struct berval msg;
00031 };
00032 
00033 static int pam_bindcb(
00034        Operation *op, SlapReply *rs)
00035 {
00036        struct paminfo *pi = op->o_callback->sc_private;
00037        LDAPControl *ctrl = ldap_control_find(LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
00038               rs->sr_ctrls, NULL);
00039        if (ctrl) {
00040               LDAP *ld;
00041               ber_int_t expire, grace;
00042               LDAPPasswordPolicyError error;
00043 
00044               ldap_create(&ld);
00045               if (ld) {
00046                      int rc = ldap_parse_passwordpolicy_control(ld,ctrl,
00047                             &expire,&grace,&error);
00048                      if (rc == LDAP_SUCCESS) {
00049                             if (expire >= 0) {
00050                                    char *unit = "seconds";
00051                                    if (expire > 60) {
00052                                           expire /= 60;
00053                                           unit = "minutes";
00054                                    }
00055                                    if (expire > 60) {
00056                                           expire /= 60;
00057                                           unit = "hours";
00058                                    }
00059                                    if (expire > 24) {
00060                                           expire /= 24;
00061                                           unit = "days";
00062                                    }
00063 #if 0  /* Who warns about expiration so far in advance? */
00064                                    if (expire > 7) {
00065                                           expire /= 7;
00066                                           unit = "weeks";
00067                                    }
00068                                    if (expire > 4) {
00069                                           expire /= 4;
00070                                           unit = "months";
00071                                    }
00072                                    if (expire > 12) {
00073                                           expire /= 12;
00074                                           unit = "years";
00075                                    }
00076 #endif
00077                                    pi->msg.bv_len = sprintf(pi->msg.bv_val,
00078                                           "\nWARNING: Password expires in %d %s\n", expire, unit);
00079                             } else if (grace > 0) {
00080                                    pi->msg.bv_len = sprintf(pi->msg.bv_val,
00081                                           "Password expired; %d grace logins remaining",
00082                                           grace);
00083                                    pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
00084                             } else if (error != PP_noError) {
00085                                    ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0,
00086                                           &pi->msg);
00087                                    switch (error) {
00088                                    case PP_passwordExpired:
00089                                           /* report this during authz */
00090                                           rs->sr_err = LDAP_SUCCESS;
00091                                           /* fallthru */
00092                                    case PP_changeAfterReset:
00093                                           pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
00094                                    }
00095                             }
00096                      }
00097                      ldap_ld_free(ld,0,NULL,NULL);
00098               }
00099        }
00100        return LDAP_SUCCESS;
00101 }
00102 
00103 static int pam_uid2dn(nssov_info *ni, Operation *op,
00104        struct paminfo *pi)
00105 {
00106        struct berval sdn;
00107 
00108        BER_BVZERO(&pi->dn);
00109 
00110        if (!isvalidusername(&pi->uid)) {
00111               Debug(LDAP_DEBUG_ANY,"nssov_pam_uid2dn(%s): invalid user name\n",
00112                      pi->uid.bv_val,0,0);
00113               return NSLCD_PAM_USER_UNKNOWN;
00114        }
00115 
00116        if (ni->ni_pam_opts & NI_PAM_SASL2DN) {
00117               int hlen = global_host_bv.bv_len;
00118 
00119               /* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */
00120               sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen +
00121                      STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" );
00122               sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx );
00123               sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth",
00124                      pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val);
00125               slap_sasl2dn(op, &sdn, &pi->dn, 0);
00126               op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx );
00127        }
00128 
00129        /* If no luck, do a basic uid search */
00130        if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) {
00131               nssov_uid2dn(op, ni, &pi->uid, &pi->dn);
00132               if (!BER_BVISEMPTY(&pi->dn)) {
00133                      sdn = pi->dn;
00134                      dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx );
00135               }
00136        }
00137        if (BER_BVISEMPTY(&pi->dn)) {
00138               return NSLCD_PAM_USER_UNKNOWN;
00139        }
00140        return 0;
00141 }
00142 
00143 int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op,
00144        struct paminfo *pi)
00145 {
00146        int rc;
00147        slap_callback cb = {0};
00148        SlapReply rs = {REP_RESULT};
00149 
00150        pi->msg.bv_val = pi->pwd.bv_val;
00151        pi->msg.bv_len = 0;
00152        pi->authz = NSLCD_PAM_SUCCESS;
00153        BER_BVZERO(&pi->dn);
00154 
00155        rc = pam_uid2dn(ni, op, pi);
00156        if (rc) goto finish;
00157 
00158        if (BER_BVISEMPTY(&pi->pwd)) {
00159               rc = NSLCD_PAM_IGNORE;
00160               goto finish;
00161        }
00162 
00163        /* Should only need to do this once at open time, but there's always
00164         * the possibility that ppolicy will get loaded later.
00165         */
00166        if (!ppolicy_cid) {
00167               rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
00168                      &ppolicy_cid);
00169        }
00170        /* of course, 0 is a valid cid, but it won't be ppolicy... */
00171        if (ppolicy_cid) {
00172               op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
00173        }
00174        cb.sc_response = pam_bindcb;
00175        cb.sc_private = pi;
00176        op->o_callback = &cb;
00177        op->o_dn.bv_val[0] = 0;
00178        op->o_dn.bv_len = 0;
00179        op->o_ndn.bv_val[0] = 0;
00180        op->o_ndn.bv_len = 0;
00181        op->o_tag = LDAP_REQ_BIND;
00182        op->o_protocol = LDAP_VERSION3;
00183        op->orb_method = LDAP_AUTH_SIMPLE;
00184        op->orb_cred = pi->pwd;
00185        op->o_req_dn = pi->dn;
00186        op->o_req_ndn = pi->dn;
00187        slap_op_time( &op->o_time, &op->o_tincr );
00188        rc = op->o_bd->be_bind( op, &rs );
00189        memset(pi->pwd.bv_val,0,pi->pwd.bv_len);
00190        /* quirk: on successful bind, caller has to send result. we need
00191         * to make sure callbacks run.
00192         */
00193        if (rc == LDAP_SUCCESS)
00194               send_ldap_result(op, &rs);
00195        switch(rs.sr_err) {
00196        case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break;
00197        case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break;
00198        default: rc = NSLCD_PAM_AUTH_ERR; break;
00199        }
00200 finish:
00201        return rc;
00202 }
00203 
00204 int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
00205 {
00206        int32_t tmpint32;
00207        int rc;
00208        slap_callback cb = {0};
00209        char dnc[1024];
00210        char uidc[32];
00211        char svcc[256];
00212        char pwdc[256];
00213        struct berval sdn, dn;
00214        struct paminfo pi;
00215 
00216 
00217        READ_STRING(fp,uidc);
00218        pi.uid.bv_val = uidc;
00219        pi.uid.bv_len = tmpint32;
00220        READ_STRING(fp,dnc);
00221        pi.dn.bv_val = dnc;
00222        pi.dn.bv_len = tmpint32;
00223        READ_STRING(fp,svcc);
00224        pi.svc.bv_val = svcc;
00225        pi.svc.bv_len = tmpint32;
00226        READ_STRING(fp,pwdc);
00227        pi.pwd.bv_val = pwdc;
00228        pi.pwd.bv_len = tmpint32;
00229 
00230        Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",pi.uid.bv_val,0,0);
00231 
00232        rc = pam_do_bind(ni, fp, op, &pi);
00233 
00234 finish:
00235        WRITE_INT32(fp,NSLCD_VERSION);
00236        WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
00237        WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
00238        WRITE_BERVAL(fp,&pi.uid);
00239        WRITE_BERVAL(fp,&pi.dn);
00240        WRITE_INT32(fp,rc);
00241        WRITE_INT32(fp,pi.authz);   /* authz */
00242        WRITE_BERVAL(fp,&pi.msg);   /* authzmsg */
00243        return 0;
00244 }
00245 
00246 static struct berval grpmsg =
00247        BER_BVC("Access denied by group check");
00248 static struct berval hostmsg =
00249        BER_BVC("Access denied for this host");
00250 static struct berval svcmsg =
00251        BER_BVC("Access denied for this service");
00252 static struct berval uidmsg =
00253        BER_BVC("Access denied by UID check");
00254 
00255 static int pam_compare_cb(Operation *op, SlapReply *rs)
00256 {
00257        if (rs->sr_err == LDAP_COMPARE_TRUE)
00258               op->o_callback->sc_private = (void *)1;
00259        return LDAP_SUCCESS;
00260 }
00261 
00262 int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
00263 {
00264        struct berval dn, uid, svc, ruser, rhost, tty;
00265        struct berval authzmsg = BER_BVNULL;
00266        int32_t tmpint32;
00267        char dnc[1024];
00268        char uidc[32];
00269        char svcc[256];
00270        char ruserc[32];
00271        char rhostc[256];
00272        char ttyc[256];
00273        int rc;
00274        Entry *e = NULL;
00275        Attribute *a;
00276        slap_callback cb = {0};
00277 
00278        READ_STRING(fp,uidc);
00279        uid.bv_val = uidc;
00280        uid.bv_len = tmpint32;
00281        READ_STRING(fp,dnc);
00282        dn.bv_val = dnc;
00283        dn.bv_len = tmpint32;
00284        READ_STRING(fp,svcc);
00285        svc.bv_val = svcc;
00286        svc.bv_len = tmpint32;
00287        READ_STRING(fp,ruserc);
00288        ruser.bv_val = ruserc;
00289        ruser.bv_len = tmpint32;
00290        READ_STRING(fp,rhostc);
00291        rhost.bv_val = rhostc;
00292        rhost.bv_len = tmpint32;
00293        READ_STRING(fp,ttyc);
00294        tty.bv_val = ttyc;
00295        tty.bv_len = tmpint32;
00296 
00297        Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0);
00298 
00299        /* If we didn't do authc, we don't have a DN yet */
00300        if (BER_BVISEMPTY(&dn)) {
00301               struct paminfo pi;
00302               pi.uid = uid;
00303               pi.svc = svc;
00304 
00305               rc = pam_uid2dn(ni, op, &pi);
00306               if (rc) goto finish;
00307               dn = pi.dn;
00308        }
00309 
00310        /* See if they have access to the host and service */
00311        if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) {
00312               AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
00313               struct berval hostdn = BER_BVNULL;
00314               struct berval odn = op->o_ndn;
00315               SlapReply rs = {REP_RESULT};
00316               op->o_dn = dn;
00317               op->o_ndn = dn;
00318               {
00319                      nssov_mapinfo *mi = &ni->ni_maps[NM_host];
00320                      char fbuf[1024];
00321                      struct berval filter = {sizeof(fbuf),fbuf};
00322                      SlapReply rs2 = {REP_RESULT};
00323 
00324                      /* Lookup the host entry */
00325                      nssov_filter_byname(mi,0,&global_host_bv,&filter);
00326                      cb.sc_private = &hostdn;
00327                      cb.sc_response = nssov_name2dn_cb;
00328                      op->o_callback = &cb;
00329                      op->o_req_dn = mi->mi_base;
00330                      op->o_req_ndn = mi->mi_base;
00331                      op->ors_scope = mi->mi_scope;
00332                      op->ors_filterstr = filter;
00333                      op->ors_filter = str2filter_x(op, filter.bv_val);
00334                      op->ors_attrs = slap_anlist_no_attrs;
00335                      op->ors_tlimit = SLAP_NO_LIMIT;
00336                      op->ors_slimit = 2;
00337                      rc = op->o_bd->be_search(op, &rs2);
00338                      filter_free_x(op, op->ors_filter, 1);
00339 
00340                      if (BER_BVISEMPTY(&hostdn) &&
00341                             !BER_BVISEMPTY(&ni->ni_pam_defhost)) {
00342                             filter.bv_len = sizeof(fbuf);
00343                             filter.bv_val = fbuf;
00344                             rs_reinit(&rs2, REP_RESULT);
00345                             nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter);
00346                             op->ors_filterstr = filter;
00347                             op->ors_filter = str2filter_x(op, filter.bv_val);
00348                             rc = op->o_bd->be_search(op, &rs2);
00349                             filter_free_x(op, op->ors_filter, 1);
00350                      }
00351 
00352                      /* no host entry, no default host -> deny */
00353                      if (BER_BVISEMPTY(&hostdn)) {
00354                             rc = NSLCD_PAM_PERM_DENIED;
00355                             authzmsg = hostmsg;
00356                             goto finish;
00357                      }
00358               }
00359 
00360               cb.sc_response = pam_compare_cb;
00361               cb.sc_private = NULL;
00362               op->o_tag = LDAP_REQ_COMPARE;
00363               op->o_req_dn = hostdn;
00364               op->o_req_ndn = hostdn;
00365               ava.aa_desc = nssov_pam_svc_ad;
00366               ava.aa_value = svc;
00367               op->orc_ava = &ava;
00368               rc = op->o_bd->be_compare( op, &rs );
00369               if ( cb.sc_private == NULL ) {
00370                      authzmsg = svcmsg;
00371                      rc = NSLCD_PAM_PERM_DENIED;
00372                      goto finish;
00373               }
00374               op->o_dn = odn;
00375               op->o_ndn = odn;
00376        }
00377 
00378        /* See if they're a member of the group */
00379        if ((ni->ni_pam_opts & NI_PAM_USERGRP) &&
00380               !BER_BVISEMPTY(&ni->ni_pam_group_dn) &&
00381               ni->ni_pam_group_ad) {
00382               AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
00383               SlapReply rs = {REP_RESULT};
00384               op->o_callback = &cb;
00385               cb.sc_response = slap_null_cb;
00386               op->o_tag = LDAP_REQ_COMPARE;
00387               op->o_req_dn = ni->ni_pam_group_dn;
00388               op->o_req_ndn = ni->ni_pam_group_dn;
00389               ava.aa_desc = ni->ni_pam_group_ad;
00390               ava.aa_value = dn;
00391               op->orc_ava = &ava;
00392               rc = op->o_bd->be_compare( op, &rs );
00393               if ( rs.sr_err != LDAP_COMPARE_TRUE ) {
00394                      authzmsg = grpmsg;
00395                      rc = NSLCD_PAM_PERM_DENIED;
00396                      goto finish;
00397               }
00398        }
00399 
00400        /* We need to check the user's entry for these bits */
00401        if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) ||
00402               ni->ni_pam_template_ad ||
00403               ni->ni_pam_min_uid || ni->ni_pam_max_uid ) {
00404               rc = be_entry_get_rw( op, &dn, NULL, NULL, 0, &e );
00405               if (rc != LDAP_SUCCESS) {
00406                      rc = NSLCD_PAM_USER_UNKNOWN;
00407                      goto finish;
00408               }
00409        }
00410        if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) {
00411               a = attr_find(e->e_attrs, nssov_pam_host_ad);
00412               if (!a || attr_valfind( a,
00413                      SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
00414                      SLAP_MR_VALUE_OF_SYNTAX,
00415                      &global_host_bv, NULL, op->o_tmpmemctx )) {
00416                      rc = NSLCD_PAM_PERM_DENIED;
00417                      authzmsg = hostmsg;
00418                      goto finish;
00419               }
00420        }
00421        if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) {
00422               a = attr_find(e->e_attrs, nssov_pam_svc_ad);
00423               if (!a || attr_valfind( a,
00424                      SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH |
00425                      SLAP_MR_VALUE_OF_SYNTAX,
00426                      &svc, NULL, op->o_tmpmemctx )) {
00427                      rc = NSLCD_PAM_PERM_DENIED;
00428                      authzmsg = svcmsg;
00429                      goto finish;
00430               }
00431        }
00432 
00433 /* from passwd.c */
00434 #define UIDN_KEY     2
00435 
00436        if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) {
00437               int id;
00438               char *tmp;
00439               nssov_mapinfo *mi = &ni->ni_maps[NM_passwd];
00440               a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc);
00441               if (!a) {
00442                      rc = NSLCD_PAM_PERM_DENIED;
00443                      authzmsg = uidmsg;
00444                      goto finish;
00445               }
00446               id = (int)strtol(a->a_vals[0].bv_val,&tmp,0);
00447               if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') {
00448                      rc = NSLCD_PAM_PERM_DENIED;
00449                      authzmsg = uidmsg;
00450                      goto finish;
00451               }
00452               if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) ||
00453                      (ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) {
00454                      rc = NSLCD_PAM_PERM_DENIED;
00455                      authzmsg = uidmsg;
00456                      goto finish;
00457               }
00458        }
00459 
00460        if (ni->ni_pam_template_ad) {
00461               a = attr_find(e->e_attrs, ni->ni_pam_template_ad);
00462               if (a)
00463                      uid = a->a_vals[0];
00464               else if (!BER_BVISEMPTY(&ni->ni_pam_template))
00465                      uid = ni->ni_pam_template;
00466        }
00467        rc = NSLCD_PAM_SUCCESS;
00468 
00469 finish:
00470        WRITE_INT32(fp,NSLCD_VERSION);
00471        WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
00472        WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
00473        WRITE_BERVAL(fp,&uid);
00474        WRITE_BERVAL(fp,&dn);
00475        WRITE_INT32(fp,rc);
00476        WRITE_BERVAL(fp,&authzmsg);
00477        if (e) {
00478               be_entry_release_r(op, e);
00479        }
00480        return 0;
00481 }
00482 
00483 static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action)
00484 {
00485        struct berval dn, uid, svc, tty, rhost, ruser;
00486        int32_t tmpint32;
00487        char dnc[1024];
00488        char svcc[256];
00489        char uidc[32];
00490        char ttyc[32];
00491        char rhostc[256];
00492        char ruserc[32];
00493        slap_callback cb = {0};
00494        SlapReply rs = {REP_RESULT};
00495        char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
00496        struct berval timestamp, bv[2], *nbv;
00497        time_t stamp;
00498        Modifications mod;
00499 
00500        READ_STRING(fp,uidc);
00501        uid.bv_val = uidc;
00502        uid.bv_len = tmpint32;
00503        READ_STRING(fp,dnc);
00504        dn.bv_val = dnc;
00505        dn.bv_len = tmpint32;
00506        READ_STRING(fp,svcc);
00507        svc.bv_val = svcc;
00508        svc.bv_len = tmpint32;
00509        READ_STRING(fp,ttyc);
00510        tty.bv_val = ttyc;
00511        tty.bv_len = tmpint32;
00512        READ_STRING(fp,rhostc);
00513        rhost.bv_val = rhostc;
00514        rhost.bv_len = tmpint32;
00515        READ_STRING(fp,ruserc);
00516        ruser.bv_val = ruserc;
00517        ruser.bv_len = tmpint32;
00518        READ_INT32(fp,stamp);
00519 
00520        Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n",
00521               action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0);
00522 
00523        if (!dn.bv_len || !ni->ni_pam_sessions) return 0;
00524 
00525        {
00526               int i, found=0;
00527               for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) {
00528                      if (ni->ni_pam_sessions[i].bv_len != svc.bv_len)
00529                             continue;
00530                      if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) {
00531                             found = 1;
00532                             break;
00533                      }
00534               }
00535               if (!found) return 0;
00536        }
00537 
00538        slap_op_time( &op->o_time, &op->o_tincr );
00539        timestamp.bv_len = sizeof(timebuf);
00540        timestamp.bv_val = timebuf;
00541        if (action == NSLCD_ACTION_PAM_SESS_O )
00542               stamp = op->o_time;
00543        slap_timestamp( &stamp, &timestamp );
00544        bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len +
00545               tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF("    (@)");
00546        bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx );
00547        sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)",
00548               timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val,
00549               ruser.bv_val, rhost.bv_val);
00550        
00551        mod.sml_numvals = 1;
00552        mod.sml_values = bv;
00553        BER_BVZERO(&bv[1]);
00554        attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx );
00555        mod.sml_nvalues = nbv;
00556        mod.sml_desc = ad_loginStatus;
00557        mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD :
00558               LDAP_MOD_DELETE;
00559        mod.sml_flags = SLAP_MOD_INTERNAL;
00560        mod.sml_next = NULL;
00561 
00562        cb.sc_response = slap_null_cb;
00563        op->o_callback = &cb;
00564        op->o_tag = LDAP_REQ_MODIFY;
00565        op->o_dn = op->o_bd->be_rootdn;
00566        op->o_ndn = op->o_bd->be_rootndn;
00567        op->orm_modlist = &mod;
00568        op->orm_no_opattrs = 1;
00569        op->o_req_dn = dn;
00570        op->o_req_ndn = dn;
00571        op->o_bd->be_modify( op, &rs );
00572        if ( mod.sml_next ) {
00573               slap_mods_free( mod.sml_next, 1 );
00574        }
00575        ber_bvarray_free_x( nbv, op->o_tmpmemctx );
00576 
00577        WRITE_INT32(fp,NSLCD_VERSION);
00578        WRITE_INT32(fp,action);
00579        WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
00580        WRITE_INT32(fp,op->o_time);
00581        return 0;
00582 }
00583 
00584 int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op)
00585 {
00586        return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_O);
00587 }
00588 
00589 int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op)
00590 {
00591        return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_C);
00592 }
00593 
00594 int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op)
00595 {
00596        struct berval npw;
00597        int32_t tmpint32;
00598        char dnc[1024];
00599        char uidc[32];
00600        char opwc[256];
00601        char npwc[256];
00602        char svcc[256];
00603        struct paminfo pi;
00604        int rc;
00605 
00606        READ_STRING(fp,uidc);
00607        pi.uid.bv_val = uidc;
00608        pi.uid.bv_len = tmpint32;
00609        READ_STRING(fp,dnc);
00610        pi.dn.bv_val = dnc;
00611        pi.dn.bv_len = tmpint32;
00612        READ_STRING(fp,svcc);
00613        pi.svc.bv_val = svcc;
00614        pi.svc.bv_len = tmpint32;
00615        READ_STRING(fp,opwc);
00616        pi.pwd.bv_val = opwc;
00617        pi.pwd.bv_len = tmpint32;
00618        READ_STRING(fp,npwc);
00619        npw.bv_val = npwc;
00620        npw.bv_len = tmpint32;
00621 
00622        Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s\n",
00623               pi.dn.bv_val,pi.uid.bv_val,0);
00624 
00625        BER_BVZERO(&pi.msg);
00626 
00627        /* This is a prelim check */
00628        if (BER_BVISEMPTY(&pi.dn)) {
00629               rc = pam_do_bind(ni,fp,op,&pi);
00630               if (rc == NSLCD_PAM_IGNORE)
00631                      rc = NSLCD_PAM_SUCCESS;
00632        } else {
00633               BerElementBuffer berbuf;
00634               BerElement *ber = (BerElement *)&berbuf;
00635               struct berval bv;
00636               SlapReply rs = {REP_RESULT};
00637               slap_callback cb = {0};
00638 
00639               ber_init_w_nullc(ber, LBER_USE_DER);
00640               ber_printf(ber, "{");
00641               if (!BER_BVISEMPTY(&pi.pwd))
00642                      ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
00643                             &pi.pwd);
00644               if (!BER_BVISEMPTY(&npw))
00645                      ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
00646                             &npw);
00647               ber_printf(ber, "N}");
00648               ber_flatten2(ber, &bv, 0);
00649               op->o_tag = LDAP_REQ_EXTENDED;
00650               op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
00651               op->ore_reqdata = &bv;
00652               op->o_dn = pi.dn;
00653               op->o_ndn = pi.dn;
00654               op->o_callback = &cb;
00655               op->o_conn->c_authz_backend = op->o_bd;
00656               cb.sc_response = slap_null_cb;
00657               op->o_bd = frontendDB;
00658               rc = op->o_bd->be_extended(op, &rs);
00659               if (rs.sr_text)
00660                      ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
00661               if (rc == LDAP_SUCCESS)
00662                      rc = NSLCD_PAM_SUCCESS;
00663               else
00664                      rc = NSLCD_PAM_PERM_DENIED;
00665        }
00666        WRITE_INT32(fp,NSLCD_VERSION);
00667        WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
00668        WRITE_INT32(fp,NSLCD_RESULT_BEGIN);
00669        WRITE_BERVAL(fp,&pi.uid);
00670        WRITE_BERVAL(fp,&pi.dn);
00671        WRITE_INT32(fp,rc);
00672        WRITE_BERVAL(fp,&pi.msg);
00673        return 0;
00674 }
00675 
00676 int nssov_pam_init()
00677 {
00678        int code = 0;
00679        const char *text;
00680        if (!ad_loginStatus)
00681               code = slap_str2ad("loginStatus", &ad_loginStatus, &text);
00682 
00683        return code;
00684 }