pam_ldap vs ppolicy patches

View: New views
1 Messages — Rating Filter:   Alert me  

pam_ldap vs ppolicy patches

by Pierre-Yves Bonnetain :: Rate this Message:

Reply to Author | View Threaded | Show Only this Message

Hello,

We have posted several patches on pam_ldap bugzilla, to correct annoying
problems in the interaction between pam_ldap and an OpenLDAP+ppolicy
server. Since other guys may have ran into the same problems we did, and
knowing it's better to have several people test those patches, we are
sending them here.

Those patches are given AS IS, without any kind of assurance whatsoever.
They could kill your server, run away with your life savings or prevent
you from drinking beer. You've been warned.

Patches are against pam_ldap-183. They should not be hard to adapt to
pam_ldap-184.

A few explanations :
First block (lines 2085,2093 versus 2085,2097) corrects bug 324
("Account Locked" message not displayed to the user). This is THE one
patch you should be careful about, it may very well break some PAM
semantics somewhere.
Second and third block (lines 2830,2835 vs 2834,2841 and lines 2843,2848
vs 2849,2893) correct bug 323 (Password expiration notice and grace
logins notice not displayed to the user).
Last block (lines 3093,3099 vs 3138,3148) corrects bug 321 (Password
constraint violations not displayed to the user when using EXOP_SEND_OLD
password change protocol).

Bug reports are
http://bugzilla.padl.com/show_bug.cgi?id=321
http://bugzilla.padl.com/show_bug.cgi?id=323
http://bugzilla.padl.com/show_bug.cgi?id=324

Feel free to add, comment or correct those patches. Send complaints and
flames to /dev/null.

Cheers,
-- Pierre-Yves Bonnetain

*** pam_ldap-183/pam_ldap.c 2006-10-19 15:22:27.000000000 +0200
--- pam_ldap-183-new/pam_ldap.c 2007-05-18 10:54:14.000000000 +0200
***************
*** 2085,2093 ****
       break;
     case POLICY_ERROR_CHANGE_AFTER_RESET:
     case POLICY_ERROR_PASSWORD_EXPIRED:
       rc = LDAP_SUCCESS;
       break;
!    case POLICY_ERROR_ACCOUNT_LOCKED:
     case POLICY_ERROR_PASSWORD_MOD_NOT_ALLOWED:
     case POLICY_ERROR_MUST_SUPPLY_OLD_PASSWORD:
     case POLICY_ERROR_INSUFFICIENT_PASSWORD_QUALITY:
--- 2085,2097 ----
       break;
     case POLICY_ERROR_CHANGE_AFTER_RESET:
     case POLICY_ERROR_PASSWORD_EXPIRED:
+    /* "Account locked" should be returned and displayed IF
+     * wanted by the admin (ppolicy_use_lockout config
+     * parameter). */
+    case POLICY_ERROR_ACCOUNT_LOCKED:
       rc = LDAP_SUCCESS;
       break;
!    /* case POLICY_ERROR_ACCOUNT_LOCKED: */
     case POLICY_ERROR_PASSWORD_MOD_NOT_ALLOWED:
     case POLICY_ERROR_MUST_SUPPLY_OLD_PASSWORD:
     case POLICY_ERROR_INSUFFICIENT_PASSWORD_QUALITY:
***************
*** 2830,2835 ****
--- 2834,2841 ----
     const char *user, const char *password)
  {
    int rc = PAM_SUCCESS;
+   int subrc;
+   struct pam_conv *appconv;
 
    if (session->info == NULL)
      {
***************
*** 2843,2848 ****
--- 2849,2893 ----
      return rc;
 
    rc = _connect_as_user (pamh, session, password);
+
+   /* Py Bonnetain, B&A Consultants
+    * It may be very interesting for users to know their password will
+    * soon expire (if pwdExpireWarning is set). So we process this information
+    * when the Ldap server sends it.
+    */
+   if (session->info->password_expiration_time ||
+       session->info->grace_logins_remaining) {
+       if (pam_get_item (pamh, PAM_CONV, (CONST_ARG void **) &appconv) ==
+           PAM_SUCCESS) {
+        char errmsg[1024];
+  int valeur;
+
+  if (session->info->password_expiration_time > 0) {
+      /* Try to compute some meaningful timespan. */
+      if (session->info->password_expiration_time > 86400) {
+          int days_left =
+      (int) (session->info->password_expiration_time / 86400);
+                   snprintf (errmsg, sizeof errmsg,
+      "Your password expires in %d days", days_left);
+      } else if (session->info->password_expiration_time > 3600) {
+          int hours_left =
+      (int) (session->info->password_expiration_time / 3600);
+                   snprintf (errmsg, sizeof errmsg,
+            "Your password expires in %d hours", hours_left);
+      } else {
+                   snprintf (errmsg, sizeof errmsg,
+      "Your password expires in %d minutes",
+                    (int) (session->info->password_expiration_time / 60));
+      }
+  } else if (session->info->grace_logins_remaining > 0) {
+               snprintf (errmsg, sizeof errmsg,
+       "Your password has expired ; %d extra connections left",
+                session->info->grace_logins_remaining);
+  }
+  valeur = _conv_sendmsg (appconv, errmsg, PAM_TEXT_INFO, 0);
+       }
+   }
+  
    _session_reopen (session);
    _connect_anonymously (session);
    return rc;
***************
*** 3093,3099 ****
        break;
      } /* end switch */
 
!   if (session->conf->password_type != PASSWORD_EXOP)
      {
        rc = ldap_modify_s (session->ld, session->info->userdn, mods);
        if (rc != LDAP_SUCCESS)
--- 3138,3148 ----
        break;
      } /* end switch */
 
!   /* Py Bonnetain, B&A Consultants
!    * This block of code should NOT be run when PASSWORD_EXOP_SEND_OLD either.
!    */
!   if (session->conf->password_type != PASSWORD_EXOP &&
!       session->conf->password_type != PASSWORD_EXOP_SEND_OLD)
      {
        rc = ldap_modify_s (session->ld, session->info->userdn, mods);
        if (rc != LDAP_SUCCESS)