From d7fa38c003a21ab4b8de582909a3998a27c336c5 Mon Sep 17 00:00:00 2001 From: Howard Chu Date: Sat, 18 Apr 2009 23:12:36 +0000 Subject: [PATCH] Move tmpluser to authz call; add ppolicy support to authc --- contrib/slapd-modules/nssov/pam.c | 107 ++++++++++++++++++++++++++++-- 1 file changed, 100 insertions(+), 7 deletions(-) diff --git a/contrib/slapd-modules/nssov/pam.c b/contrib/slapd-modules/nssov/pam.c index 2f69d94902..1ee873b0e4 100644 --- a/contrib/slapd-modules/nssov/pam.c +++ b/contrib/slapd-modules/nssov/pam.c @@ -17,9 +17,80 @@ #include -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; } -- 2.39.5