]>
Commit | Line | Data |
---|---|---|
50895889 | 1 | /* x3ldap.c - LDAP functionality for x3, by Rubin |
2 | * Copyright 2002-2007 x3 Development Team | |
3 | * | |
4 | * This file is part of x3. | |
5 | * | |
6 | * x3 is free software; you can redistribute it and/or modify | |
7 | * it under the terms of the GNU General Public License as published by | |
8 | * the Free Software Foundation; either version 2 of the License, or | |
9 | * (at your option) any later version. | |
10 | * | |
11 | * This program is distributed in the hope that it will be useful, | |
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | * GNU General Public License for more details. | |
15 | * | |
16 | * You should have received a copy of the GNU General Public License | |
17 | * along with srvx; if not, write to the Free Software Foundation, | |
18 | * Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. | |
e166c31b | 19 | * |
e166c31b | 20 | * |
21 | * TODO: | |
22 | * * get queries working in static existance, so i understand how it works | |
23 | * * get ldap enabled in ./configure | |
24 | * * x3.conf settings to enable/configure its use | |
25 | * * generic functions to enable ldap | |
26 | * * nickserv.c work to use said functions. | |
27 | */ | |
28 | ||
39edf54a | 29 | #include "config.h" |
db9a9a8a | 30 | #ifdef WITH_LDAP |
31 | ||
e166c31b | 32 | #include <stdio.h> |
33 | #include <stdlib.h> | |
34 | #include <ldap.h> | |
35 | //#include <sys/select.h> | |
36 | ||
37 | #include "conf.h" | |
e166c31b | 38 | #include "global.h" |
50895889 | 39 | #include "log.h" |
e166c31b | 40 | #include "x3ldap.h" |
41 | ||
42 | #ifdef HAVE_FCNTL_H | |
43 | #include <fcntl.h> | |
44 | #endif | |
45 | #ifdef HAVE_SYS_SELECT_H | |
46 | #include <sys/select.h> | |
47 | #endif | |
48 | #ifdef HAVE_SYS_SOCKET_H | |
49 | #include <sys/socket.h> | |
50 | #endif | |
51 | ||
e166c31b | 52 | |
53 | /* char dn[] = "uid=%s,ou=Users,dc=afternet,dc=org"; | |
54 | char password[] = "xxxxxxx"; | |
55 | char base[] = "ou=Users,dc=afternet,dc=org"; | |
56 | int ldap_version = 3; | |
57 | */ | |
58 | extern struct nickserv_config nickserv_conf; | |
59 | ||
60 | ||
e166c31b | 61 | LDAP *ld = NULL; |
62 | ||
63 | int ldap_do_init() | |
64 | { | |
39edf54a | 65 | if(!nickserv_conf.ldap_enable) |
66 | return false; | |
e166c31b | 67 | /* TODO: check here for all required config options and exit() out if not present */ |
68 | ld = ldap_init(nickserv_conf.ldap_host, nickserv_conf.ldap_port); | |
69 | if(ld == NULL) { | |
50895889 | 70 | log_module(MAIN_LOG, LOG_ERROR, "LDAP initilization failed!\n"); |
e166c31b | 71 | exit(1); |
72 | } | |
73 | ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &nickserv_conf.ldap_version); | |
50895889 | 74 | log_module(MAIN_LOG, LOG_INFO, "Success! ldap_init() was successfull in connecting to %s port %d\n", nickserv_conf.ldap_host, nickserv_conf.ldap_port ); |
e166c31b | 75 | return true; |
76 | } | |
77 | ||
ea02341b | 78 | |
e166c31b | 79 | /* Try to auth someone. If theres problems, try reconnecting |
80 | * once every 10 seconds for 1 minute. | |
81 | * TODO: move this stuff to config file | |
82 | */ | |
ea02341b | 83 | unsigned int ldap_do_bind( const char *dn, const char *pass) |
e166c31b | 84 | { |
e166c31b | 85 | int q; |
86 | ||
e166c31b | 87 | int n = 0; |
88 | while(1) { | |
ea02341b | 89 | q = ldap_simple_bind_s(ld, dn, pass); |
e166c31b | 90 | if(q == LDAP_SUCCESS) { |
ea02341b | 91 | log_module(MAIN_LOG, LOG_DEBUG, "bind() successfull! You are bound as %s\n", dn); |
92 | /* unbind now */ | |
a5a8a781 | 93 | return q; |
e166c31b | 94 | } |
95 | else if(q == LDAP_INVALID_CREDENTIALS) { | |
a5a8a781 | 96 | return q; |
e166c31b | 97 | } |
98 | else { | |
ea02341b | 99 | log_module(MAIN_LOG, LOG_ERROR, "Bind failed: %s/****** (%d)\n", dn, q); |
e166c31b | 100 | ldap_perror(ld, "ldap"); |
ea02341b | 101 | ldap_do_init(); |
e166c31b | 102 | } |
39edf54a | 103 | if(n++ > 1) { |
104 | /* TODO: return to the user that this is a connection error and not a problem | |
105 | * with their password | |
106 | */ | |
107 | log_module(MAIN_LOG, LOG_ERROR, "Failing to reconnect to ldap server. Auth failing."); | |
a5a8a781 | 108 | return q; |
e166c31b | 109 | } |
110 | } | |
ea02341b | 111 | log_module(MAIN_LOG, LOG_ERROR, "ldap_do_bind falling off the end. this shouldnt happen"); |
a5a8a781 | 112 | return q; |
ea02341b | 113 | } |
114 | ||
115 | unsigned int ldap_check_auth( char *account, char *pass) | |
116 | { | |
117 | char buff[MAXLEN]; | |
118 | ||
119 | if(!nickserv_conf.ldap_enable) | |
a5a8a781 | 120 | return LDAP_OTHER; |
ea02341b | 121 | |
122 | memset(buff, 0, MAXLEN); | |
123 | snprintf(buff, sizeof(buff)-1, nickserv_conf.ldap_dn_fmt /*"uid=%s,ou=Users,dc=afternet,dc=org"*/, account); | |
124 | return ldap_do_bind(buff, pass); | |
e166c31b | 125 | |
126 | } | |
127 | ||
128 | #ifdef notdef /* not used yet - will be used to pull email etc out of ldap */ | |
129 | LDAPMessage ldap_search_user(char uid) | |
130 | { | |
131 | ||
132 | char filter[] = "cn=admin"; | |
133 | ||
134 | struct timeval timeout; | |
135 | /* | |
136 | Now we do a search; | |
137 | */ | |
138 | timeout.tv_usec = 0; | |
139 | timeout.tv_sec = 5; | |
140 | if( ldap_search_st(ld, base, LDAP_SCOPE_ONELEVEL, filter, NULL, 0, &timeout, &res) != LDAP_SUCCESS) { | |
50895889 | 141 | log_module(MAIN_LOG, LOG_ERROR, "search failed: %s %s\n", base, filter); |
e166c31b | 142 | exit(1); |
143 | } | |
50895889 | 144 | log_module(MAIN_LOG, LOG_DEBUG, "Search successfull! %s %s\n", base, filter); |
145 | log_module(MAIN_LOG, LOG_DEBUG, "Got %d entries\n", ldap_count_entries(ld, res)); | |
e166c31b | 146 | { |
147 | LDAPMessage *entry; | |
148 | char **value; | |
149 | entry = ldap_first_entry(ld, res); | |
150 | value = ldap_get_values(ld, entry, "cn"); | |
50895889 | 151 | log_module(MAIN_LOG, LOG_DEBUG, "cn: %s\n", value[0]); |
e166c31b | 152 | value = ldap_get_values(ld, entry, "description"); |
50895889 | 153 | log_module(MAIN_LOG, LOG_DEBUG, "Description: %s\n", value[0]); |
e166c31b | 154 | value = ldap_get_values(ld, entry, "userPassword"); |
50895889 | 155 | log_module(MAIN_LOG, LOG_DEBUG, "pass: %s\n", value ? value[0] : "error"); |
e166c31b | 156 | } |
157 | /* | |
158 | ldap_result(); | |
159 | ldap_first_entry(); | |
160 | ldap_first_attribute(); | |
161 | for(;;) { | |
162 | ldap_get_values(); | |
163 | ldap_next_attribute(); | |
164 | } | |
165 | ||
166 | ldap_parse_result(); | |
167 | ||
168 | ldap_unbind_ext(); | |
169 | ||
170 | */ | |
171 | /* get errors with ldap_err2string(); */ | |
172 | } | |
173 | ||
174 | #endif | |
175 | ||
ea02341b | 176 | LDAPMod **make_mods(const char *account, const char *password, const char *email, int *num_mods_ret) |
177 | { | |
178 | static char *account_vals[] = { NULL, NULL }; | |
179 | static char *password_vals[] = { NULL, NULL }; | |
180 | static char *email_vals[] = { NULL, NULL }; | |
181 | char newdn[MAXLEN]; | |
182 | int num_mods = 3; | |
183 | int i; | |
184 | /* TODO: take this from nickserv_conf.ldap_add_objects */ | |
185 | static char *object_vals[] = { "top", "inetOrgAnonAccount", NULL }; | |
186 | LDAPMod **mods; | |
187 | ||
188 | account_vals[0] = (char *) account; | |
189 | password_vals[0] = (char *) password; | |
190 | email_vals[0] = (char *) email; | |
191 | ||
192 | if(!(nickserv_conf.ldap_field_account && *nickserv_conf.ldap_field_account)) | |
193 | return 0; /* account required */ | |
194 | if(!(nickserv_conf.ldap_field_password && *nickserv_conf.ldap_field_password)) | |
195 | return 0; /* password required */ | |
196 | if(email && *email && nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email) | |
197 | num_mods++; | |
198 | ||
199 | mods = ( LDAPMod ** ) malloc(( num_mods + 1 ) * sizeof( LDAPMod * )); | |
200 | for( i = 0; i < num_mods; i++) { | |
201 | mods[i] = (LDAPMod *) malloc(sizeof(LDAPMod)); | |
202 | memset(mods[i], 0, sizeof(LDAPMod)); | |
203 | } | |
204 | ||
205 | memset(newdn, 0, MAXLEN); | |
206 | mods[0]->mod_op = LDAP_MOD_ADD; | |
207 | mods[0]->mod_type = strdup("objectclass"); | |
208 | mods[0]->mod_values = object_vals; | |
209 | ||
210 | mods[1]->mod_op = LDAP_MOD_ADD; | |
211 | mods[1]->mod_type = strdup(nickserv_conf.ldap_field_account); | |
212 | mods[1]->mod_values = account_vals; | |
213 | ||
214 | mods[2]->mod_op = LDAP_MOD_ADD; | |
215 | mods[2]->mod_type = strdup(nickserv_conf.ldap_field_password); | |
216 | mods[2]->mod_values = password_vals; | |
217 | ||
218 | if(nickserv_conf.ldap_field_email && *nickserv_conf.ldap_field_email && email && *email) { | |
219 | mods[3]->mod_op = LDAP_MOD_ADD; | |
220 | mods[3]->mod_type = strdup(nickserv_conf.ldap_field_email); | |
221 | mods[3]->mod_values = email_vals; | |
222 | mods[4] = NULL; | |
223 | } | |
224 | else | |
225 | mods[3] = NULL; | |
226 | *num_mods_ret = num_mods; | |
227 | return mods; | |
228 | } | |
229 | ||
230 | int ldap_do_admin_bind() | |
231 | { | |
232 | if(!(nickserv_conf.ldap_admin_dn && *nickserv_conf.ldap_admin_dn && | |
233 | nickserv_conf.ldap_admin_pass && *nickserv_conf.ldap_admin_pass)) { | |
234 | log_module(MAIN_LOG, LOG_ERROR, "Tried to admin bind, but no admin credentials configured in config file. ldap_admin_dn/ldap_admin_pass"); | |
a5a8a781 | 235 | return LDAP_OTHER; /* not configured to do this */ |
ea02341b | 236 | } |
237 | return(ldap_do_bind(nickserv_conf.ldap_admin_dn, nickserv_conf.ldap_admin_pass)); | |
238 | } | |
239 | ||
240 | int ldap_do_add(const char *account, const char *password, const char *email) | |
241 | { | |
242 | char newdn[MAXLEN]; | |
243 | LDAPMod **mods; | |
244 | int rc, i; | |
245 | int num_mods; | |
246 | ||
a5a8a781 | 247 | if(LDAP_SUCCESS != ( rc = ldap_do_admin_bind())) { |
ea02341b | 248 | log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin"); |
a5a8a781 | 249 | return rc; |
ea02341b | 250 | } |
251 | ||
252 | snprintf(newdn, MAXLEN-1, nickserv_conf.ldap_dn_fmt, account); | |
253 | mods = make_mods(account, password, email, &num_mods); | |
254 | if(!mods) { | |
255 | log_module(MAIN_LOG, LOG_ERROR, "Error building mods for ldap_add"); | |
a5a8a781 | 256 | return LDAP_OTHER; |
ea02341b | 257 | } |
258 | rc = ldap_add_ext_s(ld, newdn, mods, NULL, NULL); | |
259 | if(rc != LDAP_SUCCESS) { | |
260 | log_module(MAIN_LOG, LOG_ERROR, "Error adding ldap account: %s -- %s", account, ldap_err2string(rc)); | |
a5a8a781 | 261 | return rc; |
ea02341b | 262 | } |
263 | //ldap_unbind_s(ld); | |
264 | for(i = 0; i < num_mods; i++) { | |
265 | free(mods[i]->mod_type); | |
266 | free(mods[i]); | |
267 | } | |
268 | free(mods); | |
a5a8a781 | 269 | return rc; |
ea02341b | 270 | } |
271 | ||
e166c31b | 272 | void ldap_close() |
273 | { | |
274 | ldap_unbind(ld); | |
275 | } | |
276 | ||
277 | #endif |