]> git.sur5r.net Git - openldap/commitdiff
Move tmpluser to authz call; add ppolicy support to authc
authorHoward Chu <hyc@openldap.org>
Sat, 18 Apr 2009 23:12:36 +0000 (23:12 +0000)
committerHoward Chu <hyc@openldap.org>
Sat, 18 Apr 2009 23:12:36 +0000 (23:12 +0000)
contrib/slapd-modules/nssov/pam.c

index 2f69d94902d4f11ff4e584a4934043b828cd9d91..1ee873b0e47c6504b7c9b291ed23a7e9902b7958 100644 (file)
 
 #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;
 }