summaryrefslogtreecommitdiff
blob: ecc960d7bffeda2b15d5ebf0bdf5119646a194e8 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
Allows login by uid rather than the mail address on the cyrus imapd server [Version: 2.3.9]

diff -r 2ebe14b7db9d configure
--- a/configure	Mon Oct 27 18:47:12 2008 +0100
+++ b/configure	Mon Oct 27 18:48:18 2008 +0100
@@ -19667,7 +19667,7 @@
 done
 
 IMAP_COM_ERR_LIBS="${COM_ERR_LIBS}"
-IMAP_LIBS="${LIB_SASL} ${LIBS} ${SQL_LIBS}"
+IMAP_LIBS="${LIB_SASL} -lldap -llber ${LIBS} ${SQL_LIBS}"
 
 
 
diff -r 2ebe14b7db9d imap/global.c
--- a/imap/global.c	Mon Oct 27 18:47:12 2008 +0100
+++ b/imap/global.c	Mon Oct 27 18:48:18 2008 +0100
@@ -52,6 +52,9 @@
 #include <sys/types.h>
 #include <netinet/in.h>
 #include <sys/stat.h>
+
+#include <ldap.h>
+#include <lber.h>
 
 #if HAVE_UNISTD_H
 # include <unistd.h>
@@ -378,6 +381,18 @@
     char *domain = NULL;
     int len = strlen(user);
     char buf[81];
+    const char *uri;
+    const char *base;
+    const char *binddn;
+    const char *bindpw;
+    struct timeval timeout;
+    char filter[255];
+    LDAP *handle;
+    LDAPMessage *res;
+    LDAPMessage *entry;
+    struct berval** vals;
+
+    int rc;
 
     /* check for domain */
     if (config_virtdomains &&
@@ -396,6 +411,49 @@
     }
 
     if (config_virtdomains) {
+        if (config_virtdomains == IMAP_ENUM_VIRTDOMAINS_LDAP) {
+           uri = config_getstring(IMAPOPT_LDAP_URI);
+           base = config_getstring(IMAPOPT_LDAP_BASE);
+           binddn = config_getstring(IMAPOPT_LDAP_BIND_DN);
+           bindpw = config_getstring(IMAPOPT_LDAP_PASSWORD);
+           timeout.tv_sec = config_getint(IMAPOPT_LDAP_TIME_LIMIT);
+           timeout.tv_usec = 0;
+           sprintf(filter, "(uid=%s)", user);
+           rc = ldap_initialize(&handle, uri);
+           if (rc != LDAP_SUCCESS) {
+                syslog(LOG_ERR, "ldap_initialize failed (%s)", uri);
+           } else {
+	        rc = ldap_simple_bind_s(handle, binddn, bindpw);
+	        if (rc != LDAP_SUCCESS) {
+                     syslog(LOG_ERR, "ldap_simple_bind() failed %d (%s)", rc, ldap_err2string(rc));
+	        } else {
+	             rc = ldap_search_st(handle, base, LDAP_SCOPE_SUBTREE, filter, NULL, 0, &timeout, &res);
+                     if (rc != LDAP_SUCCESS) {
+                          syslog(LOG_ERR, "ldap_search_st failed %d (%s)", rc, ldap_err2string(rc));
+                     } else {
+	                  if ( (entry = ldap_first_entry(handle, res)) != NULL ) {
+			       // read mail attribute from entry
+			       if ( (vals = ldap_get_values_len(handle, entry, "mail")) ) {
+  				    if (memchr(vals[0]->bv_val, '@', vals[0]->bv_len)) {
+				        static char buf[81]; /* same size as in auth_canonifyid */
+					   int len = ((sizeof(buf) - 1) > vals[0]->bv_len ? vals[0]->bv_len : sizeof(buf) - 1);
+					strncpy( buf, vals[0]->bv_val, len);
+					buf[len] = '\0'; /* make sure it's null-terminated */
+					ldap_value_free_len( vals );
+				        ldap_msgfree( res );
+					ldap_unbind_s(handle); /* also frees handle */
+					syslog(LOG_DEBUG, "canonify: '%s'\n", buf);
+				        return auth_canonifyid( buf, 0) ;
+				    }
+				    ldap_value_free_len( vals );
+			       }			       	
+   	                  }
+			  ldap_msgfree( res );
+                     }
+                }
+		ldap_unbind_s(handle); /* also frees handle */
+           }
+        }
 	if (domain) {
 	    if (config_defdomain && !strcasecmp(config_defdomain, domain+1)) {
 		*domain = '\0'; /* trim the default domain */
@@ -408,7 +466,7 @@
 		user = buf;
 	    }
 	}
-	else if (config_virtdomains != IMAP_ENUM_VIRTDOMAINS_USERID) {
+	else if (config_virtdomains != IMAP_ENUM_VIRTDOMAINS_USERID && config_virtdomains != IMAP_ENUM_VIRTDOMAINS_LDAP) {
 	    socklen_t salen;
 	    int error;
 	    struct sockaddr_storage localaddr;
diff -r 2ebe14b7db9d lib/imapoptions
--- a/lib/imapoptions	Mon Oct 27 18:47:12 2008 +0100
+++ b/lib/imapoptions	Mon Oct 27 18:48:18 2008 +0100
@@ -1114,7 +1114,7 @@
    mailbox hierarchy.  The default is to use the netnews separator
    character '.'. */
 
-{ "virtdomains", "off", ENUM("off", "userid", "on") }
+{ "virtdomains", "off", ENUM("off", "userid", "ldap", "on") }
 /* Enable virtual domain support.  If enabled, the user's domain will
    be determined by splitting a fully qualified userid at the last '@'
    or '%' symbol.  If the userid is unqualified, and the virtdomains