]> jfr.im git - irc/evilnet/x3.git/blame - src/x3ldap.c
use ldap_add to add users to ldap when they register on irc
[irc/evilnet/x3.git] / src / x3ldap.c
CommitLineData
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";
54char password[] = "xxxxxxx";
55char base[] = "ou=Users,dc=afternet,dc=org";
56int ldap_version = 3;
57*/
58extern struct nickserv_config nickserv_conf;
59
60
e166c31b 61LDAP *ld = NULL;
62
63int 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 83unsigned 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 */
93 return true;
e166c31b 94 }
95 else if(q == LDAP_INVALID_CREDENTIALS) {
96 return false;
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.");
108 return false;
e166c31b 109 }
110 }
ea02341b 111 log_module(MAIN_LOG, LOG_ERROR, "ldap_do_bind falling off the end. this shouldnt happen");
112 return false;
113}
114
115unsigned int ldap_check_auth( char *account, char *pass)
116{
117 char buff[MAXLEN];
118
119 if(!nickserv_conf.ldap_enable)
120 return false;
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 */
129LDAPMessage 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 176LDAPMod **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
230int 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");
235 return false; /* not configured to do this */
236 }
237 return(ldap_do_bind(nickserv_conf.ldap_admin_dn, nickserv_conf.ldap_admin_pass));
238}
239
240int 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
247 if(!( rc = ldap_do_admin_bind())) {
248 log_module(MAIN_LOG, LOG_ERROR, "failed to bind as admin");
249 return false;
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");
256 return false;
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));
261 return false;
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);
269 return true;
270}
271
e166c31b 272void ldap_close()
273{
274 ldap_unbind(ld);
275}
276
277#endif