Move tmpluser to authz call; add ppolicy support to authc

This commit is contained in:
Howard Chu 2009-04-18 23:12:36 +00:00
parent 51b87202e0
commit d7fa38c003

View File

@ -17,9 +17,80 @@
#include <security/pam_modules.h>
static int pam_nullcb(
static int ppolicy_cid;
struct bindinfo {
int authz;
struct berval msg;
};
static int pam_bindcb(
Operation *op, SlapReply *rs)
{
struct bindinfo *bi = 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
bi->msg.bv_len = sprintf(bi->msg.bv_val,
"\nWARNING: Password expires in %d %s\n", expire, unit);
} else if (grace > 0) {
bi->msg.bv_len = sprintf(bi->msg.bv_val,
"Password expired; %d grace logins remaining",
grace);
bi->authz = PAM_NEW_AUTHTOK_REQD;
} else if (error != PP_noError) {
ber_str2bv(ldap_passwordpolicy_err2txt(error), 0, 0,
&bi->msg);
switch (error) {
case PP_passwordExpired:
/* report this during authz */
rs->sr_err = LDAP_SUCCESS;
/* fallthru */
case PP_changeAfterReset:
bi->authz = PAM_NEW_AUTHTOK_REQD;
}
}
}
ldap_ld_free(ld,0,NULL,NULL);
}
}
return LDAP_SUCCESS;
}
@ -34,6 +105,11 @@ int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
char pwdc[256];
struct berval uid, svc, pwd, sdn, dn;
int hlen;
struct bindinfo bi;
bi.authz = PAM_SUCCESS;
bi.msg.bv_val = pwdc;
bi.msg.bv_len = 0;
READ_STRING_BUF2(fp,uidc,sizeof(uidc));
uid.bv_val = uidc;
@ -76,8 +152,19 @@ int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
}
BER_BVZERO(&sdn);
/* TODO: add ppolicy control */
cb.sc_response = pam_nullcb;
/* 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 = &bi;
op->o_callback = &cb;
op->o_dn.bv_val[0] = 0;
op->o_dn.bv_len = 0;
@ -90,8 +177,13 @@ int pam_authc(nssov_info *ni,TFILE *fp,Operation *op)
op->o_req_dn = dn;
op->o_req_ndn = dn;
slap_op_time( &op->o_time, &op->o_tincr );
op->o_bd->be_bind( op, &rs );
rc = op->o_bd->be_bind( op, &rs );
memset(pwd.bv_val,0,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 = PAM_SUCCESS; break;
case LDAP_INVALID_CREDENTIALS: rc = PAM_AUTH_ERR; break;
@ -103,10 +195,9 @@ finish:
WRITE_INT32(fp,NSLCD_ACTION_PAM_AUTHC);
WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
WRITE_INT32(fp,rc);
WRITE_INT32(fp,PAM_SUCCESS); /* authz */
WRITE_INT32(fp,bi.authz); /* authz */
WRITE_BERVAL(fp,&dn);
WRITE_BERVAL(fp,&sdn); /* authzmsg */
WRITE_BERVAL(fp,&sdn); /* tmpluser */
WRITE_BERVAL(fp,&bi.msg); /* authzmsg */
return 0;
}
@ -114,6 +205,7 @@ int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
{
struct berval dn, svc;
struct berval authzmsg = BER_BVNULL;
struct berval tmpluser = BER_BVNULL;
int32_t tmpint32;
char dnc[1024];
char svcc[256];
@ -132,6 +224,7 @@ int pam_authz(nssov_info *ni,TFILE *fp,Operation *op)
WRITE_INT32(fp,NSLCD_RESULT_SUCCESS);
WRITE_INT32(fp,PAM_SUCCESS);
WRITE_BERVAL(fp,&authzmsg);
WRITE_BERVAL(fp,&tmpluser);
return 0;
}