openldap/contrib/slapd-modules/nssov/pam.c
Kurt Zeilenga a5abeb92ec Update contrib notices to reflect that they are distributed as part of
OpenLDAP Software (though they may not necessarily be supported by the
OpenLDAP Project).  Assistance in updating ACKNOWLEDGEMENTS welcomed.
2009-08-16 22:55:23 +00:00

670 lines
17 KiB
C

/* pam.c - pam processing routines */
/* $OpenLDAP$ */
/* This work is part of OpenLDAP Software <http://www.openldap.org/>.
*
* Copyright 2008-2009 The OpenLDAP Foundation.
* Portions Copyright 2008 by Howard Chu, Symas Corp.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted only as authorized by the OpenLDAP
* Public License.
*
* A copy of this license is available in the file LICENSE in the
* top-level directory of the distribution or, alternatively, at
* <http://www.OpenLDAP.org/license.html>.
*/
#include "nssov.h"
#include "lutil.h"
static int ppolicy_cid;
static AttributeDescription *ad_loginStatus;
const char *at_loginStatus =
"( 1.3.6.1.4.1.4745.1.20.1 "
"NAME ( 'loginStatus' ) "
"DESC 'Currently logged in sessions for a user' "
"EQUALITY caseIgnoreMatch "
"SUBSTR caseIgnoreSubstringsMatch "
"ORDERING caseIgnoreOrderingMatch "
"SYNTAX OMsDirectoryString "
"USAGE directoryOperation )";
struct paminfo {
struct berval uid;
struct berval dn;
struct berval svc;
struct berval pwd;
int authz;
struct berval msg;
};
static int pam_bindcb(
Operation *op, SlapReply *rs)
{
struct paminfo *pi = op->o_callback->sc_private;
LDAPControl *ctrl = ldap_control_find(LDAP_CONTROL_PASSWORDPOLICYRESPONSE,
rs->sr_ctrls, NULL);
if (ctrl) {
LDAP *ld;
ber_int_t expire, grace;
LDAPPasswordPolicyError error;
ldap_create(&ld);
if (ld) {
int rc = ldap_parse_passwordpolicy_control(ld,ctrl,
&expire,&grace,&error);
if (rc == LDAP_SUCCESS) {
if (expire >= 0) {
char *unit = "seconds";
if (expire > 60) {
expire /= 60;
unit = "minutes";
}
if (expire > 60) {
expire /= 60;
unit = "hours";
}
if (expire > 24) {
expire /= 24;
unit = "days";
}
#if 0 /* Who warns about expiration so far in advance? */
if (expire > 7) {
expire /= 7;
unit = "weeks";
}
if (expire > 4) {
expire /= 4;
unit = "months";
}
if (expire > 12) {
expire /= 12;
unit = "years";
}
#endif
pi->msg.bv_len = sprintf(pi->msg.bv_val,
"\nWARNING: Password expires in %d %s\n", expire, unit);
} else if (grace > 0) {
pi->msg.bv_len = sprintf(pi->msg.bv_val,
"Password expired; %d grace logins remaining",
grace);
pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
} else if (error != PP_noError) {
ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0,
&pi->msg);
switch (error) {
case PP_passwordExpired:
/* report this during authz */
rs->sr_err = LDAP_SUCCESS;
/* fallthru */
case PP_changeAfterReset:
pi->authz = NSLCD_PAM_NEW_AUTHTOK_REQD;
}
}
}
ldap_ld_free(ld,0,NULL,NULL);
}
}
return LDAP_SUCCESS;
}
int pam_do_bind(nssov_info *ni,TFILE *fp,Operation *op,
struct paminfo *pi)
{
int rc;
slap_callback cb = {0};
SlapReply rs = {REP_RESULT};
struct berval sdn;
pi->msg.bv_val = pi->pwd.bv_val;
pi->msg.bv_len = 0;
pi->authz = NSLCD_PAM_SUCCESS;
BER_BVZERO(&pi->dn);
if (!isvalidusername(&pi->uid)) {
Debug(LDAP_DEBUG_ANY,"nssov_pam_do_bind(%s): invalid user name\n",
pi->uid.bv_val,0,0);
rc = NSLCD_PAM_USER_UNKNOWN;
goto finish;
}
if (ni->ni_pam_opts & NI_PAM_SASL2DN) {
int hlen = global_host_bv.bv_len;
/* cn=<service>+uid=<user>,cn=<host>,cn=pam,cn=auth */
sdn.bv_len = pi->uid.bv_len + pi->svc.bv_len + hlen +
STRLENOF( "cn=+uid=,cn=,cn=pam,cn=auth" );
sdn.bv_val = op->o_tmpalloc( sdn.bv_len + 1, op->o_tmpmemctx );
sprintf(sdn.bv_val, "cn=%s+uid=%s,cn=%s,cn=pam,cn=auth",
pi->svc.bv_val, pi->uid.bv_val, global_host_bv.bv_val);
slap_sasl2dn(op, &sdn, &pi->dn, 0);
op->o_tmpfree( sdn.bv_val, op->o_tmpmemctx );
}
/* If no luck, do a basic uid search */
if (BER_BVISEMPTY(&pi->dn) && (ni->ni_pam_opts & NI_PAM_UID2DN)) {
nssov_uid2dn(op, ni, &pi->uid, &pi->dn);
if (!BER_BVISEMPTY(&pi->dn)) {
sdn = pi->dn;
dnNormalize( 0, NULL, NULL, &sdn, &pi->dn, op->o_tmpmemctx );
}
}
BER_BVZERO(&sdn);
if (BER_BVISEMPTY(&pi->dn)) {
rc = NSLCD_PAM_USER_UNKNOWN;
goto finish;
}
if (BER_BVISEMPTY(&pi->pwd)) {
rc = NSLCD_PAM_IGNORE;
goto finish;
}
/* Should only need to do this once at open time, but there's always
* the possibility that ppolicy will get loaded later.
*/
if (!ppolicy_cid) {
rc = slap_find_control_id(LDAP_CONTROL_PASSWORDPOLICYREQUEST,
&ppolicy_cid);
}
/* of course, 0 is a valid cid, but it won't be ppolicy... */
if (ppolicy_cid) {
op->o_ctrlflag[ppolicy_cid] = SLAP_CONTROL_NONCRITICAL;
}
cb.sc_response = pam_bindcb;
cb.sc_private = pi;
op->o_callback = &cb;
op->o_dn.bv_val[0] = 0;
op->o_dn.bv_len = 0;
op->o_ndn.bv_val[0] = 0;
op->o_ndn.bv_len = 0;
op->o_tag = LDAP_REQ_BIND;
op->o_protocol = LDAP_VERSION3;
op->orb_method = LDAP_AUTH_SIMPLE;
op->orb_cred = pi->pwd;
op->o_req_dn = pi->dn;
op->o_req_ndn = pi->dn;
slap_op_time( &op->o_time, &op->o_tincr );
rc = op->o_bd->be_bind( op, &rs );
memset(pi->pwd.bv_val,0,pi->pwd.bv_len);
/* quirk: on successful bind, caller has to send result. we need
* to make sure callbacks run.
*/
if (rc == LDAP_SUCCESS)
send_ldap_result(op, &rs);
switch(rs.sr_err) {
case LDAP_SUCCESS: rc = NSLCD_PAM_SUCCESS; break;
case LDAP_INVALID_CREDENTIALS: rc = NSLCD_PAM_AUTH_ERR; break;
default: rc = NSLCD_PAM_AUTH_ERR; break;
}
finish:
return rc;
}
int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
{
int32_t tmpint32;
int rc;
slap_callback cb = {0};
SlapReply rs = {REP_RESULT};
char dnc[1024];
char uidc[32];
char svcc[256];
char pwdc[256];
struct berval sdn, dn;
struct paminfo pi;
READ_STRING_BUF2(fp,uidc,sizeof(uidc));
pi.uid.bv_val = uidc;
pi.uid.bv_len = tmpint32;
READ_STRING_BUF2(fp,dnc,sizeof(dnc));
pi.dn.bv_val = dnc;
pi.dn.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(svcc));
pi.svc.bv_val = svcc;
pi.svc.bv_len = tmpint32;
READ_STRING_BUF2(fp,pwdc,sizeof(pwdc));
pi.pwd.bv_val = pwdc;
pi.pwd.bv_len = tmpint32;
Debug(LDAP_DEBUG_TRACE,"nssov_pam_authc(%s)\n",pi.uid.bv_val,0,0);
rc = pam_do_bind(ni, fp, op, &pi);
finish:
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
WRITE_BERVAL(fp,&pi.uid);
WRITE_BERVAL(fp,&pi.dn);
WRITE_INT32(fp,rc);
WRITE_INT32(fp,pi.authz); /* authz */
WRITE_BERVAL(fp,&pi.msg); /* authzmsg */
return 0;
}
static struct berval grpmsg =
BER_BVC("Access denied by group check");
static struct berval hostmsg =
BER_BVC("Access denied for this host");
static struct berval svcmsg =
BER_BVC("Access denied for this service");
static struct berval uidmsg =
BER_BVC("Access denied by UID check");
int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
{
struct berval dn, uid, svc, ruser, rhost, tty;
struct berval authzmsg = BER_BVNULL;
int32_t tmpint32;
char dnc[1024];
char uidc[32];
char svcc[256];
char ruserc[32];
char rhostc[256];
char ttyc[256];
int rc = NSLCD_PAM_SUCCESS;
Entry *e = NULL;
Attribute *a;
SlapReply rs = {REP_RESULT};
slap_callback cb = {0};
READ_STRING_BUF2(fp,uidc,sizeof(uidc));
uid.bv_val = uidc;
uid.bv_len = tmpint32;
READ_STRING_BUF2(fp,dnc,sizeof(dnc));
dn.bv_val = dnc;
dn.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(svcc));
svc.bv_val = svcc;
svc.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(ruserc));
ruser.bv_val = ruserc;
ruser.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(rhostc));
rhost.bv_val = rhostc;
rhost.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(ttyc));
tty.bv_val = ttyc;
tty.bv_len = tmpint32;
Debug(LDAP_DEBUG_TRACE,"nssov_pam_authz(%s)\n",dn.bv_val,0,0);
/* We don't do authorization if they weren't authenticated by us */
if (BER_BVISEMPTY(&dn)) {
rc = NSLCD_PAM_USER_UNKNOWN;
goto finish;
}
/* See if they have access to the host and service */
if ((ni->ni_pam_opts & NI_PAM_HOSTSVC) && nssov_pam_svc_ad) {
AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
struct berval hostdn = BER_BVNULL;
struct berval odn = op->o_ndn;
op->o_dn = dn;
op->o_ndn = dn;
{
nssov_mapinfo *mi = &ni->ni_maps[NM_host];
char fbuf[1024];
struct berval filter = {sizeof(fbuf),fbuf};
SlapReply rs2 = {REP_RESULT};
/* Lookup the host entry */
nssov_filter_byname(mi,0,&global_host_bv,&filter);
cb.sc_private = &hostdn;
cb.sc_response = nssov_name2dn_cb;
op->o_callback = &cb;
op->o_req_dn = mi->mi_base;
op->o_req_ndn = mi->mi_base;
op->ors_scope = mi->mi_scope;
op->ors_filterstr = filter;
op->ors_filter = str2filter_x(op, filter.bv_val);
op->ors_attrs = slap_anlist_no_attrs;
op->ors_tlimit = SLAP_NO_LIMIT;
op->ors_slimit = 2;
rc = op->o_bd->be_search(op, &rs2);
filter_free_x(op, op->ors_filter, 1);
if (BER_BVISEMPTY(&hostdn) &&
!BER_BVISEMPTY(&ni->ni_pam_defhost)) {
filter.bv_len = sizeof(fbuf);
filter.bv_val = fbuf;
memset(&rs2, 0, sizeof(rs2));
rs2.sr_type = REP_RESULT;
nssov_filter_byname(mi,0,&ni->ni_pam_defhost,&filter);
op->ors_filterstr = filter;
op->ors_filter = str2filter_x(op, filter.bv_val);
rc = op->o_bd->be_search(op, &rs2);
filter_free_x(op, op->ors_filter, 1);
}
/* no host entry, no default host -> deny */
if (BER_BVISEMPTY(&hostdn)) {
rc = NSLCD_PAM_PERM_DENIED;
authzmsg = hostmsg;
goto finish;
}
}
cb.sc_response = slap_null_cb;
cb.sc_private = NULL;
op->o_tag = LDAP_REQ_COMPARE;
op->o_req_dn = hostdn;
op->o_req_ndn = hostdn;
ava.aa_desc = nssov_pam_svc_ad;
ava.aa_value = svc;
op->orc_ava = &ava;
rc = op->o_bd->be_compare( op, &rs );
if ( rs.sr_err != LDAP_COMPARE_TRUE ) {
authzmsg = svcmsg;
rc = NSLCD_PAM_PERM_DENIED;
goto finish;
}
op->o_dn = odn;
op->o_ndn = odn;
}
/* See if they're a member of the group */
if ((ni->ni_pam_opts & NI_PAM_USERGRP) &&
!BER_BVISEMPTY(&ni->ni_pam_group_dn) &&
ni->ni_pam_group_ad) {
AttributeAssertion ava = ATTRIBUTEASSERTION_INIT;
op->o_callback = &cb;
cb.sc_response = slap_null_cb;
op->o_tag = LDAP_REQ_COMPARE;
op->o_req_dn = ni->ni_pam_group_dn;
op->o_req_ndn = ni->ni_pam_group_dn;
ava.aa_desc = ni->ni_pam_group_ad;
ava.aa_value = dn;
op->orc_ava = &ava;
rc = op->o_bd->be_compare( op, &rs );
if ( rs.sr_err != LDAP_COMPARE_TRUE ) {
authzmsg = grpmsg;
rc = NSLCD_PAM_PERM_DENIED;
goto finish;
}
}
/* We need to check the user's entry for these bits */
if ((ni->ni_pam_opts & (NI_PAM_USERHOST|NI_PAM_USERSVC)) ||
ni->ni_pam_template_ad ||
ni->ni_pam_min_uid || ni->ni_pam_max_uid ) {
rc = be_entry_get_rw( op, &dn, NULL, NULL, 0, &e );
if (rc != LDAP_SUCCESS) {
rc = NSLCD_PAM_USER_UNKNOWN;
goto finish;
}
}
if ((ni->ni_pam_opts & NI_PAM_USERHOST) && nssov_pam_host_ad) {
a = attr_find(e->e_attrs, nssov_pam_host_ad);
if (!a || value_find_ex( nssov_pam_host_ad,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
a->a_vals, &global_host_bv, op->o_tmpmemctx )) {
rc = NSLCD_PAM_PERM_DENIED;
authzmsg = hostmsg;
goto finish;
}
}
if ((ni->ni_pam_opts & NI_PAM_USERSVC) && nssov_pam_svc_ad) {
a = attr_find(e->e_attrs, nssov_pam_svc_ad);
if (!a || value_find_ex( nssov_pam_svc_ad,
SLAP_MR_ATTRIBUTE_VALUE_NORMALIZED_MATCH,
a->a_vals, &svc, op->o_tmpmemctx )) {
rc = NSLCD_PAM_PERM_DENIED;
authzmsg = svcmsg;
goto finish;
}
}
/* from passwd.c */
#define UIDN_KEY 2
if (ni->ni_pam_min_uid || ni->ni_pam_max_uid) {
int id;
char *tmp;
nssov_mapinfo *mi = &ni->ni_maps[NM_host];
a = attr_find(e->e_attrs, mi->mi_attrs[UIDN_KEY].an_desc);
if (!a) {
rc = NSLCD_PAM_PERM_DENIED;
authzmsg = uidmsg;
goto finish;
}
id = (int)strtol(a->a_vals[0].bv_val,&tmp,0);
if (a->a_vals[0].bv_val[0] == '\0' || *tmp != '\0') {
rc = NSLCD_PAM_PERM_DENIED;
authzmsg = uidmsg;
goto finish;
}
if ((ni->ni_pam_min_uid && id < ni->ni_pam_min_uid) ||
(ni->ni_pam_max_uid && id > ni->ni_pam_max_uid)) {
rc = NSLCD_PAM_PERM_DENIED;
authzmsg = uidmsg;
goto finish;
}
}
if (ni->ni_pam_template_ad) {
a = attr_find(e->e_attrs, ni->ni_pam_template_ad);
if (a)
uid = a->a_vals[0];
else if (!BER_BVISEMPTY(&ni->ni_pam_template))
uid = ni->ni_pam_template;
}
finish:
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHZ);
WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
WRITE_BERVAL(fp,&uid);
WRITE_BERVAL(fp,&dn);
WRITE_INT32(fp,rc);
WRITE_BERVAL(fp,&authzmsg);
if (e) {
be_entry_release_r(op, e);
}
return 0;
}
static int pam_sess(nssov_info *ni,TFILE *fp,Operation *op,int action)
{
struct berval dn, uid, svc, tty, rhost, ruser;
int32_t tmpint32;
char dnc[1024];
char svcc[256];
char uidc[32];
char ttyc[32];
char rhostc[256];
char ruserc[32];
slap_callback cb = {0};
SlapReply rs = {REP_RESULT};
char timebuf[LDAP_LUTIL_GENTIME_BUFSIZE];
struct berval timestamp, bv[2], *nbv;
time_t stamp;
Modifications mod;
READ_STRING_BUF2(fp,uidc,sizeof(uidc));
uid.bv_val = uidc;
uid.bv_len = tmpint32;
READ_STRING_BUF2(fp,dnc,sizeof(dnc));
dn.bv_val = dnc;
dn.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(svcc));
svc.bv_val = svcc;
svc.bv_len = tmpint32;
READ_STRING_BUF2(fp,ttyc,sizeof(ttyc));
tty.bv_val = ttyc;
tty.bv_len = tmpint32;
READ_STRING_BUF2(fp,rhostc,sizeof(rhostc));
rhost.bv_val = rhostc;
rhost.bv_len = tmpint32;
READ_STRING_BUF2(fp,ruserc,sizeof(ruserc));
ruser.bv_val = ruserc;
ruser.bv_len = tmpint32;
READ_INT32(fp,stamp);
Debug(LDAP_DEBUG_TRACE,"nssov_pam_sess_%c(%s)\n",
action==NSLCD_ACTION_PAM_SESS_O ? 'o' : 'c', dn.bv_val,0);
if (!dn.bv_len || !ni->ni_pam_sessions) return 0;
{
int i, found=0;
for (i=0; !BER_BVISNULL(&ni->ni_pam_sessions[i]); i++) {
if (ni->ni_pam_sessions[i].bv_len != svc.bv_len)
continue;
if (!strcasecmp(ni->ni_pam_sessions[i].bv_val, svc.bv_val)) {
found = 1;
break;
}
}
if (!found) return 0;
}
slap_op_time( &op->o_time, &op->o_tincr );
timestamp.bv_len = sizeof(timebuf);
timestamp.bv_val = timebuf;
if (action == NSLCD_ACTION_PAM_SESS_O )
stamp = op->o_time;
slap_timestamp( &stamp, &timestamp );
bv[0].bv_len = timestamp.bv_len + global_host_bv.bv_len + svc.bv_len +
tty.bv_len + ruser.bv_len + rhost.bv_len + STRLENOF(" (@)");
bv[0].bv_val = op->o_tmpalloc( bv[0].bv_len+1, op->o_tmpmemctx );
sprintf(bv[0].bv_val, "%s %s %s %s (%s@%s)",
timestamp.bv_val, global_host_bv.bv_val, svc.bv_val, tty.bv_val,
ruser.bv_val, rhost.bv_val);
mod.sml_numvals = 1;
mod.sml_values = bv;
BER_BVZERO(&bv[1]);
attr_normalize( ad_loginStatus, bv, &nbv, op->o_tmpmemctx );
mod.sml_nvalues = nbv;
mod.sml_desc = ad_loginStatus;
mod.sml_op = action == NSLCD_ACTION_PAM_SESS_O ? LDAP_MOD_ADD :
LDAP_MOD_DELETE;
mod.sml_flags = SLAP_MOD_INTERNAL;
mod.sml_next = NULL;
cb.sc_response = slap_null_cb;
op->o_callback = &cb;
op->o_tag = LDAP_REQ_MODIFY;
op->o_dn = op->o_bd->be_rootdn;
op->o_ndn = op->o_bd->be_rootndn;
op->orm_modlist = &mod;
op->orm_no_opattrs = 1;
op->o_req_dn = dn;
op->o_req_ndn = dn;
op->o_bd->be_modify( op, &rs );
if ( mod.sml_next ) {
slap_mods_free( mod.sml_next, 1 );
}
ber_bvarray_free_x( nbv, op->o_tmpmemctx );
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,action);
WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
WRITE_INT32(fp,op->o_time);
return 0;
}
int pam_sess_o(nssov_info *ni,TFILE *fp,Operation *op)
{
return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_O);
}
int pam_sess_c(nssov_info *ni,TFILE *fp,Operation *op)
{
return pam_sess(ni,fp,op,NSLCD_ACTION_PAM_SESS_C);
}
int pam_pwmod(nssov_info *ni,TFILE *fp,Operation *op)
{
struct berval npw;
int32_t tmpint32;
char dnc[1024];
char uidc[32];
char opwc[256];
char npwc[256];
char svcc[256];
struct paminfo pi;
int rc;
READ_STRING_BUF2(fp,uidc,sizeof(uidc));
pi.uid.bv_val = uidc;
pi.uid.bv_len = tmpint32;
READ_STRING_BUF2(fp,dnc,sizeof(dnc));
pi.dn.bv_val = dnc;
pi.dn.bv_len = tmpint32;
READ_STRING_BUF2(fp,svcc,sizeof(svcc));
pi.svc.bv_val = svcc;
pi.svc.bv_len = tmpint32;
READ_STRING_BUF2(fp,opwc,sizeof(opwc));
pi.pwd.bv_val = opwc;
pi.pwd.bv_len = tmpint32;
READ_STRING_BUF2(fp,npwc,sizeof(npwc));
npw.bv_val = npwc;
npw.bv_len = tmpint32;
Debug(LDAP_DEBUG_TRACE,"nssov_pam_pwmod(%s), %s\n",
pi.dn.bv_val,pi.uid.bv_val,0);
BER_BVZERO(&pi.msg);
/* This is a prelim check */
if (BER_BVISEMPTY(&pi.dn)) {
rc = pam_do_bind(ni,fp,op,&pi);
if (rc == NSLCD_PAM_IGNORE)
rc = NSLCD_PAM_SUCCESS;
} else {
BerElementBuffer berbuf;
BerElement *ber = (BerElement *)&berbuf;
struct berval bv;
SlapReply rs = {REP_RESULT};
slap_callback cb = {0};
ber_init_w_nullc(ber, LBER_USE_DER);
ber_printf(ber, "{");
if (!BER_BVISEMPTY(&pi.pwd))
ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_OLD,
&pi.pwd);
if (!BER_BVISEMPTY(&npw))
ber_printf(ber, "tO", LDAP_TAG_EXOP_MODIFY_PASSWD_NEW,
&npw);
ber_printf(ber, "N}");
ber_flatten2(ber, &bv, 0);
op->o_tag = LDAP_REQ_EXTENDED;
op->ore_reqoid = slap_EXOP_MODIFY_PASSWD;
op->ore_reqdata = &bv;
op->o_dn = pi.dn;
op->o_ndn = pi.dn;
op->o_callback = &cb;
op->o_conn->c_authz_backend = op->o_bd;
cb.sc_response = slap_null_cb;
op->o_bd = frontendDB;
rc = op->o_bd->be_extended(op, &rs);
if (rs.sr_text)
ber_str2bv(rs.sr_text, 0, 0, &pi.msg);
if (rc == LDAP_SUCCESS)
rc = NSLCD_PAM_SUCCESS;
else
rc = NSLCD_PAM_PERM_DENIED;
}
WRITE_INT32(fp,NSLCD_VERSION);
WRITE_INT32(fp,NSLCD_ACTION_PAM_PWMOD);
WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
WRITE_BERVAL(fp,&pi.uid);
WRITE_BERVAL(fp,&pi.dn);
WRITE_INT32(fp,rc);
WRITE_BERVAL(fp,&pi.msg);
return 0;
}
int nssov_pam_init()
{
int code = 0;
if (!ad_loginStatus)
code = register_at( at_loginStatus, &ad_loginStatus, 0 );
return code;
}