Build fixes
[public/libpam-csc.git] / pam_csc.c
index bbfbb23..3896e2d 100644 (file)
--- a/pam_csc.c
+++ b/pam_csc.c
@@ -7,13 +7,25 @@
 #include <stdlib.h>
 #include <stdbool.h>
 #include <string.h>
-#include <security/pam_modules.h>
 #include <security/pam_appl.h>
+#include <security/pam_modules.h>
 #include <ldap.h>
 #include <sasl/sasl.h>
 #include <syslog.h>
 #include <pwd.h>
 
+#ifndef LDAP_SASL_QUIET
+#  define LDAP_SASL_QUIET 0
+#endif
+
+#ifndef LOG_AUTHPRIV
+#  define LOG_AUTHPRIV LOG_AUTH
+#endif
+
+#ifndef PAM_EXTERN
+#  define PAM_EXTERN extern
+#endif
+
 #define PAM_CSC_CSC_BASE_DN         "ou=People,dc=csclub,dc=uwaterloo,dc=ca"
 #define PAM_CSC_CSCF_URI \
     "ldaps://eponina.student.cs.uwaterloo.ca" \
@@ -165,7 +177,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
     int i;
     time_t cur_time;
     struct tm* local_time;
-    int long_term;
+    int long_term, term_month;
     static const char term_chars[] = {'w', 's', 'f'};
     char cur_term[6], prev_term[6];
     LDAP *ld_csc = NULL, *ld_cscf = NULL;
@@ -173,7 +185,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
     FILE* pass_file = NULL;
     char* username_escaped = NULL;
     char *filter_csc = NULL, *filter_cscf = NULL;
-    char *attrs_csc[] = {"objectClass", "term", NULL}, 
+    char *attrs_csc[] = {"objectClass", "term", "nonMemberTerm", NULL},
         *attrs_cscf[] = {"objectClass", NULL};
     bool expired;
     const char* pam_rhost;
@@ -181,7 +193,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
     LDAPMessage *res_csc = NULL, *res_cscf = NULL;
     struct timeval timeout = {PAM_CSC_LDAP_TIMEOUT, 0};
     LDAPMessage* entry = NULL;
-    char **values = NULL, **values_iter = NULL;
+    char **values = NULL, **nmvalues = NULL, **values_iter = NULL;
 
     /* determine username */
     if((pam_get_user(pamh, &username, NULL) != PAM_SUCCESS) || !username)
@@ -219,6 +231,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
     sprintf(cur_term, "%c%d", term_chars[long_term % 3], long_term / 3);
     long_term--;
     sprintf(prev_term, "%c%d", term_chars[long_term % 3], long_term / 3);
+    term_month = local_time->tm_mon % 4;
 
     /* connect to CSC */
     WARN_LDAP( ldap_create(&ld_csc) )
@@ -256,8 +269,8 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
     }
 
     /* create CSC request string */
-    WARN_ZERO( filter_csc = malloc(100 + strlen(username_escaped)) )
-    sprintf(filter_csc, "(&(uid=%s)(|(&(objectClass=member)(|(term=%s)(term=%s)))(!(objectClass=member))))", username_escaped, cur_term, prev_term);
+    WARN_ZERO( filter_csc = malloc(140 + strlen(username_escaped)) )
+    sprintf(filter_csc, "(&(uid=%s)(|(&(objectClass=member)(|(term=%s)(term=%s)(nonMemberTerm=%s)(nonMemberTerm=%s)))(!(objectClass=member))))", username_escaped, cur_term, prev_term, cur_term, prev_term);
 
     /* issue CSC request */
     WARN_NEG1( msg_csc = ldap_search(ld_csc, PAM_CSC_CSC_BASE_DN, 
@@ -291,7 +304,9 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
     /* get CSC entry */
     WARN_ZERO( entry = ldap_first_entry(ld_csc, res_csc) )
     values = ldap_get_values(ld_csc, entry, "term");
-    if(!values)
+    nmvalues = ldap_get_values(ld_csc, entry, "nonMemberTerm");
+
+    if(!values && !nmvalues)
     {
         syslog(LOG_AUTHPRIV | LOG_NOTICE, PAM_CSC_SYSLOG_NOT_A_MEMBER, 
             username);
@@ -301,25 +316,50 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
 
     /* iterate through term attributes */
     expired = true;
-    values_iter = values;
-    while(*values_iter)
-    {
-        if(strcmp(*values_iter, cur_term) == 0)
+    if (values) {
+        values_iter = values;
+        while(*values_iter)
         {
-            /* user is registered in current term */
-            expired = false;
-            break;
+            if(strcmp(*values_iter, cur_term) == 0)
+            {
+                /* user is registered in current term */
+                expired = false;
+                break;
+            }
+            values_iter++;
+        }
+    }
+    if (nmvalues) {
+        values_iter = nmvalues;
+        while (*values_iter) {
+            if (strcmp(*values_iter, cur_term) == 0) {
+                expired = false;
+                break;
+            }
+            values_iter++;
         }
-        values_iter++;
     }
 
     /* check if account is expired */
     if(expired)
     {
-        /* show notice and continue */
-        pam_csc_print_message(pamh, PAM_CSC_EXPIRED_MSG, PAM_TEXT_INFO);
-        syslog(LOG_AUTHPRIV | LOG_NOTICE, PAM_CSC_SYSLOG_EXPIRED_ERROR, 
-            username);
+        /* we allow once month grace-period */
+        if(term_month == 0)
+        {
+            /* show notice and continue */
+            pam_csc_print_message(pamh, PAM_CSC_EXPIRED_MSG, PAM_TEXT_INFO);
+            syslog(LOG_AUTHPRIV | LOG_NOTICE, PAM_CSC_SYSLOG_EXPIRED_ERROR, 
+                username);
+        }
+        else
+        {
+            /* show notice and disallow login */
+            pam_csc_print_message(pamh, PAM_CSC_EXPIRED_MSG, PAM_ERROR_MSG);
+            syslog(LOG_AUTHPRIV | LOG_NOTICE, PAM_CSC_SYSLOG_EXPIRED_WARNING, 
+                username);
+            retval = PAM_AUTH_ERR;
+            goto cleanup;
+        }
     }
 
     if(cscf)
@@ -343,6 +383,7 @@ PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const c
 cleanup:
 
     if(values) ldap_value_free(values);
+    if(nmvalues) ldap_value_free(nmvalues);
     if(res_csc) ldap_msgfree(res_csc);
     if(res_cscf) ldap_msgfree(res_cscf);
     if(ld_csc) ldap_unbind(ld_csc);