* LDAP auth code is now complete. Config is still hardcoded, though; need to fix...
[citadel.git] / citadel / ldap.c
1 /*
2  * 
3  */
4
5
6 int ldap_version = 3;
7
8
9 #include "sysdep.h"
10 #include <errno.h>
11 #include <stdlib.h>
12 #include <unistd.h>
13 #include <stdio.h>
14 #include <fcntl.h>
15 #include <signal.h>
16 #include <pwd.h>
17 #include <ctype.h>
18 #include <sys/types.h>
19 #include <sys/wait.h>
20 #ifdef HAVE_SYS_STAT_H
21 #include <sys/stat.h>
22 #endif
23
24 #if TIME_WITH_SYS_TIME
25 # include <sys/time.h>
26 # include <time.h>
27 #else
28 # if HAVE_SYS_TIME_H
29 #  include <sys/time.h>
30 # else
31 #  include <time.h>
32 # endif
33 #endif
34
35 #include <string.h>
36 #include <limits.h>
37 #include <libcitadel.h>
38 #include "auth.h"
39 #include "citadel.h"
40 #include "server.h"
41 #include "database.h"
42 #include "user_ops.h"
43 #include "sysdep_decls.h"
44 #include "support.h"
45 #include "room_ops.h"
46 #include "file_ops.h"
47 #include "control.h"
48 #include "msgbase.h"
49 #include "config.h"
50 #include "citserver.h"
51 #include "citadel_dirs.h"
52 #include "genstamp.h"
53 #include "threads.h"
54 #include "citadel_ldap.h"
55
56 #ifdef HAVE_LDAP
57
58 #define LDAP_DEPRECATED 1       /* Needed to suppress misleading warnings */
59
60 #include <ldap.h>
61
62 int CtdlTryUserLDAP(char *username,
63                 char *found_dn, int found_dn_size,
64                 char *fullname, int fullname_size,
65                 uid_t *uid)
66 {
67         LDAP *ldserver = NULL;
68         int i;
69         LDAPMessage *search_result = NULL;
70         LDAPMessage *entry = NULL;
71         char searchstring[1024];
72         struct timeval tv;
73         char **values;
74         char *user_dn = NULL;
75
76         if (fullname) safestrncpy(fullname, username, fullname_size);
77
78         ldserver = ldap_init(CTDL_LDAP_HOST, CTDL_LDAP_PORT);
79         if (ldserver == NULL) {
80                 CtdlLogPrintf(CTDL_ALERT, "LDAP: Could not connect to %s:%d : %s\n",
81                         CTDL_LDAP_HOST, CTDL_LDAP_PORT,
82                         strerror(errno));
83                 return(errno);
84         }
85
86         ldap_set_option(ldserver, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
87
88         i = ldap_simple_bind_s(ldserver, BIND_DN, BIND_PW);
89         if (i != LDAP_SUCCESS) {
90                 CtdlLogPrintf(CTDL_ALERT, "LDAP: Cannot bind: %s (%d)\n", ldap_err2string(i), i);
91                 return(i);
92         }
93
94         tv.tv_sec = 10;
95         tv.tv_usec = 0;
96
97         sprintf(searchstring, SEARCH_STRING, username);
98
99         i = ldap_search_st(ldserver,
100                 BASE_DN,
101                 LDAP_SCOPE_SUBTREE,
102                 searchstring,
103                 NULL,   // return all attributes
104                 0,      // attributes + values
105                 &tv,    // timeout
106                 &search_result
107         );
108         if (i != LDAP_SUCCESS) {
109                 CtdlLogPrintf(CTDL_DEBUG,
110                         "Couldn't find what I was looking for: %s (%d)\n", ldap_err2string(i), i);
111                 ldap_unbind(ldserver);
112                 return(i);
113         }
114
115         if (search_result == NULL) {
116                 CtdlLogPrintf(CTDL_DEBUG, "No results were returned\n");
117                 ldap_unbind(ldserver);
118                 return(2);
119         }
120
121         /* At this point we've got at least one result from our query.  If there are multiple
122          * results, we still only look at the first one.
123          */
124         entry = ldap_first_entry(ldserver, search_result);
125         if (entry) {
126
127                 user_dn = ldap_get_dn(ldserver, entry);
128                 if (user_dn) {
129                         CtdlLogPrintf(CTDL_DEBUG, "dn = %s\n", user_dn);
130                 }
131
132                 values = ldap_get_values(ldserver, search_result, "cn");
133                 if (values) {
134                         if (values[0]) {
135                                 if (fullname) safestrncpy(fullname, values[0], fullname_size);
136                                 CtdlLogPrintf(CTDL_DEBUG, "cn = %s\n", values[0]);
137                         }
138                         ldap_value_free(values);
139                 }
140
141                 values = ldap_get_values(ldserver, search_result, "uidNumber");
142                 if (values) {
143                         if (values[0]) {
144                                 CtdlLogPrintf(CTDL_DEBUG, "uidNumber = %s\n", values[0]);
145                                 if (uid != NULL) {
146                                         *uid = atoi(values[0]);
147                                 }
148                         }
149                         ldap_value_free(values);
150                 }
151
152                 values = ldap_get_values(ldserver, search_result, "objectGUID");
153                 if (values) {
154                         if (values[0]) {
155                                 CtdlLogPrintf(CTDL_DEBUG, "objectGUID = (%d characers)\n", strlen(values[0]));
156                         }
157                         ldap_value_free(values);
158                 }
159
160         }
161
162         /* free the results */
163         ldap_msgfree(search_result);
164
165         /* unbind so we can go back in as the authenticating user */
166         ldap_unbind(ldserver);
167
168         if (!user_dn) {
169                 CtdlLogPrintf(CTDL_DEBUG, "No such user was found.\n");
170                 return(4);
171         }
172
173         if (found_dn) safestrncpy(found_dn, user_dn, found_dn_size);
174         ldap_memfree(user_dn);
175         return(0);
176 }
177
178
179 int CtdlTryPasswordLDAP(char *user_dn, char *password)
180 {
181         LDAP *ldserver = NULL;
182         int i = (-1);
183
184         ldserver = ldap_init(CTDL_LDAP_HOST, CTDL_LDAP_PORT);
185         if (ldserver) {
186                 ldap_set_option(ldserver, LDAP_OPT_PROTOCOL_VERSION, &ldap_version);
187                 i = ldap_simple_bind_s(ldserver, user_dn, password);
188                 if (i == LDAP_SUCCESS) {
189                         CtdlLogPrintf(CTDL_DEBUG, "LDAP: bind succeeded\n");
190                 }
191                 else {
192                         CtdlLogPrintf(CTDL_DEBUG, "LDAP: Cannot bind: %s (%d)\n", ldap_err2string(i), i);
193                 }
194                 ldap_unbind(ldserver);
195         }
196
197         if (i == LDAP_SUCCESS) {
198                 return(0);
199         }
200
201         return(1);
202 }
203
204
205
206
207 #endif /* HAVE_LDAP */