Tue Jul 22 2014 14:32:54 EDT from dothebart @ Uncensored

8.25? Now?



Here are a few of my local patches to 8.24 (the vcard bit I submitted earlier, it's here just for completeness) :

Feel free to use or not.  The smtp send fix on empty 'F' field you've noted above.

 

 

--- citadel-8.24/context.h    2014-01-27 09:42:11.000000000 -0600
+++ citadel-8.24patched/context.h    2014-07-21 14:01:24.009299829 -0500
@@ -149,6 +149,8 @@
     long *cached_msglist;            /* results of the previous CtdlForEachMessage() */
     int cached_num_msgs;
 
+    char vcard_updated_by_ldap;        /* !0 iff ldap changed the vcard, treat as aide update */
+
     AsyncIO *IO;                /* if this session has AsyncIO going on... */
 };
 
--- citadel-8.16/control.c    2013-03-07 14:44:12.000000000 -0600
+++ citadel-new/control.c    2014-03-10 23:07:41.705783000 -0500
@@ -423,6 +423,11 @@
         cprintf("%d\n", config.c_guest_logins);
         cprintf("%d\n", config.c_port_number);
         cprintf("%d\n", config.c_ctdluid);
+#ifdef HAVE_LDAP
+        cprintf("%s\n", config.c_ldap_searchstring);
+#else
+        cprintf("\n");
+#endif
         cprintf("000\n");
     }
 
@@ -688,6 +693,12 @@
             case 69:
                 config.c_ctdluid = atoi(buf);
                 break;
+#ifdef HAVE_LDAP
+            case 70:
+                safestrncpy(config.c_ldap_searchstring, buf,
+                        sizeof config.c_ldap_searchstring);
+                break;
+#endif
             }
             ++a;
         }
--- citadel-8.16/include/ctdl_module.h    2013-03-07 14:44:12.000000000 -0600
+++ citadel-new/include/ctdl_module.h    2014-03-10 23:07:41.721783000 -0500
@@ -357,6 +357,7 @@
     time_t c_pop3_fastest;
     int c_spam_flag_only;
     int c_guest_logins;
+    char c_ldap_searchstring[256];
 };
 
 extern struct config config;
--- citadel-8.16/ldap.c    2013-03-07 14:44:11.000000000 -0600
+++ citadel-new/ldap.c    2014-03-12 18:12:04.221417792 -0500
@@ -109,13 +109,17 @@
 
     tv.tv_sec = 10;
     tv.tv_usec = 0;
-
-    if (config.c_auth_mode == AUTHMODE_LDAP_AD) {
-        sprintf(searchstring, "(sAMAccountName=%s)", username);
-    }
-    else {
-        sprintf(searchstring, "(&(objectclass=posixAccount)(uid=%s))", username);
-    }
+    if (config.c_ldap_searchstring[0]==0) {
+      if (config.c_auth_mode == AUTHMODE_LDAP_AD) {
+        strcpy(config.c_ldap_searchstring, "(sAMAccountName=%s)");
+      }
+      else {
+        strcpy(config.c_ldap_searchstring, "(&(objectclass=posixAccount)(uid=%s))");
+      }
+    }
+    sprintf(searchstring, config.c_ldap_searchstring, username);
+   
+   
 
     syslog(LOG_DEBUG, "LDAP search: %s\n", searchstring);
     (void) ldap_search_ext_s(
@@ -249,6 +253,38 @@
     return(1);
 }
 
+//return !0 iff property changed.
+int vcard_set_props_iff_different(struct vCard *v,char *propname,int numvals, char **vals) {
+    int i;
+    char *oldval;
+    for(i=0;i<numvals;i++) {
+      oldval = vcard_get_prop(v,propname,0,i,0);
+      if (oldval == NULL) break;
+      if (strcmp(vals[i],oldval)) break;
+    }
+    if (i!=numvals) {
+        for(i=0;i<numvals;i++) vcard_set_prop(v,propname,vals[i],(i==0) ? 0 : 1);
+        return 1;
+    }
+    return 0;
+}
+
+
+//return !0 iff property changed.
+int vcard_set_one_prop_iff_different(struct vCard *v,char *propname, char *newfmt, ...) {
+    va_list args;
+    char *newvalue;
+    int changed_something;
+    va_start(args,newfmt);
+    if (-1==vasprintf(&newvalue,newfmt,args)) {
+        syslog(LOG_ALERT, "Out of memory!\n");
+        return 0;
+    }
+    changed_something = vcard_set_props_iff_different(v,propname,1,&newvalue);
+    va_end(args);
+    free(newvalue);
+    return changed_something;
+}
 
 /*
  * Learn LDAP attributes and stuff them into the vCard.
@@ -257,23 +293,166 @@
 int Ctdl_LDAP_to_vCard(char *ldap_dn, struct vCard *v)
 {
     int changed_something = 0;
+    LDAP *ldserver = NULL;
+    int i;
+    struct timeval tv;
+    LDAPMessage *search_result = NULL;
+    LDAPMessage *entry = NULL;
+    char **givenName;
+    char **sn;
+    char **cn;
+    char **initials;
+    char **o;
+    char **street;
+    char **l;
+    char **st;
+    char **postalCode;
+    char **telephoneNumber;
+    char **mobile;
+    char **homePhone;
+    char **facsimileTelephoneNumber;
+    char **mail;
+    char **uid;
+    char **homeDirectory;
+    char **uidNumber;
+    char **loginShell;
+    char **gidNumber;
+    char **c;
+    char **title;
+    char **uuid;
+    char *attrs[] = { "*","+",NULL};
 
     if (!ldap_dn) return(0);
     if (!v) return(0);
+    ldserver = ldap_init(config.c_ldap_host, config.c_ldap_port);
+    if (ldserver == NULL) {
+        syslog(LOG_ALERT, "LDAP: Could not connect to %s:%d : %s\n",
+            config.c_ldap_host, config.c_ldap_port,
+            strerror(errno)
+        );
+        return(0);
+    }
+
+    ldap_set_option(ldserver, LDAP_OPT_PROTOCOL_VERSION, &ctdl_require_ldap_version);
+    ldap_set_option(ldserver, LDAP_OPT_REFERRALS, (void *)LDAP_OPT_OFF);
+
+    striplt(config.c_ldap_bind_dn);
+    striplt(config.c_ldap_bind_pw);
+    syslog(LOG_DEBUG, "LDAP bind DN: %s\n", config.c_ldap_bind_dn);
+    i = ldap_simple_bind_s(ldserver,
+        (!IsEmptyStr(config.c_ldap_bind_dn) ? config.c_ldap_bind_dn : NULL),
+        (!IsEmptyStr(config.c_ldap_bind_pw) ? configc_ldap_bind_pw : NULL)
+    );
+    if (i != LDAP_SUCCESS) {
+        syslog(LOG_ALERT, "LDAP: Cannot bind: %s (%d)\n", ldap_err2string(i), i);
+        return(0);
+    }
+
+    tv.tv_sec = 10;
+    tv.tv_usec = 0;
+
+    syslog(LOG_DEBUG, "LDAP search: %s\n", ldap_dn);
+    (void) ldap_search_ext_s(
+        ldserver,                /* ld                */
+        ldap_dn,                /* base                */
+        LDAP_SCOPE_SUBTREE,        /* scope            */
+        NULL,                    /* filter            */
+        attrs,                    /* attrs (all attributes)    */
+        0,                        /* attrsonly (attrs + values)    */
+        NULL,                    /* serverctrls (none)        */
+        NULL,                    /* clientctrls (none)        */
+        &tv,                    /* timeout            */
+        1,                        /* sizelimit (1 result max)    */
+        &search_result            /* res                */
+    );
+   
+    /* Ignore the return value of ldap_search_ext_s().  Sometimes it returns an error even when
+     * the search succeeds.  Instead, we check to see whether search_result is still NULL.
+     */
+     
+    if (search_result == NULL) {
+        syslog(LOG_DEBUG, "LDAP search: zero results were returned\n");
+        ldap_unbind(ldserver);
+        return(0);
+    }
 
-    /*
-     * FIXME this is a stub function
-     *
-     * ldap_dn will contain the DN of the user, and v will contain a pointer to
-     * the vCard that needs to be (re-)populated.  Put the requisite LDAP code here.
-     *
-    vcard_set_prop(v, "email;internet", xxx, 0);
-     *
-     * return nonzero to tell the caller that we made changes that need to be saved
-    changed_something = 1;
-     *
+    /* At this point we've got at least one result from our query.  If there are multiple
+     * results, we still only look at the first one.
      */
+    entry = ldap_first_entry(ldserver, search_result);
+    if (entry) {
+        syslog(LOG_DEBUG, "LDAP search, got user details for vcard.\n");
+        givenName=ldap_get_values(ldserver, search_result, "givenName");
+        sn=ldap_get_values(ldserver, search_result, "sn");
+        cn=ldap_get_values(ldserver, search_result, "cn");
+        initials=ldap_get_values(ldserver, search_result, "initials");
+        title=ldap_get_values(ldserver, search_result, "title");
+        o=ldap_get_values(ldserver, search_result, "o");
+        street=ldap_get_values(ldserver, search_result, "street");
+        l=ldap_get_values(ldserver, search_result, "l");
+        st=ldap_get_values(ldserver, search_result, "st");
+        postalCode=ldap_get_values(ldserver, search_result, "postalCode");
+        telephoneNumber=ldap_get_values(ldserver, search_result, "telephoneNumber");
+        mobile=ldap_get_values(ldserver, search_result, "mobile");
+        homePhone=ldap_get_values(ldserver, search_result, "homePhone");
+        facsimileTelephoneNumber=ldap_get_values(ldserver, search_result, "facsimileTelephoneNumber");
+        mail=ldap_get_values(ldserver, search_result, "mail");
+        uid=ldap_get_values(ldserver, search_result, "uid");
+        homeDirectory=ldap_get_values(ldserver, search_result, "homeDirectory");
+        uidNumber=ldap_get_values(ldserver, search_result, "uidNumber");
+        loginShell=ldap_get_values(ldserver, search_result, "loginShell");
+        gidNumber=ldap_get_values(ldserver, search_result, "gidNumber");
+        c=ldap_get_values(ldserver, search_result, "c");
+        uuid=ldap_get_values(ldserver, search_result, "entryUUID");
+
+        if (street && l && st && postalCode && c) changed_something |= vcard_set_one_prop_iff_different(v,"adr",";;%s;%s;%s;%s;%s",street[0],l[0],st[0],postalCode[0],c[0]);
+        if (telephoneNumber) changed_something |= vcard_set_one_prop_iff_different(v,"tel;work","%s",telephoneNumber[0]);
+        if (facsimileTelephoneNumber) changed_something |= vcard_set_one_prop_iff_different(v,"tel;fax","%s",facsimileTelephoneNumber[0]);
+        if (mobile) changed_something |= vcard_set_one_prop_iff_different(v,"tel;cell","%s",mobile[0]);
+        if (homePhone) changed_something |= vcard_set_one_prop_iff_different(v,"tel;home","%s",homePhone[0]);
+        if (givenName && sn) {
+            if (initials)
+              changed_something |= vcard_set_one_prop_iff_different(v,"n","%s;%s;%s",sn[0],givenName[0],initials[0]);
+            else
+              changed_something |= vcard_set_one_prop_iff_different(v,"n","%s;%s",sn[0],givenName[0]);
+        }
+        if (mail) {
+            changed_something |= vcard_set_props_iff_different(v,"email;internet",ldap_count_values(mail),mail);
+        }
+        if (uuid) changed_something |= vcard_set_one_prop_iff_different(v,"uid","%s",uuid[0]);
+        if (o) changed_something |= vcard_set_one_prop_iff_different(v,"org","%s",o[0]);
+        if (cn) changed_something |= vcard_set_one_prop_iff_different(v,"fn","%s",cn[0]);
+        if (title) changed_something |= vcard_set_one_prop_iff_different(v,"title","%s",title[0]);
+       
+        if (givenName) ldap_value_free(givenName);
+        if (initials) ldap_value_free(initials);
+        if (sn) ldap_value_free(sn);
+        if (cn) ldap_value_free(cn);
+        if (o) ldap_value_free(o);
+        if (street) ldap_value_free(street);
+        if (l) ldap_value_free(l);
+        if (st) ldap_value_free(st);
+        if (postalCode) ldap_value_free(postalCode);
+        if (telephoneNumber) ldap_value_free(telephoneNumber);
+        if (mobile) ldap_value_free(mobile);
+        if (homePhone) ldap_value_free(homePhone);
+        if (facsimileTelephoneNumber) ldap_value_free(facsimileTelephoneNumber);
+        if (mail) ldap_value_free(mail);
+        if (uid) ldap_value_free(uid);
+        if (homeDirectory) ldap_value_free(homeDirectory);
+        if (uidNumber) ldap_value_free(uidNumber);
+        if (loginShell) ldap_value_free(loginShell);
+        if (gidNumber) ldap_value_free(gidNumber);
+        if (c) ldap_value_free(c);
+        if (title) ldap_value_free(title);
+        if (uuid) ldap_value_free(uuid);
+    }
+    /* free the results */
+    ldap_msgfree(search_result);
 
+    /* unbind so we can go back in as the authenticating user */
+    ldap_unbind(ldserver);
+   
     return(changed_something);    /* tell the caller whether we made any changes */
 }
 
--- citadel-8.16/modules/migrate/serv_migrate.c    2013-03-07 14:44:11.000000000 -0600
+++ citadel-new/modules/migrate/serv_migrate.c    2014-03-10 23:07:41.761783000 -0500
@@ -437,6 +437,7 @@
     client_write("<c_ldap_base_dn>", 16);    xml_strout(config.c_ldap_base_dn);    client_write("</c_ldap_base_dn>\n", 18);
     client_write("<c_ldap_bind_dn>", 16);    xml_strout(config.c_ldap_bind_dn);    client_write("</c_ldap_bind_dn>\n", 18);
     client_write("<c_ldap_bind_pw>", 16);    xml_strout(config.c_ldap_bind_pw);    client_write("</c_ldap_bind_pw>\n", 18);
+    client_write("<c_ldap_searchstring>", 16);    xml_strout(config.c_ldap_searchstring);    client_write("</c_ldap_searchstring>\n", 18);
     cprintf("<c_msa_port>%d</c_msa_port>\n", config.c_msa_port);
     cprintf("<c_imaps_port>%d</c_imaps_port>\n", config.c_imaps_port);
     cprintf("<c_pop3s_port>%d</c_pop3s_port>\n", config.c_pop3s_port);
@@ -671,6 +672,7 @@
     else if (!strcasecmp(el, "c_ldap_base_dn"))        safestrncpy(config.c_ldap_base_dn, migr_chardata, sizeof config.c_ldap_base_dn);
     else if (!strcasecmp(el, "c_ldap_bind_dn"))        safestrncpy(config.c_ldap_bind_dn, migr_chardata, sizeof config.c_ldap_bind_dn);
     else if (!strcasecmp(el, "c_ldap_bind_pw"))        safestrncpy(config.c_ldap_bind_pw, migr_chardata, sizeof config.c_ldap_bind_pw);
+    else if (!strcasecmp(el, "c_ldap_searchstring"))    safestrncpy(config.c_ldap_searchstring, migr_chardata, sizeof config.c_ldap_searchstring);
     else if (!strcasecmp(el, "c_msa_port"))            config.c_msa_port = atoi(migr_chardata);
     else if (!strcasecmp(el, "c_imaps_port"))        config.c_imaps_port = atoi(migr_chardata);
     else if (!strcasecmp(el, "c_pop3s_port"))        config.c_pop3s_port = atoi(migr_chardata);
--- citadel-816/modules/vcard/serv_vcard.c    2013-03-07 14:44:11.000000000 -0600
+++ citadel-new/modules/vcard/serv_vcard.c    2014-03-12 14:57:47.527404126 -0500
@@ -341,17 +341,16 @@
     int yes_my_citadel_config = 0;
     int yes_any_vcard_room = 0;
 
-    if (!CCC->logged_in) return(0);    /* Only do this if logged in. */
+    if ((!CCC->logged_in) && (CCC->vcard_updated_by_ldap==0)) return(0);    /* Only do this if logged in, or if ldap changed the vcard. */
 
     /* Is this some user's "My Citadel Config" room? */
     if (((CCC->room.QRflags & QR_MAILBOX) != 0) &&
           (!strcasecmp(&CCC->room.QRname[11], USERCONFIGROOM)) ) {
         /* Yes, we want to do this */
         yes_my_citadel_config = 1;
-
 #ifdef VCARD_SAVES_BY_AIDES_ONLY
-        /* Prevent non-aides from performing registration changes */
-        if (CCC->user.axlevel < AxAideU) {
+        /* Prevent non-aides from performing registration changes, but ldap is ok. */
+        if ((CCC->user.axlevel < AxAideU) && (CCC->vcard_updated_by_ldap==0)) {
             return(1);
         }
 #endif
@@ -387,12 +386,13 @@
     if (v == NULL) return(0);    /* no vCards were found in this message */
 
     /* If users cannot create their own accounts, they cannot re-register either. */
-    if ( (yes_my_citadel_config) && (config.c_disable_newu) && (CCC->user.axlevel < AxAideU) ) {
+    if ( (yes_my_citadel_config) && (config.c_disable_newu) && (CCC->user.axlevel < AxAideU) && (CCC->vcard_updated_by_ldap==0) ) {
         return(1);
     }
 
     vcard_get_prop(v, "fn", 1, 0, 0);
 
+
     if (yes_my_citadel_config) {
         /* Bingo!  The user is uploading a new vCard, so
          * delete the old one.  First, figure out which user
@@ -520,7 +520,7 @@
     char roomname[ROOMNAMELEN];
 
     if (msg->cm_format_type != 4) return(0);
-    if (!CCC->logged_in) return(0);    /* Only do this if logged in. */
+    if ((!CCC->logged_in) && (CCC->vcard_updated_by_ldap==0)) return(0);    /* Only do this if logged in, or if ldap changed the vcard. */
 
     /* We're interested in user config rooms only. */
 
@@ -541,6 +541,8 @@
     ptr = msg->cm_fields['M'];
     if (ptr == NULL) return(0);
 
+    CCC->vcard_updated_by_ldap=0;  //As this will write LDAP's previous changes, disallow LDAP change auth until next LDAP change.
+
     NewStrBufDupAppendFlush(&CCC->StatusMessage, NULL, NULL, 0);
 
     StrBufPrintf(CCC->StatusMessage, "%d\n", LISTING_FOLLOWS);
@@ -883,6 +885,26 @@
     }
     vcard_add_prop(v, "email;internet", buf);
 
+#ifdef HAVE_LDAP
+    /*
+     * Is this an LDAP session?  If so, copy various LDAP attributes from the directory entry
+     * into the user's vCard.
+     */
+    if ((config.c_auth_mode == AUTHMODE_LDAP) || (config.c_auth_mode == AUTHMODE_LDAP_AD)) {
+            uid_t ldap_uid;
+        int found_user;
+            char ldap_cn[512];
+            char ldap_dn[512];
+        found_user = CtdlTryUserLDAP(usbuf->fullname, ldap_dn, sizeof ldap_dn, ldap_cn, sizeof ldap_cn, &ldap_uid);
+            if (found_user == 0) {
+        if (Ctdl_LDAP_to_vCard(ldap_dn, v)) {
+            //Allow global address book and internet directory update without login long enough to write this.
+            CC->vcard_updated_by_ldap++;  //Otherwise we'll only update the user config.
+            syslog(LOG_DEBUG, "LDAP Created Initial Vcard for %s\n",usbuf->fullname);
+        }
+        }
+    }
+#endif
 
     vcard_write_user(usbuf, v);
     vcard_free(v);
@@ -1249,6 +1271,8 @@
         v = vcard_get_user(&CCC->user);
         if (v) {
             if (Ctdl_LDAP_to_vCard(CCC->ldap_dn, v)) {
+                CCC->vcard_updated_by_ldap++; //Make sure changes make it to the global address book and internet directory, not just the user config.
+                syslog(LOG_DEBUG, "LDAP Detected vcard change.\n");
                 vcard_write_user(&CCC->user, v);
             }
         }

Reply via email to