]>
Commit | Line | Data |
---|---|---|
ca02e0ec | 1 | /* |
77b1029d | 2 | * Copyright (C) 1996-2020 The Squid Software Foundation and contributors |
ca02e0ec AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
9 | /* | |
10 | * Copyright (C) 2009-2011 Chad E. Naugle | |
f86504f1 AJ |
11 | * |
12 | ******************************************************************************** | |
13 | * | |
14 | * This file is part of ext_edirectory_userip_acl. | |
15 | * | |
16 | * ext_edirectory_userip_acl is free software: you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation, either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * ext_edirectory_userip_acl is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with squid_edir_iplookup. If not, see <http://www.gnu.org/licenses/>. | |
28 | * | |
29 | ******************************************************************************** | |
30 | * | |
915c866f CN |
31 | * ext_edirectory_userip_acl.cc -- Rev 2011-03-28 |
32 | * | |
33 | * - Misc code cleanups using "static", and 64-bit SLES fix for SearchFilterLDAP() | |
f86504f1 AJ |
34 | * |
35 | */ | |
36 | ||
f86504f1 | 37 | /* Squid-3.X includes */ |
f7f3304a | 38 | #include "squid.h" |
079b1d0f | 39 | #include "helper/protocol_defines.h" |
f86504f1 AJ |
40 | #include "rfc1738.h" |
41 | #include "util.h" | |
f86504f1 | 42 | |
f53969cc SM |
43 | #define EDUI_PROGRAM_NAME "ext_edirectory_userip_acl" |
44 | #define EDUI_PROGRAM_VERSION "2.1" | |
f86504f1 AJ |
45 | |
46 | /* System includes */ | |
88f2cf55 | 47 | #ifndef _GNU_SOURCE |
f86504f1 | 48 | #define _GNU_SOURCE |
88f2cf55 AJ |
49 | #endif |
50 | #ifndef __USE_GNU | |
f86504f1 | 51 | #define __USE_GNU |
88f2cf55 | 52 | #endif |
074d6a40 AJ |
53 | #include <cctype> |
54 | #include <cerrno> | |
55 | #include <csignal> | |
074d6a40 AJ |
56 | #include <cstdlib> |
57 | #include <cstring> | |
58 | #include <ctime> | |
f86504f1 AJ |
59 | #ifdef HAVE_ARPA_INET_H |
60 | #include <arpa/inet.h> | |
61 | #endif | |
62 | #define LDAP_DEPRECATED 1 /* Set flag for enabling classic ldap functions */ | |
63 | #ifdef HAVE_LBER_H | |
64 | #include <lber.h> | |
65 | #endif | |
66 | #ifdef HAVE_LDAP_H | |
67 | #include <ldap.h> | |
68 | #endif | |
d08caf47 AJ |
69 | #ifdef HAVE_NETDB_H |
70 | #include <netdb.h> | |
71 | #endif | |
f86504f1 AJ |
72 | |
73 | #ifdef HELPER_INPUT_BUFFER | |
f53969cc | 74 | #define EDUI_MAXLEN HELPER_INPUT_BUFFER |
f86504f1 | 75 | #else |
f53969cc | 76 | #define EDUI_MAXLEN 4096 /* Modified to improve performance, unless HELPER_INPUT_BUFFER exists */ |
f86504f1 AJ |
77 | #endif |
78 | ||
79 | /* ldap compile options */ | |
80 | #define USE_LDAP_INIT | |
81 | #ifndef NETSCAPE_SSL | |
82 | # define NETSCAPE_SSL | |
83 | #endif | |
84 | ||
915c866f CN |
85 | /* define LDAP_AUTH_TLS |
86 | * - ldap.h Hack for cleaner code, if it does not provide it. | |
87 | */ | |
f86504f1 AJ |
88 | #ifdef NETSCAPE_SSL |
89 | # ifndef LDAP_AUTH_TLS | |
90 | # define LDAP_AUTH_TLS ((ber_tag_t) 0xb3U) | |
91 | # endif | |
92 | #endif | |
93 | ||
94 | /* conf_t - status flags */ | |
f53969cc SM |
95 | #define EDUI_MODE_INIT 0x01 |
96 | #define EDUI_MODE_DEBUG 0x02 /* Replace with Squid's debug system */ | |
97 | #define EDUI_MODE_TLS 0x04 | |
98 | #define EDUI_MODE_IPV4 0x08 | |
99 | #define EDUI_MODE_IPV6 0x10 | |
100 | #define EDUI_MODE_GROUP 0x20 /* Group is REQUIRED */ | |
101 | #define EDUI_MODE_PERSIST 0x40 /* Persistent LDAP connections */ | |
102 | #define EDUI_MODE_KILL 0x80 | |
f86504f1 AJ |
103 | |
104 | /* conf_t - Program configuration struct typedef */ | |
105 | typedef struct { | |
106 | char program[EDUI_MAXLEN]; | |
107 | char basedn[EDUI_MAXLEN]; | |
108 | char host[EDUI_MAXLEN]; | |
109 | char attrib[EDUI_MAXLEN]; | |
110 | char dn[EDUI_MAXLEN]; | |
111 | char passwd[EDUI_MAXLEN]; | |
f53969cc | 112 | char search_filter[EDUI_MAXLEN]; /* Base search_filter that gets copied to edui_ldap_t */ |
f86504f1 AJ |
113 | int ver; |
114 | int scope; | |
115 | int port; | |
116 | time_t persist_timeout; | |
117 | unsigned int mode; | |
118 | } edui_conf_t; | |
119 | ||
120 | /* edui_ldap_t - status flags */ | |
121 | #define LDAP_INIT_S 0x0001 | |
122 | #define LDAP_OPEN_S 0x0002 | |
123 | #define LDAP_BIND_S 0x0004 | |
124 | #define LDAP_SEARCH_S 0x0008 /* We got data */ | |
125 | #define LDAP_VAL_S 0x0010 /* Data has been copied to l->val */ | |
126 | #define LDAP_CLOSE_S 0x0020 | |
127 | #define LDAP_PERSIST_S 0x0040 /* Persistent connection */ | |
128 | #define LDAP_IDLE_S 0x0080 /* Connection is idle */ | |
129 | #define LDAP_SSL_S 0x0100 | |
130 | #define LDAP_TLS_S 0x0200 | |
131 | #define LDAP_IPV4_S 0x0400 /* Search IP is IPv4 */ | |
132 | #define LDAP_IPV6_S 0x0800 /* Search IP is IPv6 */ | |
133 | ||
134 | /* edui_ldap_t - Meaningful error codes */ | |
135 | #define LDAP_ERR_NULL -1 /* Null edui_ldap_t pointer */ | |
136 | #define LDAP_ERR_POINTER -2 /* Null l->lp pointer */ | |
137 | #define LDAP_ERR_PARAM -3 /* Null or Missing parameters */ | |
138 | #define LDAP_ERR_INIT -4 /* Not initalized */ | |
139 | #define LDAP_ERR_OPEN -5 /* Not open */ | |
140 | #define LDAP_ERR_CONNECT -6 /* Unable to connect */ | |
141 | #define LDAP_ERR_BIND -7 /* Not bound */ | |
142 | #define LDAP_ERR_SEARCHED -8 /* Already Searched */ | |
143 | #define LDAP_ERR_NOT_SEARCHED -9 /* Not searching */ | |
144 | #define LDAP_ERR_INVALID -10 /* Invalid parameter */ | |
145 | #define LDAP_ERR_OOB -11 /* Out of bounds value */ | |
146 | #define LDAP_ERR_PERSIST -12 /* Persistent mode is not active */ | |
147 | #define LDAP_ERR_DATA -13 /* Required data missing */ | |
148 | #define LDAP_ERR_NOTFOUND -14 /* Item not found */ | |
149 | #define LDAP_ERR_OTHER -15 /* Other Generic Error condition */ | |
150 | #define LDAP_ERR_FAILED -16 /* Operation failed */ | |
151 | #define LDAP_ERR_SUCCESS -17 /* Operation successful */ | |
152 | ||
153 | /* edui_ldap_t - struct typedef */ | |
154 | typedef struct { | |
155 | LDAP *lp; | |
156 | LDAPMessage *lm; | |
157 | struct berval **val; | |
158 | char basedn[EDUI_MAXLEN]; | |
159 | char host[EDUI_MAXLEN]; | |
160 | char dn[EDUI_MAXLEN]; | |
161 | char passwd[EDUI_MAXLEN]; | |
f53969cc SM |
162 | char search_filter[EDUI_MAXLEN]; /* search_group gets appended here by GroupLDAP */ |
163 | char search_ip[EDUI_MAXLEN]; /* Could be IPv4 or IPv6, set by ConvertIP */ | |
7a545fdb | 164 | char userid[EDUI_MAXLEN]; /* Resulting userid */ |
f86504f1 AJ |
165 | unsigned int status; |
166 | unsigned int port; | |
f53969cc | 167 | unsigned long type; /* Type of bind */ |
f86504f1 AJ |
168 | int ver; |
169 | int scope; | |
f53969cc | 170 | int err; /* LDAP error code */ |
f86504f1 AJ |
171 | time_t idle_time; |
172 | int num_ent; /* Number of entry's found via search */ | |
173 | int num_val; /* Number of value's found via getval */ | |
174 | } edui_ldap_t; | |
175 | ||
6ca7324f | 176 | /* Global function prototypes */ |
915c866f CN |
177 | static void local_printfx(const char *,...); |
178 | static int StringSplit(char *, char, char *, size_t); | |
179 | static int BinarySplit(void *, size_t, char, void *, size_t); | |
6ca7324f AJ |
180 | static void DisplayVersion(); |
181 | static void DisplayUsage(); | |
182 | static void InitConf(); | |
183 | static void DisplayConf(); | |
184 | static void InitLDAP(edui_ldap_t *); | |
915c866f CN |
185 | static int OpenLDAP(edui_ldap_t *, char *, unsigned int); |
186 | static int CloseLDAP(edui_ldap_t *); | |
187 | static int SetVerLDAP(edui_ldap_t *, int); | |
188 | static int BindLDAP(edui_ldap_t *, char *, char *, unsigned int); | |
189 | static int ConvertIP(edui_ldap_t *, char *); | |
190 | static int ResetLDAP(edui_ldap_t *); | |
191 | static int SearchFilterLDAP(edui_ldap_t *, char *); | |
192 | static int SearchLDAP(edui_ldap_t *, int, char *, char **); | |
193 | static int SearchIPLDAP(edui_ldap_t *); | |
6ca7324f | 194 | const char *ErrLDAP(int); |
5cd16654 | 195 | extern "C" void SigTrap(int); |
6ca7324f | 196 | |
f86504f1 | 197 | /* Global variables */ |
6ca7324f | 198 | const char *search_attrib[] = { "cn", "uid", "networkAddress", "groupMembership", NULL }; |
915c866f CN |
199 | static edui_conf_t edui_conf; |
200 | static edui_ldap_t edui_ldap; | |
f86504f1 AJ |
201 | time_t edui_now; |
202 | time_t edui_elap; | |
203 | ||
f86504f1 AJ |
204 | /* local_printfx() - |
205 | * | |
206 | * Print formatted message to stderr AND stdout, without preformatting. | |
207 | * | |
915c866f CN |
208 | * - Exists as a hack, because SEND_OK() does not appear to work here. |
209 | * | |
f86504f1 | 210 | */ |
915c866f CN |
211 | static void |
212 | local_printfx(const char *msg,...) | |
f86504f1 AJ |
213 | { |
214 | char prog[EDUI_MAXLEN], dbuf[EDUI_MAXLEN]; | |
215 | size_t sz, x; | |
216 | va_list ap; | |
217 | ||
218 | if (edui_conf.program[0] == '\0') | |
bcdce702 | 219 | xstrncpy(prog, EDUI_PROGRAM_NAME, sizeof(prog)); |
f86504f1 | 220 | else |
bcdce702 | 221 | xstrncpy(prog, edui_conf.program, sizeof(prog)); |
f86504f1 | 222 | |
915c866f | 223 | if (msg == NULL) { |
f86504f1 | 224 | /* FAIL */ |
915c866f | 225 | debug("local_printfx() FAILURE, no data.\n"); |
f86504f1 AJ |
226 | return; |
227 | } | |
228 | sz = sizeof(dbuf); | |
229 | va_start(ap, msg); | |
230 | x = vsnprintf(dbuf, sz, msg, ap); | |
231 | va_end(ap); | |
232 | if (x > 0) { | |
233 | dbuf[x] = '\0'; | |
755494da | 234 | ++x; |
f86504f1 | 235 | fputs(dbuf, stdout); |
9c76c145 | 236 | *(dbuf) = '\0'; |
f86504f1 AJ |
237 | } else { |
238 | /* FAIL */ | |
fe1e5c91 | 239 | debug("local_printfx() FAILURE: %" PRIuSIZE "\n", x); |
f86504f1 AJ |
240 | } |
241 | ||
242 | /* stdout needs to be flushed for it to work with Squid */ | |
243 | fflush(stdout); | |
244 | } | |
245 | ||
246 | /* | |
7a545fdb | 247 | * StringSplit() - <string-to-split> <char> <split-object> <obj-size> |
f86504f1 AJ |
248 | * |
249 | * Breaks down string, splitting out element <char> into <split-object>, and removing it from string. | |
250 | * Will not exceed size tolerances. | |
251 | * | |
f86504f1 | 252 | */ |
915c866f | 253 | static int |
9c2c41b2 | 254 | StringSplit(char *In_Str, char chr, char *Out_Str, size_t Out_Sz) |
f86504f1 | 255 | { |
9c2c41b2 AJ |
256 | if ((In_Str == NULL) || (Out_Str == NULL)) |
257 | return (-1); | |
258 | ||
259 | size_t In_Len = strlen(In_Str) + 1; | |
260 | ||
261 | // find the char delimiter position... | |
262 | char *p = In_Str; | |
263 | while (*p != chr && *p != '\0' && (In_Str+In_Len) > p) { | |
755494da | 264 | ++p; |
f86504f1 | 265 | } |
9c2c41b2 AJ |
266 | |
267 | size_t i = (p-In_Str); | |
268 | ||
269 | // token to big for the output buffer | |
270 | if (i >= Out_Sz) | |
271 | return (-2); | |
272 | ||
273 | // wipe the unused Out_Obj area | |
274 | memset(Out_Str+i, 0, Out_Sz-i); | |
275 | // copy token from In_Str to Out_Str | |
276 | memcpy(Out_Str, In_Str, i); | |
277 | ||
278 | // omit the delimiter | |
279 | if (*p == chr) { | |
755494da FC |
280 | ++p; |
281 | ++i; | |
9c2c41b2 AJ |
282 | } else { |
283 | // chr not found (or \0 found first). Wipe whole input buffer. | |
284 | memset(In_Str, 0, In_Len); | |
acbf414b AJ |
285 | // return (-3); |
286 | // Returning <0 breaks current ConvertIP() code for last object | |
90737510 | 287 | return (i); |
9c2c41b2 AJ |
288 | } |
289 | ||
290 | // move the unused In_Str forward | |
291 | memmove(In_Str, p, In_Len-i); | |
292 | // wipe the end of In_Str | |
293 | memset(In_Str+In_Len-i, 0, i); | |
294 | return (i-1); | |
f86504f1 AJ |
295 | } |
296 | ||
7a545fdb AJ |
297 | /* |
298 | * BinarySplit() - <binary-to-split> <bin-size> <char> <split-object> <obj-size> | |
299 | * | |
300 | * Breaks down Binary Block, splitting out element <char> into <split-object>, and removing it from Block, padding remainder with '\0'. | |
301 | * Will not exceed size tolerances. | |
302 | * | |
303 | */ | |
915c866f | 304 | static int |
9c2c41b2 | 305 | BinarySplit(void *In_Obj, size_t In_Sz, char chr, void *Out_Obj, size_t Out_Sz) |
7a545fdb | 306 | { |
9c2c41b2 AJ |
307 | // check tolerances |
308 | if ((In_Obj == NULL) || (Out_Obj == NULL)) | |
309 | return (-1); | |
310 | ||
311 | char *in = static_cast<char*>(In_Obj); | |
312 | char *out = static_cast<char*>(Out_Obj); | |
313 | ||
314 | // find the char delimiter position... | |
315 | char *p = static_cast<char*>(In_Obj); | |
316 | while (*p != chr && (in+In_Sz) > p) { | |
755494da | 317 | ++p; |
9c2c41b2 AJ |
318 | } |
319 | ||
320 | size_t i = (p-in); | |
321 | ||
322 | // token to big for the output buffer | |
323 | if (i > Out_Sz) | |
324 | return (-2); | |
325 | ||
326 | // wipe the unused Out_Obj area | |
327 | memset(out+i, 0, Out_Sz-i); | |
328 | // copy token from In_Obj to Out_Obj | |
329 | memcpy(Out_Obj, In_Obj, i); | |
330 | ||
331 | // omit the delimiter | |
332 | if (*p == chr) { | |
755494da FC |
333 | ++p; |
334 | ++i; | |
9c2c41b2 AJ |
335 | } else { |
336 | // chr not found | |
337 | memset(In_Obj, 0, In_Sz); | |
acbf414b AJ |
338 | // return (-3); |
339 | // Returning <0 breaks current code for last object | |
90737510 | 340 | return (i); |
7a545fdb | 341 | } |
9c2c41b2 AJ |
342 | |
343 | // move the unused In_Obj forward | |
344 | memmove(In_Obj, p, In_Sz-i); | |
345 | // wipe the end of In_Obj | |
346 | memset(in+In_Sz-i, 0, i); | |
347 | return (i-1); | |
7a545fdb | 348 | } |
9c2c41b2 | 349 | |
f86504f1 | 350 | /* Displays version information */ |
915c866f CN |
351 | static void |
352 | DisplayVersion() | |
f86504f1 | 353 | { |
915c866f | 354 | local_printfx("Squid eDirectory IP Lookup Helper %s. Copyright (C) 2009-2011 Chad E. Naugle\n", EDUI_PROGRAM_VERSION); |
f86504f1 AJ |
355 | } |
356 | ||
357 | /* Displays program usage information */ | |
915c866f CN |
358 | static void |
359 | DisplayUsage() | |
f86504f1 AJ |
360 | { |
361 | DisplayVersion(); | |
362 | local_printfx("\n"); | |
363 | local_printfx("Usage: %s\n", edui_conf.program); | |
364 | local_printfx(" -H <host> -p <port> [-Z] [-P] [-v 3] -b <basedn> -s <scope>\n"); | |
365 | local_printfx(" -D <binddn> -W <bindpass> -F <search-filter> [-G] \n\n"); | |
366 | local_printfx(" -d : Debug Mode.\n"); | |
367 | local_printfx(" -4 : Force Addresses to be in IPv4 (127.0.0.1 format).\n"); | |
368 | local_printfx(" -6 : Force Addresses to be in IPv6 (::1 format).\n"); | |
369 | local_printfx(" -H <host> : Specify hostname/ip of server.\n"); | |
370 | local_printfx(" -p <port> : Specify port number. (Range 1-65535)\n"); | |
371 | local_printfx(" -Z : Enable TLS security.\n"); | |
372 | local_printfx(" -P : Use persistent connections.\n"); | |
373 | local_printfx(" -t <sec> : Timeout factor for persistent connections. (Default is 60 sec, set to 0 for never timeout)\n"); | |
374 | local_printfx(" -v <1,2,3> : Set LDAP version to 1, 2, or 3.\n"); | |
375 | local_printfx(" -b <base> : Specify Base DN. (ie. \"o=ORG\")\n"); | |
6ca7324f | 376 | local_printfx(" -s <scope> : Specify LDAP Search Scope (base, one, sub; defaults to 'one').\n"); |
f86504f1 AJ |
377 | local_printfx(" -D <dn> : Specify Binding DN. (ie. cn=squid,o=ORG)\n"); |
378 | local_printfx(" -W <pass> : Specify Binding password.\n"); | |
379 | local_printfx(" -u <attrib> : Set userid attribute (Defaults to \"cn\").\n"); | |
380 | local_printfx(" -F <filter> : Specify LDAP search filter. (ie. \"(objectClass=User)\")\n"); | |
381 | local_printfx(" -G : Specify if LDAP search group is required. (ie. \"groupMembership=\")\n"); | |
382 | local_printfx(" -V : Display version & exit.\n"); | |
383 | local_printfx(" -h : This screen & exit.\n"); | |
384 | local_printfx("\n"); | |
385 | } | |
386 | ||
387 | /* Initalizes program's configuration paremeters */ | |
915c866f CN |
388 | static void |
389 | InitConf() | |
f86504f1 | 390 | { |
7a545fdb AJ |
391 | *(edui_conf.program) = '\0'; |
392 | *(edui_conf.basedn) = '\0'; | |
393 | *(edui_conf.host) = '\0'; | |
394 | *(edui_conf.attrib) = '\0'; | |
395 | *(edui_conf.dn) = '\0'; | |
396 | *(edui_conf.passwd) = '\0'; | |
397 | *(edui_conf.search_filter) = '\0'; | |
f86504f1 AJ |
398 | edui_conf.scope = -1; |
399 | edui_conf.ver = -1; | |
400 | edui_conf.port = -1; | |
401 | edui_conf.persist_timeout = -1; | |
402 | edui_conf.mode = 0; | |
403 | edui_conf.mode |= EDUI_MODE_INIT; | |
404 | ||
915c866f | 405 | /* Set defaults from compile-time-options, if provided, but depriciated. */ |
f86504f1 | 406 | #ifdef EDUI_BASE_DN |
6ca7324f | 407 | xstrncpy(edui_conf.basedn, EDUI_BASE_DN, sizeof(edui_conf.basedn)); |
f86504f1 AJ |
408 | #endif |
409 | #ifdef EDUI_DEFAULT_HOST | |
6ca7324f | 410 | xstrncpy(edui_conf.host, EDUI_DEFAULT_HOST, sizeof(edui_conf.host)); |
f86504f1 AJ |
411 | #endif |
412 | #ifdef EDUI_BIND_DN | |
6ca7324f | 413 | xstrncpy(edui_conf.dn, EDUI_BIND_DN, sizeof(edui_conf.dn)); |
f86504f1 AJ |
414 | #endif |
415 | #ifdef EDUI_BIND_PASS | |
6ca7324f | 416 | xstrncpy(edui_conf.passwd, EDUI_BIND_PASS, sizeof(edui_conf.passwd)); |
f86504f1 AJ |
417 | #endif |
418 | #ifdef EDUI_USER_ATTRIB | |
6ca7324f | 419 | xstrncpy(edui_conf.attrib, EDUI_USER_ATTRIB, sizeof(edui_conf.attrib)); |
f86504f1 AJ |
420 | #endif |
421 | #ifdef EDUI_SEARCH_FILTER | |
6ca7324f | 422 | xstrncpy(edui_conf.search_filter, EDUI_SEARCH_FILTER, sizeof(edui_conf.search_filter)); |
f86504f1 AJ |
423 | #endif |
424 | #ifdef EDUI_SEARCH_SCOPE | |
425 | if (!strcmp(EDUI_SEARCH_SCOPE, "base")) | |
426 | edui_conf.scope = 0; | |
427 | else if (!strcmp(EDUI_SEARCH_SCOPE, "one")) | |
428 | edui_conf.scope = 1; | |
429 | else if (!strcmp(EDUI_SEARCH_SCOPE, "sub")) | |
430 | edui_conf.scope = 2; | |
431 | else | |
432 | edui_conf.scope = 1; | |
433 | #endif | |
434 | #ifdef EDUI_LDAP_VERSION | |
435 | edui_conf.ver = EDUI_LDAP_VERSION; | |
436 | #endif | |
437 | #ifdef EDUI_DEFAULT_PORT | |
438 | edui_conf.port = EDUI_DEFAULT_PORT; | |
439 | #endif | |
440 | #ifdef EDUI_FORCE_IPV4 | |
441 | edui_conf.mode |= EDUI_MODE_IPV4; | |
442 | #endif | |
443 | #ifdef EDUI_FORCE_IPV6 | |
444 | edui_conf.mode |= EDUI_MODE_IPV6; | |
445 | #endif | |
446 | #ifdef EDUI_USE_TLS | |
447 | edui_conf.mode |= EDUI_MODE_TLS; | |
448 | #endif | |
449 | #ifdef EDUI_USE_PERSIST | |
450 | edui_conf.mode |= EDUI_MODE_PERSIST; | |
451 | #endif | |
452 | #ifdef EDUI_PERSIST_TIMEOUT | |
453 | edui_conf.persist_timeout = EDUI_PERSIST_TIMEOUT; | |
454 | #endif | |
455 | #ifdef EDUI_GROUP_REQUIRED | |
456 | edui_conf.mode |= EDUI_MODE_GROUP; | |
457 | #endif | |
458 | #ifdef EDUI_DEBUG | |
459 | edui_conf.mode |= EDUI_MODE_DEBUG; | |
460 | #endif | |
461 | } | |
462 | ||
463 | /* Displays running configuration */ | |
915c866f CN |
464 | static void |
465 | DisplayConf() | |
f86504f1 AJ |
466 | { |
467 | if (!(edui_conf.mode & EDUI_MODE_DEBUG)) | |
468 | return; | |
469 | DisplayVersion(); | |
470 | local_printfx("\n"); | |
471 | local_printfx("Configuration:\n"); | |
fe1e5c91 | 472 | local_printfx(" EDUI_MAXLEN: %u\n", EDUI_MAXLEN); |
f86504f1 AJ |
473 | if (edui_conf.mode & EDUI_MODE_DEBUG) |
474 | local_printfx(" Debug mode: ON\n"); | |
475 | else | |
476 | local_printfx(" Debug mode: OFF\n"); | |
477 | if (edui_conf.mode & EDUI_MODE_IPV4) | |
478 | local_printfx(" Address format: IPv4 (127.0.0.1)\n"); | |
479 | else if (edui_conf.mode & EDUI_MODE_IPV6) | |
480 | local_printfx(" Address format: IPv6 (::1)\n"); | |
481 | else | |
482 | local_printfx(" Address format: Not enforced.\n"); | |
483 | if (edui_conf.host[0] != '\0') | |
484 | local_printfx(" Hostname: %s\n", edui_conf.host); | |
485 | else | |
486 | local_printfx(" Hostname: localhost\n"); | |
487 | if (edui_conf.port > 0) | |
488 | local_printfx(" Port: %d\n", edui_conf.port); | |
489 | else | |
490 | local_printfx(" Port: %d\n", LDAP_PORT); | |
491 | if (edui_conf.mode & EDUI_MODE_TLS) | |
492 | local_printfx(" TLS mode: ON\n"); | |
493 | else | |
494 | local_printfx(" TLS mode: OFF\n"); | |
495 | if (edui_conf.mode & EDUI_MODE_PERSIST) { | |
496 | local_printfx(" Persistent mode: ON\n"); | |
497 | if (edui_conf.persist_timeout > 0) | |
498 | local_printfx(" Persistent mode idle timeout: %d\n", edui_conf.persist_timeout); | |
499 | else | |
500 | local_printfx(" Persistent mode idle timeout: OFF\n"); | |
501 | } else | |
502 | local_printfx(" Persistent mode: OFF\n"); | |
503 | local_printfx(" LDAP Version: %d\n", edui_conf.ver); | |
504 | if (edui_conf.basedn[0] != '\0') | |
505 | local_printfx(" Base DN: %s\n", edui_conf.basedn); | |
506 | else | |
507 | local_printfx(" Base DN: None\n"); | |
508 | if (edui_conf.dn[0] != '\0') | |
509 | local_printfx(" Binding DN: %s\n", edui_conf.dn); | |
510 | else | |
511 | local_printfx(" Binding DN: Anonymous\n"); | |
512 | if (edui_conf.passwd[0] != '\0') | |
513 | local_printfx(" Binding Password: %s\n", edui_conf.passwd); | |
514 | else | |
515 | local_printfx(" Binding Password: None\n"); | |
516 | switch (edui_conf.scope) { | |
517 | case 0: | |
518 | local_printfx(" Search Scope: base\n"); | |
519 | break; | |
520 | case 1: | |
521 | local_printfx(" Search Scope: one level\n"); | |
522 | break; | |
523 | case 2: | |
524 | local_printfx(" Search Scope: subtree\n"); | |
525 | break; | |
526 | default: | |
527 | local_printfx(" Search Scope: base\n"); | |
528 | break; | |
529 | } | |
6ca7324f AJ |
530 | if (edui_conf.attrib[0] != '\0') |
531 | local_printfx(" Search Attribute: %s\n", edui_conf.attrib); | |
532 | else | |
533 | local_printfx(" Search Attribute: cn\n"); | |
f86504f1 AJ |
534 | if (edui_conf.search_filter[0] != '\0') |
535 | local_printfx(" Search Filter: %s\n", edui_conf.search_filter); | |
536 | else | |
537 | local_printfx(" Search Filter: (&(objectClass=User)(networkAddress=*))\n"); | |
538 | if (edui_conf.mode & EDUI_MODE_GROUP) | |
539 | local_printfx(" Search Group Required: Yes\n"); | |
540 | else | |
541 | local_printfx(" Search Group Required: No\n"); | |
542 | local_printfx("\n"); | |
543 | } | |
544 | ||
545 | /* InitLDAP() - <edui_ldap_t> | |
546 | * | |
547 | * Initalize LDAP structure for use, zeroing out all variables. | |
548 | * | |
549 | */ | |
915c866f CN |
550 | static void |
551 | InitLDAP(edui_ldap_t *l) | |
f86504f1 | 552 | { |
7a545fdb | 553 | if (l == NULL) return; |
f86504f1 AJ |
554 | |
555 | l->lp = NULL; | |
556 | if (l->lm != NULL) | |
557 | ldap_msgfree(l->lm); | |
558 | if (l->val != NULL) | |
559 | ldap_value_free_len(l->val); | |
560 | l->lm = NULL; | |
561 | l->val = NULL; | |
7a545fdb AJ |
562 | *(l->basedn) = '\0'; |
563 | *(l->host) = '\0'; | |
564 | *(l->dn) = '\0'; | |
565 | *(l->passwd) = '\0'; | |
566 | *(l->search_filter) = '\0'; | |
567 | *(l->userid) = '\0'; | |
f86504f1 | 568 | memset(l->search_ip, '\0', sizeof(l->search_ip)); |
f86504f1 AJ |
569 | l->status = 0; |
570 | l->status |= LDAP_INIT_S; | |
571 | l->port = 0; | |
572 | l->scope = -1; | |
573 | l->type = 0; | |
f53969cc | 574 | l->err = -1; /* Set error to LDAP_SUCCESS by default */ |
f86504f1 AJ |
575 | l->ver = 0; |
576 | l->idle_time = 0; | |
f53969cc SM |
577 | l->num_ent = 0; /* Number of entries in l->lm */ |
578 | l->num_val = 0; /* Number of entries in l->val */ | |
f86504f1 AJ |
579 | |
580 | /* Set default settings from conf */ | |
581 | if (edui_conf.basedn[0] != '\0') | |
6ca7324f | 582 | xstrncpy(l->basedn, edui_conf.basedn, sizeof(l->basedn)); |
f86504f1 | 583 | if (edui_conf.host[0] != '\0') |
6ca7324f | 584 | xstrncpy(l->host, edui_conf.host, sizeof(l->host)); |
f86504f1 AJ |
585 | if (edui_conf.port != 0) |
586 | l->port = edui_conf.port; | |
587 | if (edui_conf.dn[0] != '\0') | |
6ca7324f | 588 | xstrncpy(l->dn, edui_conf.dn, sizeof(l->dn)); |
f86504f1 | 589 | if (edui_conf.passwd[0] != '\0') |
6ca7324f | 590 | xstrncpy(l->passwd, edui_conf.passwd, sizeof(l->passwd)); |
f86504f1 | 591 | if (edui_conf.search_filter[0] != '\0') |
6ca7324f | 592 | xstrncpy(l->search_filter, edui_conf.search_filter, sizeof(l->search_filter)); |
f86504f1 AJ |
593 | if (!(edui_conf.scope < 0)) |
594 | l->scope = edui_conf.scope; | |
f86504f1 AJ |
595 | } |
596 | ||
597 | /* OpenLDAP() - <edui_ldap_t> <host> <port> | |
598 | * | |
599 | * Build LDAP struct with hostname and port, and ready it for binding. | |
600 | * | |
601 | */ | |
915c866f CN |
602 | static int |
603 | OpenLDAP(edui_ldap_t *l, char *h, unsigned int p) | |
f86504f1 AJ |
604 | { |
605 | if ((l == NULL) || (h == NULL)) return LDAP_ERR_NULL; | |
f53969cc SM |
606 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized, or might be in use */ |
607 | if (l->status & LDAP_OPEN_S) return LDAP_ERR_OPEN; /* Already open */ | |
608 | if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */ | |
f86504f1 | 609 | |
6ca7324f | 610 | xstrncpy(l->host, h, sizeof(l->host)); |
f86504f1 AJ |
611 | if (p > 0) |
612 | l->port = p; | |
613 | else | |
f53969cc | 614 | l->port = LDAP_PORT; /* Default is port 389 */ |
f86504f1 AJ |
615 | |
616 | #ifdef NETSCAPE_SSL | |
617 | if (l->port == LDAPS_PORT) | |
f53969cc | 618 | l->status |= (LDAP_SSL_S | LDAP_TLS_S); /* SSL Port: 636 */ |
f86504f1 AJ |
619 | #endif |
620 | ||
621 | #ifdef USE_LDAP_INIT | |
622 | l->lp = ldap_init(l->host, l->port); | |
623 | #else | |
624 | l->lp = ldap_open(l->host, l->port); | |
625 | #endif | |
626 | if (l->lp == NULL) { | |
627 | l->err = LDAP_CONNECT_ERROR; | |
f53969cc | 628 | return LDAP_ERR_CONNECT; /* Unable to connect */ |
f86504f1 AJ |
629 | } else { |
630 | /* set status */ | |
631 | // l->status &= ~(LDAP_INIT_S); | |
632 | l->status |= LDAP_OPEN_S; | |
633 | l->err = LDAP_SUCCESS; | |
634 | return LDAP_ERR_SUCCESS; | |
635 | } | |
636 | } | |
637 | ||
638 | /* CloseLDAP() - <edui_ldap_t> | |
639 | * | |
640 | * Close LDAP connection, and clean up data structure. | |
641 | * | |
642 | */ | |
915c866f CN |
643 | static int |
644 | CloseLDAP(edui_ldap_t *l) | |
f86504f1 AJ |
645 | { |
646 | int s; | |
647 | if (l == NULL) return LDAP_ERR_NULL; | |
648 | if (l->lp == NULL) return LDAP_ERR_NULL; | |
f53969cc SM |
649 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Connection not initalized */ |
650 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Connection not open */ | |
f86504f1 AJ |
651 | |
652 | if (l->lm != NULL) { | |
653 | ldap_msgfree(l->lm); | |
654 | l->lm = NULL; | |
655 | } | |
656 | if (l->val != NULL) { | |
657 | ldap_value_free_len(l->val); | |
658 | l->val = NULL; | |
659 | } | |
660 | ||
661 | /* okay, so it's open, close it - No need to check other criteria */ | |
662 | s = ldap_unbind(l->lp); | |
663 | if (s == LDAP_SUCCESS) { | |
664 | l->status = LDAP_INIT_S; | |
f86504f1 | 665 | l->idle_time = 0; |
f53969cc | 666 | l->err = s; /* Set LDAP error code */ |
f86504f1 AJ |
667 | return LDAP_ERR_SUCCESS; |
668 | } else { | |
f53969cc | 669 | l->err = s; /* Set LDAP error code */ |
f86504f1 AJ |
670 | return LDAP_ERR_FAILED; |
671 | } | |
672 | } | |
673 | ||
674 | /* SetVerLDAP() - <edui_ldap_t> <version> | |
675 | * | |
676 | * Set LDAP version number for connection to <version> of 1, 2, or 3 | |
677 | * | |
678 | */ | |
915c866f CN |
679 | static int |
680 | SetVerLDAP(edui_ldap_t *l, int v) | |
f86504f1 AJ |
681 | { |
682 | int x; | |
683 | if (l == NULL) return LDAP_ERR_NULL; | |
684 | if ((v > 3) || (v < 1)) return LDAP_ERR_PARAM; | |
685 | if (l->lp == NULL) return LDAP_ERR_POINTER; | |
f53969cc SM |
686 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
687 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
688 | if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */ | |
f86504f1 AJ |
689 | |
690 | /* set version */ | |
691 | x = ldap_set_option(l->lp, LDAP_OPT_PROTOCOL_VERSION, &v); | |
692 | if (x == LDAP_SUCCESS) { | |
693 | l->ver = v; | |
f53969cc | 694 | l->err = x; /* Set LDAP error code */ |
f86504f1 AJ |
695 | return LDAP_ERR_SUCCESS; |
696 | } else { | |
f53969cc | 697 | l->err = x; /* Set LDAP error code */ |
f86504f1 AJ |
698 | return LDAP_ERR_FAILED; |
699 | } | |
700 | } | |
701 | ||
702 | /* BindLDAP() - <edui_ldap_t> <use-dn> <use-password> <type> | |
703 | * | |
704 | * Bind LDAP connection (Open) using optional dn and password, of <type> | |
705 | * | |
706 | */ | |
915c866f CN |
707 | static int |
708 | BindLDAP(edui_ldap_t *l, char *dn, char *pw, unsigned int t) | |
f86504f1 AJ |
709 | { |
710 | int s; | |
711 | if (l == NULL) return LDAP_ERR_NULL; | |
f53969cc SM |
712 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
713 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
714 | if (l->status & LDAP_BIND_S) return LDAP_ERR_BIND; /* Already bound */ | |
715 | if (l->lp == NULL) return LDAP_ERR_POINTER; /* Error */ | |
f86504f1 AJ |
716 | |
717 | /* Copy details - dn and pw CAN be NULL for anonymous and/or TLS */ | |
718 | if (dn != NULL) { | |
d08caf47 AJ |
719 | if (strlen(dn) >= sizeof(l->dn)) |
720 | return LDAP_ERR_OOB; /* DN too large */ | |
721 | ||
f86504f1 AJ |
722 | if ((l->basedn[0] != '\0') && (strstr(dn, l->basedn) == NULL)) { |
723 | /* We got a basedn, but it's not part of dn */ | |
d08caf47 AJ |
724 | const int x = snprintf(l->dn, sizeof(l->dn)-1, "%s,%s", dn, l->basedn); |
725 | if (x < 0 || static_cast<size_t>(x) >= sizeof(l->dn)) | |
726 | return LDAP_ERR_OOB; /* DN too large */ | |
f86504f1 | 727 | } else |
6ca7324f | 728 | xstrncpy(l->dn, dn, sizeof(l->dn)); |
f86504f1 AJ |
729 | } |
730 | if (pw != NULL) | |
6ca7324f | 731 | xstrncpy(l->passwd, pw, sizeof(l->passwd)); |
f86504f1 | 732 | |
7a545fdb | 733 | /* Type */ |
f86504f1 AJ |
734 | switch (t) { |
735 | case LDAP_AUTH_NONE: | |
736 | l->type = t; | |
737 | break; | |
738 | case LDAP_AUTH_SIMPLE: | |
739 | l->type = t; | |
740 | break; | |
741 | case LDAP_AUTH_SASL: | |
742 | l->type = t; | |
743 | break; | |
67245b81 | 744 | #ifdef LDAP_AUTH_KRBV4 |
f86504f1 AJ |
745 | case LDAP_AUTH_KRBV4: |
746 | l->type = t; | |
747 | break; | |
67245b81 AJ |
748 | #endif |
749 | #ifdef LDAP_AUTH_KRBV41 | |
f86504f1 AJ |
750 | case LDAP_AUTH_KRBV41: |
751 | l->type = t; | |
752 | break; | |
67245b81 AJ |
753 | #endif |
754 | #ifdef LDAP_AUTH_KRBV42 | |
f86504f1 AJ |
755 | case LDAP_AUTH_KRBV42: |
756 | l->type = t; | |
757 | break; | |
67245b81 | 758 | #endif |
f86504f1 | 759 | #ifdef LDAP_AUTH_TLS |
f53969cc | 760 | case LDAP_AUTH_TLS: /* Added for chicken switch to TLS-enabled without using SSL */ |
f86504f1 AJ |
761 | l->type = t; |
762 | break; | |
763 | #endif | |
764 | default: | |
765 | l->type = LDAP_AUTH_NONE; | |
f53969cc | 766 | break; /* Default to anonymous bind */ |
f86504f1 AJ |
767 | } |
768 | ||
769 | /* Bind */ | |
60727a6f | 770 | #if defined(LDAP_AUTH_TLS) && defined(NETSCAPE_SSL) && HAVE_LDAP_START_TLS_S |
f86504f1 AJ |
771 | if (l->type == LDAP_AUTH_TLS) |
772 | s = ldap_start_tls_s(l->lp, NULL, NULL); | |
773 | else | |
774 | #endif | |
775 | s = ldap_bind_s(l->lp, l->dn, l->passwd, l->type); | |
776 | if (s == LDAP_SUCCESS) { | |
f53969cc SM |
777 | l->status |= LDAP_BIND_S; /* Success */ |
778 | l->err = s; /* Set LDAP error code */ | |
f86504f1 AJ |
779 | return LDAP_ERR_SUCCESS; |
780 | } else { | |
f53969cc | 781 | l->err = s; /* Set LDAP error code */ |
f86504f1 AJ |
782 | return LDAP_ERR_FAILED; |
783 | } | |
784 | } | |
785 | ||
d08caf47 AJ |
786 | // XXX: duplicate (partial) of Ip::Address::lookupHostIp |
787 | /** | |
788 | * Convert the IP address string representation in src to | |
789 | * its binary representation. | |
790 | * | |
791 | * \return binary representation of the src IP address. | |
792 | * Must be free'd using freeaddrinfo(). | |
793 | */ | |
794 | static struct addrinfo * | |
795 | makeIpBinary(const char *src) | |
796 | { | |
797 | struct addrinfo want; | |
798 | memset(&want, 0, sizeof(want)); | |
799 | want.ai_flags = AI_NUMERICHOST; // prevent actual DNS lookups! | |
800 | ||
801 | struct addrinfo *dst = nullptr; | |
802 | if (getaddrinfo(src, nullptr, &want, &dst) != 0) { | |
803 | // not an IP address | |
804 | /* free any memory getaddrinfo() dynamically allocated. */ | |
805 | if (dst) | |
806 | freeaddrinfo(dst); | |
807 | return nullptr; | |
808 | } | |
809 | ||
810 | return dst; | |
811 | } | |
812 | ||
813 | /** | |
814 | * Convert srcLen bytes from src into HEX and store into dst, which | |
815 | * has a maximum content size of dstSize including c-string terminator. | |
816 | * The dst value produced will be a 0-terminated c-string. | |
817 | * | |
818 | * \retval N length of dst written (excluding c-string terminator) | |
819 | * \retval -11 (LDAP_ERR_OOB) buffer overflow detected | |
820 | */ | |
821 | static int | |
822 | makeHexString(char *dst, const int dstSize, const char *src, const int srcLen) | |
823 | { | |
824 | // HEX encoding doubles the amount of bytes/octets copied | |
825 | if ((srcLen*2) >= dstSize) | |
826 | return LDAP_ERR_OOB; // cannot copy that many | |
827 | ||
828 | *dst = 0; | |
829 | ||
830 | for (int k = 0; k < srcLen; ++k) { | |
831 | int c = static_cast<int>(src[k]); | |
832 | if (c < 0) | |
833 | c = c + 256; | |
834 | char hexc[4]; | |
835 | const int hlen = snprintf(hexc, sizeof(hexc), "%02X", c); | |
836 | if (hlen < 0 || static_cast<size_t>(hlen) > sizeof(hexc)) // should be impossible | |
837 | return LDAP_ERR_OOB; | |
838 | strcat(dst, hexc); | |
839 | } | |
840 | return strlen(dst); | |
841 | } | |
842 | ||
f86504f1 AJ |
843 | /* |
844 | * ConvertIP() - <edui_ldap_t> <ip> | |
845 | * | |
846 | * Take an IPv4 address in dot-decimal or IPv6 notation, and convert to 2-digit HEX stored in l->search_ip | |
847 | * This is the networkAddress that we search LDAP for. | |
f86504f1 | 848 | */ |
915c866f CN |
849 | static int |
850 | ConvertIP(edui_ldap_t *l, char *ip) | |
f86504f1 | 851 | { |
f86504f1 | 852 | void *y, *z; |
f86504f1 AJ |
853 | if (l == NULL) return LDAP_ERR_NULL; |
854 | if (ip == NULL) return LDAP_ERR_PARAM; | |
f53969cc SM |
855 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
856 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
857 | if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */ | |
f86504f1 AJ |
858 | |
859 | y = memchr((void *)ip, ':', EDUI_MAXLEN); | |
860 | z = memchr((void *)ip, '.', EDUI_MAXLEN); | |
861 | if ((y != NULL) && (z != NULL)) { | |
314b9463 A |
862 | y = NULL; |
863 | z = NULL; | |
864 | return LDAP_ERR_INVALID; | |
f86504f1 AJ |
865 | } |
866 | if ((y != NULL) && (edui_conf.mode & EDUI_MODE_IPV4)) { | |
314b9463 A |
867 | /* IPv4 Mode forced */ |
868 | return LDAP_ERR_INVALID; | |
869 | } else if (y != NULL) { | |
870 | /* Set IPv6 mode */ | |
314b9463 A |
871 | if (l->status & LDAP_IPV4_S) |
872 | l->status &= ~(LDAP_IPV4_S); | |
873 | if (!(l->status & LDAP_IPV6_S)) | |
874 | l->status |= (LDAP_IPV6_S); | |
875 | y = NULL; | |
f86504f1 AJ |
876 | } |
877 | if ((z != NULL) && (edui_conf.mode & EDUI_MODE_IPV6)) { | |
314b9463 A |
878 | /* IPv6 Mode forced */ |
879 | return LDAP_ERR_INVALID; | |
880 | } else if (z != NULL) { | |
314b9463 A |
881 | /* Set IPv4 mode */ |
882 | if (l->status & LDAP_IPV6_S) | |
883 | l->status &= ~(LDAP_IPV6_S); | |
884 | if (!(l->status & LDAP_IPV4_S)) | |
885 | l->status |= (LDAP_IPV4_S); | |
886 | z = NULL; | |
f86504f1 | 887 | } |
f86504f1 | 888 | |
d08caf47 AJ |
889 | size_t s = LDAP_ERR_INVALID; |
890 | if (struct addrinfo *dst = makeIpBinary(ip)) { | |
891 | if (dst->ai_family == AF_INET6) { | |
892 | struct sockaddr_in6 *sia = reinterpret_cast<struct sockaddr_in6 *>(dst->ai_addr); | |
893 | const char *ia = reinterpret_cast<const char *>(sia->sin6_addr.s6_addr); | |
894 | s = makeHexString(l->search_ip, sizeof(l->search_ip), ia, 16); // IPv6 = 16-byte address | |
895 | ||
896 | } else if (dst->ai_family == AF_INET) { | |
897 | struct sockaddr_in *sia = reinterpret_cast<struct sockaddr_in *>(dst->ai_addr); | |
898 | const char *ia = reinterpret_cast<const char *>(&(sia->sin_addr)); | |
899 | s = makeHexString(l->search_ip, sizeof(l->search_ip), ia, 4); // IPv4 = 4-byte address | |
900 | } // else leave s with LDAP_ERR_INVALID value | |
901 | freeaddrinfo(dst); | |
f86504f1 AJ |
902 | } |
903 | ||
f86504f1 AJ |
904 | return s; |
905 | } | |
906 | ||
907 | /* ResetLDAP() - <edui_ldap_t> | |
908 | * | |
909 | * Resets LDAP connection for next search query. | |
910 | * | |
911 | */ | |
915c866f CN |
912 | static int |
913 | ResetLDAP(edui_ldap_t *l) | |
314b9463 A |
914 | { |
915 | if (l == NULL) return LDAP_ERR_NULL; | |
916 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ | |
917 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
918 | if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */ | |
919 | if (!(l->status & LDAP_PERSIST_S)) return LDAP_ERR_PERSIST; /* Not persistent */ | |
920 | ||
921 | /* Cleanup data struct */ | |
314b9463 A |
922 | if (l->status & LDAP_VAL_S) |
923 | l->status &= ~(LDAP_VAL_S); | |
924 | if (l->status & LDAP_SEARCH_S) | |
925 | l->status &= ~(LDAP_SEARCH_S); | |
926 | if (l->status & LDAP_IPV4_S) | |
927 | l->status &= ~(LDAP_IPV4_S); | |
928 | if (l->status & LDAP_IPV6_S) | |
929 | l->status &= ~(LDAP_IPV6_S); | |
930 | if (l->lm != NULL) { | |
931 | ldap_msgfree(l->lm); | |
932 | l->lm = NULL; | |
933 | } | |
934 | if (l->val != NULL) { | |
935 | ldap_value_free_len(l->val); | |
936 | l->val = NULL; | |
937 | } | |
938 | memset(l->search_ip, '\0', sizeof(l->search_ip)); | |
7a545fdb | 939 | *(l->search_filter) = '\0'; |
6ca7324f | 940 | xstrncpy(l->search_filter, edui_conf.search_filter, sizeof(l->search_filter)); |
7a545fdb | 941 | *(l->userid) = '\0'; |
314b9463 A |
942 | if (!(l->status & LDAP_IDLE_S)) |
943 | l->status |= LDAP_IDLE_S; /* Set idle mode */ | |
944 | l->num_ent = 0; | |
945 | l->num_val = 0; | |
314b9463 A |
946 | l->err = LDAP_SUCCESS; |
947 | return LDAP_ERR_SUCCESS; | |
f86504f1 AJ |
948 | } |
949 | ||
950 | /* | |
951 | * SearchFilterLDAP() - <edui_ldap_t> <IP> <group> | |
952 | * | |
953 | * Build LDAP Search Filter string and copy to l->search_filter | |
954 | * | |
955 | */ | |
915c866f CN |
956 | static int |
957 | SearchFilterLDAP(edui_ldap_t *l, char *group) | |
f86504f1 AJ |
958 | { |
959 | size_t i, j, s; | |
960 | int swi; | |
961 | char bufa[EDUI_MAXLEN], bufb[EDUI_MAXLEN], bufc[EDUI_MAXLEN], bufd[EDUI_MAXLEN], bufg[EDUI_MAXLEN]; | |
962 | if (l == NULL) return LDAP_ERR_NULL; | |
f53969cc SM |
963 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
964 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
965 | if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not Bound */ | |
966 | if (l->search_ip[0] == '\0') return LDAP_ERR_DATA; /* Search IP is required */ | |
f86504f1 AJ |
967 | |
968 | /* Zero out if not already */ | |
915c866f CN |
969 | memset(bufa, '\0', sizeof(bufa)); |
970 | // using memset() for 'bufa' fixes the 64-bit issue | |
7a545fdb AJ |
971 | *(bufb) = '\0'; |
972 | *(bufc) = '\0'; | |
973 | *(bufd) = '\0'; | |
974 | *(bufg) = '\0'; | |
f86504f1 | 975 | |
f86504f1 AJ |
976 | s = strlen(l->search_ip); |
977 | bufc[0] = '\134'; | |
978 | swi = 0; | |
979 | j = 1; | |
eb62585f | 980 | for (i = 0; i < s; ++i) { |
f86504f1 AJ |
981 | if (swi == 2) { |
982 | bufc[j] = '\134'; | |
755494da | 983 | ++j; |
f86504f1 | 984 | bufc[j] = l->search_ip[i]; |
755494da | 985 | ++j; |
f86504f1 AJ |
986 | swi = 1; |
987 | } else { | |
988 | bufc[j] = l->search_ip[i]; | |
755494da FC |
989 | ++j; |
990 | ++swi; | |
f86504f1 AJ |
991 | } |
992 | } | |
993 | if (group == NULL) { | |
994 | /* No groupMembership= to add, yay! */ | |
f86504f1 | 995 | /* networkAddress */ |
314b9463 | 996 | if (l->status & LDAP_IPV4_S) { |
d08caf47 AJ |
997 | const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s)", bufc, bufc); |
998 | if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) | |
999 | return LDAP_ERR_OOB; | |
1000 | ||
f86504f1 | 1001 | } else if (l->status & LDAP_IPV6_S) { |
d08caf47 AJ |
1002 | const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s)", bufc, bufc); |
1003 | if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) | |
1004 | return LDAP_ERR_OOB; | |
1005 | } | |
1006 | const int x = snprintf(bufa, sizeof(bufa), "(&%s(|(networkAddress=1\\23%s)%s))", edui_conf.search_filter, bufc, bufd); | |
1007 | if (x < 0 || static_cast<size_t>(x) >= sizeof(bufa)) | |
1008 | return LDAP_ERR_OOB; | |
1009 | ||
f86504f1 AJ |
1010 | } else { |
1011 | /* Needs groupMembership= to add... */ | |
f86504f1 | 1012 | /* groupMembership -- NOTE: Squid *MUST* provide "cn=" from squid.conf */ |
f86504f1 | 1013 | if ((l->basedn[0] != '\0') && (strstr(group, l->basedn) == NULL)) { |
d08caf47 AJ |
1014 | const int ln = snprintf(bufg, sizeof(bufg), ",%s", l->basedn); |
1015 | if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) | |
1016 | return LDAP_ERR_OOB; | |
f86504f1 | 1017 | } |
f86504f1 | 1018 | /* networkAddress */ |
314b9463 | 1019 | if (l->status & LDAP_IPV4_S) { |
d08caf47 AJ |
1020 | const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s)", bufc, bufc); |
1021 | if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) | |
1022 | return LDAP_ERR_OOB; | |
f86504f1 | 1023 | } else if (l->status & LDAP_IPV6_S) { |
d08caf47 AJ |
1024 | const int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s)", bufc, bufc); |
1025 | if (ln < 0 || static_cast<size_t>(ln) >= sizeof(bufd)) | |
1026 | return LDAP_ERR_OOB; | |
1027 | } | |
1028 | const int x = snprintf(bufa, sizeof(bufa), "(&(&%s(groupMembership=%s%s)(|(networkAddress=1\\23%s)%s)))", edui_conf.search_filter, group, bufg, bufc, bufd); | |
1029 | if (x < 0 || static_cast<size_t>(x) >= sizeof(bufa)) | |
1030 | return LDAP_ERR_OOB; | |
f86504f1 AJ |
1031 | } |
1032 | s = strlen(bufa); | |
bcdce702 | 1033 | xstrncpy(l->search_filter, bufa, sizeof(l->search_filter)); |
f86504f1 AJ |
1034 | return s; |
1035 | } | |
1036 | ||
1037 | /* | |
1038 | * SearchLDAP() - <edui_ldap_t> <scope> <filter> <attrib> | |
1039 | * | |
1040 | * Initate LDAP query, under <scope> levels, filtering matches with <filter> and optionally <attrib> | |
1041 | * <attrib> will generally be networkAddress ... | |
1042 | * | |
1043 | */ | |
915c866f CN |
1044 | static int |
1045 | SearchLDAP(edui_ldap_t *l, int scope, char *filter, char **attrs) | |
f86504f1 AJ |
1046 | { |
1047 | int s; | |
1048 | char ft[EDUI_MAXLEN]; | |
1049 | if (l == NULL) return LDAP_ERR_NULL; | |
f53969cc | 1050 | if ((scope < 0) || (filter == NULL)) return LDAP_ERR_PARAM; /* If attrs is NULL, then all attrs will return */ |
f86504f1 | 1051 | if (l->lp == NULL) return LDAP_ERR_POINTER; |
f53969cc SM |
1052 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
1053 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
1054 | if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */ | |
1055 | if (l->status & LDAP_SEARCH_S) return LDAP_ERR_SEARCHED; /* Already searching */ | |
1056 | if (l->basedn[0] == '\0') return LDAP_ERR_DATA; /* We require a basedn */ | |
f86504f1 | 1057 | if (l->lm != NULL) |
f53969cc | 1058 | ldap_msgfree(l->lm); /* Make sure l->lm is empty */ |
f86504f1 | 1059 | |
0fbf9a8f | 1060 | xstrncpy(ft, filter, sizeof(ft)); |
f86504f1 AJ |
1061 | |
1062 | /* We have a binded connection, with a free l->lm, so let's get this done */ | |
1063 | switch (scope) { | |
1064 | case 0: | |
1065 | s = ldap_search_s(l->lp, l->basedn, LDAP_SCOPE_BASE, ft, attrs, 0, &(l->lm)); | |
1066 | break; | |
1067 | case 1: | |
1068 | s = ldap_search_s(l->lp, l->basedn, LDAP_SCOPE_ONELEVEL, ft, attrs, 0, &(l->lm)); | |
1069 | break; | |
1070 | case 2: | |
1071 | s = ldap_search_s(l->lp, l->basedn, LDAP_SCOPE_SUBTREE, ft, attrs, 0, &(l->lm)); | |
1072 | break; | |
1073 | default: | |
6ca7324f AJ |
1074 | /* Only search ONE by default */ |
1075 | s = ldap_search_s(l->lp, l->basedn, LDAP_SCOPE_ONELEVEL, ft, attrs, 0, &(l->lm)); | |
f86504f1 AJ |
1076 | break; |
1077 | } | |
1078 | if (s == LDAP_SUCCESS) { | |
f53969cc | 1079 | l->status |= (LDAP_SEARCH_S); /* Mark as searched */ |
f86504f1 | 1080 | l->err = s; |
f53969cc SM |
1081 | l->idle_time = 0; /* Connection in use, reset idle timer */ |
1082 | l->num_ent = ldap_count_entries(l->lp, l->lm); /* Counted */ | |
f86504f1 AJ |
1083 | return LDAP_ERR_SUCCESS; |
1084 | } else { | |
1085 | l->err = s; | |
1086 | l->num_ent = (-1); | |
1087 | return LDAP_ERR_FAILED; | |
1088 | } | |
1089 | } | |
1090 | ||
1091 | /* | |
7a545fdb | 1092 | * SearchIPLDAP() - <edui_ldap_t> |
f86504f1 AJ |
1093 | * |
1094 | * Scan LDAP and get all networkAddress Values, and see if they match l->search_ip | |
1095 | * Actual IP matching routine for eDirectory | |
1096 | * | |
1097 | */ | |
915c866f CN |
1098 | static int |
1099 | SearchIPLDAP(edui_ldap_t *l) | |
f86504f1 AJ |
1100 | { |
1101 | ber_len_t i, x; | |
d08caf47 AJ |
1102 | ber_len_t j; |
1103 | ber_len_t z; | |
1104 | char bufa[EDUI_MAXLEN]; | |
1105 | char bufb[EDUI_MAXLEN]; | |
f86504f1 | 1106 | LDAPMessage *ent; |
f86504f1 | 1107 | if (l == NULL) return LDAP_ERR_NULL; |
f86504f1 | 1108 | if (l->lp == NULL) return LDAP_ERR_POINTER; |
f53969cc SM |
1109 | if (!(l->status & LDAP_INIT_S)) return LDAP_ERR_INIT; /* Not initalized */ |
1110 | if (!(l->status & LDAP_OPEN_S)) return LDAP_ERR_OPEN; /* Not open */ | |
1111 | if (!(l->status & LDAP_BIND_S)) return LDAP_ERR_BIND; /* Not bound */ | |
1112 | if (!(l->status & LDAP_SEARCH_S)) return LDAP_ERR_NOT_SEARCHED; /* Not searched */ | |
9c76c145 A |
1113 | if (l->num_ent <= 0) { |
1114 | debug("l->num_ent: %d\n", l->num_ent); | |
f53969cc | 1115 | return LDAP_ERR_DATA; /* No entries found */ |
7a545fdb | 1116 | } |
f86504f1 | 1117 | if (l->val != NULL) |
f53969cc | 1118 | ldap_value_free_len(l->val); /* Clear data before populating */ |
f86504f1 AJ |
1119 | l->num_val = 0; |
1120 | if (l->status & LDAP_VAL_S) | |
f53969cc | 1121 | l->status &= ~(LDAP_VAL_S); /* Clear VAL bit */ |
f86504f1 | 1122 | if (edui_conf.attrib[0] == '\0') |
f53969cc | 1123 | xstrncpy(edui_conf.attrib, "cn", sizeof(edui_conf.attrib)); /* Make sure edui_conf.attrib is set */ |
f86504f1 AJ |
1124 | |
1125 | /* Sift through entries */ | |
9d70add4 | 1126 | struct berval **ber = NULL; |
f86504f1 AJ |
1127 | for (ent = ldap_first_entry(l->lp, l->lm); ent != NULL; ent = ldap_next_entry(l->lp, ent)) { |
1128 | l->val = ldap_get_values_len(l->lp, ent, "networkAddress"); | |
f53969cc | 1129 | ber = ldap_get_values_len(l->lp, ent, edui_conf.attrib); /* edui_conf.attrib is the <userid> mapping */ |
f86504f1 | 1130 | if (l->val != NULL) { |
f53969cc | 1131 | x = ldap_count_values_len(l->val); /* We got x values ... */ |
f86504f1 AJ |
1132 | l->num_val = x; |
1133 | if (x > 0) { | |
1134 | /* Display all values */ | |
eb62585f | 1135 | for (i = 0; i < x; ++i) { |
f86504f1 AJ |
1136 | j = l->val[i]->bv_len; |
1137 | memcpy(bufa, l->val[i]->bv_val, j); | |
7a545fdb | 1138 | z = BinarySplit(bufa, j, '#', bufb, sizeof(bufb)); |
9c76c145 | 1139 | /* BINARY DEBUGGING * |
f53969cc SM |
1140 | local_printfx("value[%" PRIuSIZE "]: BinarySplit(", (size_t) i); |
1141 | for (k = 0; k < z; ++k) { | |
1142 | c = (int) bufb[k]; | |
1143 | if (c < 0) | |
1144 | c = c + 256; | |
1145 | local_printfx("%02X", c); | |
1146 | } | |
1147 | local_printfx(", "); | |
1148 | for (k = 0; k < (j - z - 1); ++k) { | |
1149 | c = (int) bufa[k]; | |
1150 | if (c < 0) | |
1151 | c = c + 256; | |
1152 | local_printfx("%02X", c); | |
1153 | } | |
1154 | local_printfx("): %" PRIuSIZE "\n", (size_t) z); | |
9c76c145 | 1155 | * BINARY DEBUGGING */ |
f86504f1 | 1156 | z = j - z - 1; |
9c76c145 | 1157 | j = atoi(bufb); |
7a545fdb | 1158 | if (j == 1) { |
9c76c145 | 1159 | /* IPv4 address (eDirectory 8.7 and below) */ |
f86504f1 AJ |
1160 | /* bufa is the address, just compare it */ |
1161 | if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S)) | |
f53969cc | 1162 | break; /* Not looking for IPv4 */ |
d08caf47 AJ |
1163 | const int blen = makeHexString(bufb, sizeof(bufb), bufa, z); |
1164 | if (blen < 0) | |
1165 | return blen; | |
f86504f1 | 1166 | /* Compare value with IP */ |
d08caf47 | 1167 | if (memcmp(l->search_ip, bufb, blen) == 0) { |
f86504f1 AJ |
1168 | /* We got a match! - Scan 'ber' for 'cn' values */ |
1169 | z = ldap_count_values_len(ber); | |
eb62585f | 1170 | for (j = 0; j < z; ++j) { |
7a545fdb AJ |
1171 | // broken? xstrncpy(l->userid, ber[j]->bv_val, min(sizeof(l->userid),static_cast<size_t>(ber[j]->bv_len))); |
1172 | xstrncpy(l->userid, ber[j]->bv_val, sizeof(l->userid)); | |
9c76c145 A |
1173 | /* Using bv_len of min() breaks the result by 2 chars */ |
1174 | } | |
f86504f1 AJ |
1175 | ldap_value_free_len(l->val); |
1176 | l->val = NULL; | |
1177 | ldap_value_free_len(ber); | |
1178 | ber = NULL; | |
1179 | l->num_val = 0; | |
1180 | l->err = LDAP_SUCCESS; | |
1181 | l->status &= ~(LDAP_SEARCH_S); | |
f53969cc | 1182 | return LDAP_ERR_SUCCESS; /* We got our userid */ |
f86504f1 AJ |
1183 | } |
1184 | /* Not matched, continue */ | |
9c76c145 A |
1185 | } else if ((j == 8) || (j == 9)) { |
1186 | /* IPv4 (UDP/TCP) address (eDirectory 8.8 and higher) */ | |
f86504f1 AJ |
1187 | /* bufa + 2 is the address (skip 2 digit port) */ |
1188 | if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S)) | |
f53969cc | 1189 | break; /* Not looking for IPv4 */ |
d08caf47 AJ |
1190 | const int blen = makeHexString(bufb, sizeof(bufb), &bufa[2], z); |
1191 | if (blen < 0) | |
1192 | return blen; | |
f86504f1 | 1193 | /* Compare value with IP */ |
d08caf47 | 1194 | if (memcmp(l->search_ip, bufb, blen) == 0) { |
f86504f1 AJ |
1195 | /* We got a match! - Scan 'ber' for 'cn' values */ |
1196 | z = ldap_count_values_len(ber); | |
eb62585f | 1197 | for (j = 0; j < z; ++j) { |
7a545fdb AJ |
1198 | // broken? xstrncpy(l->userid, ber[j]->bv_val, min(sizeof(l->userid),static_cast<size_t>(ber[j]->bv_len))); |
1199 | xstrncpy(l->userid, ber[j]->bv_val, sizeof(l->userid)); | |
915c866f | 1200 | /* Using bv_len of min() breaks the result by 2 chars */ |
2c3d5aec | 1201 | } |
f86504f1 AJ |
1202 | ldap_value_free_len(l->val); |
1203 | l->val = NULL; | |
1204 | ldap_value_free_len(ber); | |
1205 | ber = NULL; | |
1206 | l->num_val = 0; | |
1207 | l->err = LDAP_SUCCESS; | |
1208 | l->status &= ~(LDAP_SEARCH_S); | |
f53969cc | 1209 | return LDAP_ERR_SUCCESS; /* We got our userid */ |
f86504f1 AJ |
1210 | } |
1211 | /* Not matched, continue */ | |
9c76c145 | 1212 | } else if ((j == 10) || (j == 11)) { |
7a545fdb | 1213 | /* IPv6 (UDP/TCP) address (eDirectory 8.8 and higher) */ |
f86504f1 AJ |
1214 | /* bufa + 2 is the address (skip 2 digit port) */ |
1215 | if (!(l->status & LDAP_IPV6_S)) | |
f53969cc | 1216 | break; /* Not looking for IPv6 */ |
d08caf47 AJ |
1217 | const int blen = makeHexString(bufb, sizeof(bufb), &bufa[2], z); |
1218 | if (blen < 0) | |
1219 | return blen; | |
f86504f1 | 1220 | /* Compare value with IP */ |
d08caf47 | 1221 | if (memcmp(l->search_ip, bufb, blen) == 0) { |
f86504f1 AJ |
1222 | /* We got a match! - Scan 'ber' for 'cn' values */ |
1223 | z = ldap_count_values_len(ber); | |
eb62585f | 1224 | for (j = 0; j < z; ++j) { |
7a545fdb AJ |
1225 | // broken? xstrncpy(l->userid, ber[j]->bv_val, min(sizeof(l->userid),static_cast<size_t>(ber[j]->bv_len))); |
1226 | xstrncpy(l->userid, ber[j]->bv_val, sizeof(l->userid)); | |
915c866f | 1227 | /* Using bv_len of min() breaks the result by 2 chars */ |
2c3d5aec | 1228 | } |
f86504f1 AJ |
1229 | ldap_value_free_len(l->val); |
1230 | l->val = NULL; | |
1231 | ldap_value_free_len(ber); | |
1232 | ber = NULL; | |
1233 | l->num_val = 0; | |
1234 | l->err = LDAP_SUCCESS; | |
1235 | l->status &= ~(LDAP_SEARCH_S); | |
f53969cc | 1236 | return LDAP_ERR_SUCCESS; /* We got our userid */ |
f86504f1 AJ |
1237 | } |
1238 | /* Not matched, continue */ | |
9c76c145 | 1239 | } |
f53969cc | 1240 | // else { |
9c76c145 | 1241 | /* Others are unsupported */ |
7a545fdb | 1242 | // } |
f86504f1 AJ |
1243 | } |
1244 | if (ber != NULL) { | |
1245 | ldap_value_free_len(ber); | |
1246 | ber = NULL; | |
1247 | } | |
1248 | } | |
1249 | ldap_value_free_len(l->val); | |
1250 | l->val = NULL; | |
1251 | } | |
1252 | if (ber != NULL) { | |
1253 | ldap_value_free_len(ber); | |
1254 | ber = NULL; | |
1255 | } | |
1256 | /* Attr not found, continue */ | |
1257 | } | |
1258 | /* No entries found using given attr */ | |
1259 | if (l->val != NULL) { | |
1260 | ldap_value_free_len(l->val); | |
1261 | l->val = NULL; | |
1262 | } | |
f86504f1 AJ |
1263 | if (l->lm != NULL) { |
1264 | ldap_msgfree(l->lm); | |
1265 | l->lm = NULL; | |
1266 | } | |
1267 | l->num_ent = 0; | |
1268 | l->num_val = 0; | |
1269 | l->err = LDAP_NO_SUCH_OBJECT; | |
1270 | l->status &= ~(LDAP_SEARCH_S); | |
f53969cc | 1271 | return LDAP_ERR_NOTFOUND; /* Not found ... Sorry :) */ |
f86504f1 AJ |
1272 | } |
1273 | ||
915c866f CN |
1274 | /* |
1275 | * ErrLDAP() - <errno> | |
1276 | * | |
1277 | * Returns error description of error code | |
1278 | * | |
1279 | */ | |
1280 | const char | |
1281 | *ErrLDAP(int e) | |
f86504f1 AJ |
1282 | { |
1283 | switch (e) { | |
1284 | case LDAP_ERR_NULL: | |
1285 | return "Null pointer provided"; | |
1286 | case LDAP_ERR_POINTER: | |
1287 | return "Null LDAP pointer"; | |
1288 | case LDAP_ERR_PARAM: | |
1289 | return "Null or Missing paremeter(s)"; | |
1290 | case LDAP_ERR_INIT: | |
1291 | return "LDAP data not initalized"; | |
1292 | case LDAP_ERR_OPEN: | |
1293 | return "LDAP connection is not active"; | |
1294 | case LDAP_ERR_CONNECT: | |
1295 | return "Unable to connect to LDAP host"; | |
1296 | case LDAP_ERR_BIND: | |
1297 | return "LDAP connection is not bound"; | |
1298 | case LDAP_ERR_SEARCHED: | |
1299 | return "LDAP connection has already been searched"; | |
1300 | case LDAP_ERR_NOT_SEARCHED: | |
1301 | return "LDAP connection has not been searched"; | |
1302 | case LDAP_ERR_INVALID: | |
1303 | return "Invalid paremeters"; | |
1304 | case LDAP_ERR_OOB: | |
1305 | return "Paremeter is out of bounds"; | |
1306 | case LDAP_ERR_PERSIST: | |
1307 | return "Persistent mode is not active"; | |
1308 | case LDAP_ERR_DATA: | |
1309 | return "Required data has not been found"; | |
1310 | case LDAP_ERR_NOTFOUND: | |
1311 | return "Item or object has not been found"; | |
1312 | case LDAP_ERR_OTHER: | |
61beade2 | 1313 | return "An unknown error has occurred"; |
f86504f1 AJ |
1314 | case LDAP_ERR_FAILED: |
1315 | return "Operation has failed"; | |
1316 | case LDAP_ERR_SUCCESS: | |
1317 | return "Operation is successful"; | |
1318 | default: | |
61beade2 | 1319 | return "An unknown error has occurred"; |
f86504f1 AJ |
1320 | } |
1321 | } | |
1322 | ||
915c866f CN |
1323 | /* |
1324 | * SigTrap() - <signal> | |
1325 | * | |
1326 | * Traps signal codes by number, and gracefully shuts down. | |
1327 | * | |
1328 | */ | |
1329 | extern "C" void | |
1330 | SigTrap(int s) | |
f86504f1 AJ |
1331 | { |
1332 | if (!(edui_conf.mode & EDUI_MODE_KILL)) | |
1333 | edui_conf.mode |= EDUI_MODE_KILL; | |
1334 | ||
1335 | /* Clean Up */ | |
1336 | if (edui_ldap.status & LDAP_OPEN_S) | |
1337 | CloseLDAP(&edui_ldap); | |
1338 | ||
6ca7324f | 1339 | debug("Terminating, Signal: %d\n", s); |
24885773 | 1340 | exit(EXIT_SUCCESS); |
f86504f1 AJ |
1341 | } |
1342 | ||
915c866f CN |
1343 | /* |
1344 | * MainSafe() - <argc> <argv> | |
1345 | * | |
1346 | * "Safe" version of main() | |
1347 | * | |
1348 | */ | |
1349 | static int | |
1350 | MainSafe(int argc, char **argv) | |
f86504f1 AJ |
1351 | { |
1352 | char bufa[EDUI_MAXLEN], bufb[EDUI_MAXLEN], *p = NULL; | |
1353 | char bufc[EDUI_MAXLEN]; | |
1354 | char sfmod[EDUI_MAXLEN]; | |
1355 | int x; | |
1356 | size_t i, j, s, k; | |
1357 | time_t t; | |
1358 | struct sigaction sv; | |
1359 | ||
1360 | /* Init */ | |
1361 | k = (size_t) argc; | |
1362 | memset(bufa, '\0', sizeof(bufa)); | |
1363 | memset(bufb, '\0', sizeof(bufb)); | |
1364 | memset(bufc, '\0', sizeof(bufc)); | |
1365 | memset(sfmod, '\0', sizeof(sfmod)); | |
3ea9e875 | 1366 | memset(&sv, 0, sizeof(sv)); |
7a545fdb | 1367 | |
f86504f1 | 1368 | InitConf(); |
6ca7324f | 1369 | xstrncpy(edui_conf.program, argv[0], sizeof(edui_conf.program)); |
f86504f1 AJ |
1370 | edui_now = -1; |
1371 | t = -1; | |
f86504f1 AJ |
1372 | |
1373 | /* Scan args */ | |
1374 | if (k > 1) { | |
eb62585f | 1375 | for (i = 1; i < k; ++i) { |
f86504f1 AJ |
1376 | /* Classic / novelty usage schemes */ |
1377 | if (!strcmp(argv[i], "--help")) { | |
1378 | DisplayUsage(); | |
1379 | return 1; | |
1380 | } else if (!strcmp(argv[i], "--usage")) { | |
1381 | DisplayUsage(); | |
1382 | return 1; | |
1383 | } else if (!strcmp(argv[i], "--version")) { | |
1384 | DisplayVersion(); | |
1385 | return 1; | |
1386 | } else if (argv[i][0] == '-') { | |
1387 | s = strlen(argv[i]); | |
eb62585f | 1388 | for (j = 1; j < s; ++j) { |
f86504f1 AJ |
1389 | switch (argv[i][j]) { |
1390 | case 'h': | |
1391 | DisplayUsage(); | |
1392 | return 1; | |
1393 | case 'V': | |
1394 | DisplayVersion(); | |
1395 | return 1; | |
1396 | case 'd': | |
1397 | if (!(edui_conf.mode & EDUI_MODE_DEBUG)) | |
f53969cc SM |
1398 | edui_conf.mode |= EDUI_MODE_DEBUG; /* Don't set mode more than once */ |
1399 | debug_enabled = 1; /* Official Squid-3 Debug Mode */ | |
f86504f1 AJ |
1400 | break; |
1401 | case '4': | |
1402 | if (!(edui_conf.mode & EDUI_MODE_IPV4) || !(edui_conf.mode & EDUI_MODE_IPV6)) | |
f53969cc | 1403 | edui_conf.mode |= EDUI_MODE_IPV4; /* Don't set mode more than once */ |
f86504f1 AJ |
1404 | break; |
1405 | case '6': | |
1406 | if (!(edui_conf.mode & EDUI_MODE_IPV4) || !(edui_conf.mode & EDUI_MODE_IPV6)) | |
f53969cc | 1407 | edui_conf.mode |= EDUI_MODE_IPV6; /* Don't set mode more than once */ |
f86504f1 AJ |
1408 | break; |
1409 | case 'Z': | |
1410 | if (!(edui_conf.mode & EDUI_MODE_TLS)) | |
f53969cc | 1411 | edui_conf.mode |= EDUI_MODE_TLS; /* Don't set mode more than once */ |
f86504f1 AJ |
1412 | break; |
1413 | case 'P': | |
1414 | if (!(edui_conf.mode & EDUI_MODE_PERSIST)) | |
f53969cc | 1415 | edui_conf.mode |= EDUI_MODE_PERSIST; /* Don't set mode more than once */ |
f86504f1 AJ |
1416 | break; |
1417 | case 'v': | |
f53969cc | 1418 | ++i; /* Set LDAP version */ |
f86504f1 AJ |
1419 | if (argv[i] != NULL) { |
1420 | edui_conf.ver = atoi(argv[i]); | |
1421 | if (edui_conf.ver < 1) | |
1422 | edui_conf.ver = 1; | |
1423 | else if (edui_conf.ver > 3) | |
1424 | edui_conf.ver = 3; | |
1425 | } else { | |
1426 | local_printfx("No parameters given for 'v'.\n"); | |
1427 | DisplayUsage(); | |
1428 | return 1; | |
1429 | } | |
1430 | break; | |
1431 | case 't': | |
f53969cc | 1432 | ++i; /* Set Persistent timeout */ |
f86504f1 AJ |
1433 | if (argv[i] != NULL) { |
1434 | edui_conf.persist_timeout = atoi(argv[i]); | |
1435 | if (edui_conf.persist_timeout < 0) | |
1436 | edui_conf.persist_timeout = 0; | |
1437 | } else { | |
1438 | local_printfx("No parameters given for 't'.\n"); | |
1439 | DisplayUsage(); | |
1440 | return 1; | |
1441 | } | |
1442 | break; | |
1443 | case 'b': | |
f53969cc | 1444 | ++i; /* Set Base DN */ |
f86504f1 | 1445 | if (argv[i] != NULL) |
6ca7324f | 1446 | xstrncpy(edui_conf.basedn, argv[i], sizeof(edui_conf.basedn)); |
f86504f1 AJ |
1447 | else { |
1448 | local_printfx("No parameters given for 'b'.\n"); | |
1449 | DisplayUsage(); | |
1450 | return 1; | |
1451 | } | |
1452 | break; | |
1453 | case 'H': | |
f53969cc | 1454 | ++i; /* Set Hostname */ |
f86504f1 | 1455 | if (argv[i] != NULL) |
6ca7324f | 1456 | xstrncpy(edui_conf.host, argv[i], sizeof(edui_conf.host)); |
f86504f1 AJ |
1457 | else { |
1458 | local_printfx("No parameters given for 'H'.\n"); | |
1459 | DisplayUsage(); | |
1460 | return 1; | |
1461 | } | |
1462 | break; | |
1463 | case 'p': | |
f53969cc | 1464 | ++i; /* Set port */ |
f86504f1 AJ |
1465 | if (argv[i] != NULL) |
1466 | edui_conf.port = atoi(argv[i]); | |
1467 | else { | |
1468 | local_printfx("No parameters given for 'p'.\n"); | |
1469 | DisplayUsage(); | |
1470 | return 1; | |
1471 | } | |
1472 | break; | |
1473 | case 'D': | |
f53969cc | 1474 | ++i; /* Set Bind DN */ |
f86504f1 | 1475 | if (argv[i] != NULL) |
6ca7324f | 1476 | xstrncpy(edui_conf.dn, argv[i], sizeof(edui_conf.dn)); |
f86504f1 AJ |
1477 | else { |
1478 | local_printfx("No parameters given for 'D'.\n"); | |
1479 | DisplayUsage(); | |
1480 | return 1; | |
1481 | } | |
1482 | break; | |
1483 | case 'W': | |
f53969cc | 1484 | ++i; /* Set Bind PWD */ |
f86504f1 | 1485 | if (argv[i] != NULL) |
6ca7324f | 1486 | xstrncpy(edui_conf.passwd, argv[i], sizeof(edui_conf.passwd)); |
f86504f1 AJ |
1487 | else { |
1488 | local_printfx("No parameters given for 'W'.\n"); | |
1489 | DisplayUsage(); | |
1490 | return 1; | |
1491 | } | |
1492 | break; | |
1493 | case 'F': | |
f53969cc | 1494 | ++i; /* Set Search Filter */ |
f86504f1 | 1495 | if (argv[i] != NULL) |
6ca7324f | 1496 | xstrncpy(edui_conf.search_filter, argv[i], sizeof(edui_conf.search_filter)); |
f86504f1 AJ |
1497 | else { |
1498 | local_printfx("No parameters given for 'F'.\n"); | |
1499 | DisplayUsage(); | |
1500 | return 1; | |
1501 | } | |
1502 | break; | |
1503 | case 'G': | |
1504 | if (!(edui_conf.mode & EDUI_MODE_GROUP)) | |
f53969cc | 1505 | edui_conf.mode |= EDUI_MODE_GROUP; /* Don't set mode more than once */ |
f86504f1 AJ |
1506 | break; |
1507 | case 's': | |
f53969cc | 1508 | ++i; /* Set Scope Level */ |
f86504f1 AJ |
1509 | if (argv[i] != NULL) { |
1510 | if (!strncmp(argv[i], "base", 4)) | |
1511 | edui_conf.scope = 0; | |
1512 | else if (!strncmp(argv[i], "one", 4)) | |
1513 | edui_conf.scope = 1; | |
1514 | else if (!strncmp(argv[i], "sub", 4)) | |
1515 | edui_conf.scope = 2; | |
1516 | else | |
f53969cc | 1517 | edui_conf.scope = 1; /* Default is 'one' */ |
f86504f1 AJ |
1518 | } else { |
1519 | local_printfx("No parameters given for 's'.\n"); | |
1520 | DisplayUsage(); | |
1521 | return 1; | |
1522 | } | |
1523 | break; | |
6ca7324f | 1524 | case 'u': |
f53969cc | 1525 | ++i; /* Set Search Attribute */ |
6ca7324f | 1526 | if (argv[i] != NULL) { |
ab745b44 | 1527 | xstrncpy(edui_conf.attrib, argv[i], sizeof(edui_conf.attrib)); |
6ca7324f AJ |
1528 | } else { |
1529 | local_printfx("No parameters given for 'u'.\n"); | |
1530 | DisplayUsage(); | |
1531 | return 1; | |
1532 | } | |
1533 | break; | |
f53969cc | 1534 | case '-': /* We got a second '-' ... ignore */ |
f86504f1 AJ |
1535 | break; |
1536 | default: | |
1537 | local_printfx("Invalid parameter - '%c'.\n", argv[i][j]); | |
1538 | break; | |
1539 | } | |
1540 | } | |
1541 | } else { | |
1542 | /* Incorrect parameter, display usage */ | |
1543 | DisplayUsage(); | |
1544 | return 1; | |
1545 | } | |
1546 | } | |
1547 | } | |
1548 | ||
1549 | /* Set predefined required paremeters if none are given, localhost:LDAP_PORT, etc */ | |
f53969cc | 1550 | if (edui_conf.host[0] == '\0') /* Default to localhost */ |
6ca7324f | 1551 | xstrncpy(edui_conf.host, "localhost", sizeof(edui_conf.host)); |
f86504f1 | 1552 | if (edui_conf.port < 0) |
f53969cc | 1553 | edui_conf.port = LDAP_PORT; /* Default: LDAP_PORT */ |
f86504f1 | 1554 | if ((edui_conf.mode & EDUI_MODE_IPV4) && (edui_conf.mode & EDUI_MODE_IPV6)) |
f53969cc | 1555 | edui_conf.mode &= ~(EDUI_MODE_IPV6); /* Default to IPv4 */ |
f86504f1 AJ |
1556 | if (edui_conf.ver < 0) |
1557 | edui_conf.ver = 2; | |
1558 | if (!(edui_conf.mode & EDUI_MODE_TLS)) | |
f53969cc | 1559 | edui_conf.mode |= EDUI_MODE_TLS; /* eDirectory requires TLS mode */ |
f86504f1 | 1560 | if ((edui_conf.mode & EDUI_MODE_TLS) && (edui_conf.ver < 3)) |
f53969cc | 1561 | edui_conf.ver = 3; /* TLS requires version 3 */ |
f86504f1 | 1562 | if (edui_conf.persist_timeout < 0) |
f53969cc | 1563 | edui_conf.persist_timeout = 600; /* Default: 600 seconds (10 minutes) */ |
f86504f1 | 1564 | if (edui_conf.scope < 0) |
f53969cc | 1565 | edui_conf.scope = 1; /* Default: one */ |
f86504f1 | 1566 | if (edui_conf.search_filter[0] == '\0') |
6ca7324f | 1567 | xstrncpy(edui_conf.search_filter, "(&(objectclass=User)(networkAddress=*))", sizeof(edui_conf.search_filter)); |
f86504f1 | 1568 | if (edui_conf.attrib[0] == '\0') |
6ca7324f | 1569 | xstrncpy(edui_conf.attrib, "cn", sizeof(edui_conf.attrib)); |
f86504f1 | 1570 | if (edui_conf.basedn[0] == '\0') { |
314b9463 A |
1571 | local_printfx("FATAL: No '-b' option provided (Base DN).\n"); |
1572 | DisplayUsage(); | |
1573 | return 1; | |
f86504f1 | 1574 | } |
f86504f1 AJ |
1575 | /* Trap the following signals */ |
1576 | sigemptyset(&sv.sa_mask); | |
1577 | sv.sa_handler = SigTrap; | |
1578 | sigaction(SIGTERM, &sv, NULL); | |
1579 | sv.sa_handler = SigTrap; | |
1580 | sigaction(SIGHUP, &sv, NULL); | |
1581 | sv.sa_handler = SigTrap; | |
1582 | sigaction(SIGABRT, &sv, NULL); | |
1583 | sv.sa_handler = SigTrap; | |
1584 | sigaction(SIGINT, &sv, NULL); | |
1585 | sv.sa_handler = SigTrap; | |
1586 | sigaction(SIGSEGV, &sv, NULL); | |
7a545fdb AJ |
1587 | |
1588 | DisplayConf(); | |
1589 | /* Done with arguments */ | |
f86504f1 AJ |
1590 | |
1591 | /* Set elap timer */ | |
1592 | time(&edui_now); | |
1593 | t = edui_now; | |
f86504f1 AJ |
1594 | /* Main loop -- Waits for stdin input before action */ |
1595 | while (fgets(bufa, sizeof(bufa), stdin) != NULL) { | |
1596 | if (edui_conf.mode & EDUI_MODE_KILL) | |
1597 | break; | |
1598 | time(&edui_now); | |
1599 | if (t < edui_now) { | |
1600 | /* Elapse seconds */ | |
1601 | edui_elap = edui_now - t; | |
f86504f1 AJ |
1602 | t = edui_now; |
1603 | } else | |
1604 | edui_elap = 0; | |
1605 | k = strlen(bufa); | |
9c76c145 | 1606 | /* BINARY DEBUGGING * |
fe1e5c91 | 1607 | local_printfx("while() -> bufa[%" PRIuSIZE "]: %s", k, bufa); |
eb62585f | 1608 | for (i = 0; i < k; ++i) |
9c76c145 A |
1609 | local_printfx("%02X", bufa[i]); |
1610 | local_printfx("\n"); | |
1611 | * BINARY DEBUGGING */ | |
f86504f1 AJ |
1612 | /* Check for CRLF */ |
1613 | p = strchr(bufa, '\n'); | |
1614 | if (p != NULL) | |
1615 | *p = '\0'; | |
1616 | p = strchr(bufa, '\r'); | |
1617 | if (p != NULL) | |
1618 | *p = '\0'; | |
1619 | p = strchr(bufa, ' '); | |
1620 | ||
1621 | /* No space given, but group string is required --> ERR */ | |
1622 | if ((edui_conf.mode & EDUI_MODE_GROUP) && (p == NULL)) { | |
6ca7324f | 1623 | debug("while() -> Search group is missing. (required)\n"); |
194ccc9c | 1624 | local_printfx("BH message=\"(Search Group Required)\"\n"); |
f86504f1 AJ |
1625 | continue; |
1626 | } | |
1627 | x = 0; | |
1628 | ||
1629 | /* Open LDAP connection */ | |
1630 | if (!(edui_ldap.status & LDAP_INIT_S)) { | |
1631 | InitLDAP(&edui_ldap); | |
6ca7324f | 1632 | debug("InitLDAP() -> %s\n", ErrLDAP(LDAP_ERR_SUCCESS)); |
f53969cc | 1633 | if (edui_conf.mode & EDUI_MODE_PERSIST) /* Setup persistant mode */ |
f86504f1 AJ |
1634 | edui_ldap.status |= LDAP_PERSIST_S; |
1635 | } | |
1636 | if ((edui_ldap.status & LDAP_IDLE_S) && (edui_elap > 0)) { | |
1637 | edui_ldap.idle_time = edui_ldap.idle_time + edui_elap; | |
1638 | } | |
1639 | if ((edui_ldap.status & LDAP_PERSIST_S) && (edui_ldap.status & LDAP_IDLE_S) && (edui_ldap.idle_time > edui_conf.persist_timeout)) { | |
6ca7324f | 1640 | debug("while() -> Connection timed out after %d seconds\n", (int)(edui_ldap.idle_time)); |
f86504f1 | 1641 | x = CloseLDAP(&edui_ldap); |
6ca7324f | 1642 | debug("CloseLDAP(-) -> %s\n", ErrLDAP(x)); |
f86504f1 AJ |
1643 | } |
1644 | edui_ldap.err = -1; | |
1645 | if (!(edui_ldap.status & LDAP_OPEN_S)) { | |
1646 | x = OpenLDAP(&edui_ldap, edui_conf.host, edui_conf.port); | |
1647 | if (x != LDAP_ERR_SUCCESS) { | |
1648 | /* Failed to connect */ | |
6ca7324f | 1649 | debug("OpenLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
f86504f1 | 1650 | } else { |
6ca7324f | 1651 | debug("OpenLDAP(-, %s, %d) -> %s\n", edui_conf.host, edui_conf.port, ErrLDAP(x)); |
f86504f1 AJ |
1652 | x = SetVerLDAP(&edui_ldap, edui_conf.ver); |
1653 | if (x != LDAP_ERR_SUCCESS) { | |
1654 | /* Failed to set version */ | |
6ca7324f | 1655 | debug("SetVerLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
f86504f1 | 1656 | } else |
6ca7324f | 1657 | debug("SetVerLDAP(-, %d) -> %s\n", edui_conf.ver, ErrLDAP(x)); |
f86504f1 AJ |
1658 | } |
1659 | } | |
1660 | edui_ldap.err = -1; | |
1661 | if (!(edui_ldap.status & LDAP_BIND_S) && (edui_conf.mode & EDUI_MODE_TLS)) { | |
1662 | /* TLS binding */ | |
1663 | x = BindLDAP(&edui_ldap, edui_conf.dn, edui_conf.passwd, LDAP_AUTH_TLS); | |
1664 | if (x != LDAP_ERR_SUCCESS) { | |
1665 | /* Unable to bind */ | |
6ca7324f | 1666 | debug("BindLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
194ccc9c | 1667 | local_printfx("BH message=\"(BindLDAP: %s - %s)\"\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
ab745b44 | 1668 | continue; |
f86504f1 | 1669 | } else |
6ca7324f | 1670 | debug("BindLDAP(-, %s, %s, (LDAP_AUTH_TLS)) -> %s\n", edui_conf.dn, edui_conf.passwd, ErrLDAP(x)); |
f86504f1 AJ |
1671 | } else if (!(edui_ldap.status & LDAP_BIND_S)) { |
1672 | if (edui_conf.dn[0] != '\0') { | |
1673 | /* Simple binding - using dn / passwd for authorization */ | |
1674 | x = BindLDAP(&edui_ldap, edui_conf.dn, edui_conf.passwd, LDAP_AUTH_SIMPLE); | |
1675 | if (x != LDAP_ERR_SUCCESS) { | |
1676 | /* Unable to bind */ | |
6ca7324f | 1677 | debug("BindLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
194ccc9c | 1678 | local_printfx("BH message=\"(BindLDAP: %s - %s)\"\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
ab745b44 | 1679 | continue; |
f86504f1 | 1680 | } else |
6ca7324f | 1681 | debug("BindLDAP(-, %s, %s, (LDAP_AUTH_SIMPLE)) -> %s\n", edui_conf.dn, edui_conf.passwd, ErrLDAP(x)); |
f86504f1 AJ |
1682 | } else { |
1683 | /* Anonymous binding */ | |
1684 | x = BindLDAP(&edui_ldap, edui_conf.dn, edui_conf.passwd, LDAP_AUTH_NONE); | |
1685 | if (x != LDAP_ERR_SUCCESS) { | |
1686 | /* Unable to bind */ | |
6ca7324f | 1687 | debug("BindLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
194ccc9c | 1688 | local_printfx("BH message=\"(BindLDAP: %s - %s)\"\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
ab745b44 | 1689 | continue; |
f86504f1 | 1690 | } else |
6ca7324f | 1691 | debug("BindLDAP(-, -, -, (LDAP_AUTH_NONE)) -> %s\n", ErrLDAP(x)); |
f86504f1 AJ |
1692 | } |
1693 | } | |
1694 | edui_ldap.err = -1; | |
1695 | if (edui_ldap.status & LDAP_PERSIST_S) { | |
1696 | x = ResetLDAP(&edui_ldap); | |
1697 | if (x != LDAP_ERR_SUCCESS) { | |
1698 | /* Unable to reset */ | |
6ca7324f | 1699 | debug("ResetLDAP() -> %s\n", ErrLDAP(x)); |
f86504f1 | 1700 | } else |
6ca7324f | 1701 | debug("ResetLDAP() -> %s\n", ErrLDAP(x)); |
f86504f1 AJ |
1702 | } |
1703 | if (x != LDAP_ERR_SUCCESS) { | |
1704 | /* Everything failed --> ERR */ | |
6ca7324f | 1705 | debug("while() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
f86504f1 | 1706 | CloseLDAP(&edui_ldap); |
194ccc9c | 1707 | local_printfx("BH message=\"(General Failure: %s)\"\n", ErrLDAP(x)); |
f86504f1 AJ |
1708 | continue; |
1709 | } | |
1710 | edui_ldap.err = -1; | |
1711 | /* If we got a group string, split it */ | |
1712 | if (p != NULL) { | |
1713 | /* Split string */ | |
fe1e5c91 | 1714 | debug("StringSplit(%s, ' ', %s, %" PRIuSIZE ")\n", bufa, bufb, sizeof(bufb)); |
7a545fdb | 1715 | i = StringSplit(bufa, ' ', bufb, sizeof(bufb)); |
f86504f1 | 1716 | if (i > 0) { |
fe1e5c91 | 1717 | debug("StringSplit(%s, %s) done. Result: %" PRIuSIZE "\n", bufa, bufb, i); |
f86504f1 AJ |
1718 | /* Got a group to match against */ |
1719 | x = ConvertIP(&edui_ldap, bufb); | |
1720 | if (x < 0) { | |
6ca7324f | 1721 | debug("ConvertIP() -> %s\n", ErrLDAP(x)); |
194ccc9c | 1722 | local_printfx("BH message=\"(ConvertIP: %s)\"\n", ErrLDAP(x)); |
f86504f1 AJ |
1723 | } else { |
1724 | edui_ldap.err = -1; | |
88f2cf55 | 1725 | debug("ConvertIP(-, %s) -> Result[%d]: %s\n", bufb, x, edui_ldap.search_ip); |
f86504f1 AJ |
1726 | x = SearchFilterLDAP(&edui_ldap, bufa); |
1727 | if (x < 0) { | |
6ca7324f | 1728 | debug("SearchFilterLDAP() -> %s\n", ErrLDAP(x)); |
194ccc9c | 1729 | local_printfx("BH message=\"(SearchFilterLDAP: %s)\"\n", ErrLDAP(x)); |
f86504f1 AJ |
1730 | } else { |
1731 | /* Do Search */ | |
1732 | edui_ldap.err = -1; | |
6ca7324f AJ |
1733 | debug("SearchFilterLDAP(-, %s) -> Length: %u\n", bufa, x); |
1734 | x = SearchLDAP(&edui_ldap, edui_ldap.scope, edui_ldap.search_filter, (char **) &search_attrib); | |
f86504f1 | 1735 | if (x != LDAP_ERR_SUCCESS) { |
6ca7324f | 1736 | debug("SearchLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); |
194ccc9c | 1737 | local_printfx("BH message=\"(SearchLDAP: %s)\"\n", ErrLDAP(x)); |
f86504f1 AJ |
1738 | } else { |
1739 | edui_ldap.err = -1; | |
6ca7324f | 1740 | debug("SearchLDAP(-, %d, %s, -) -> %s\n", edui_conf.scope, edui_ldap.search_filter, ErrLDAP(x)); |
7a545fdb | 1741 | x = SearchIPLDAP(&edui_ldap); |
194ccc9c CT |
1742 | if (x == LDAP_ERR_NOTFOUND) { |
1743 | debug("SearchIPLDAP() -> %s\n", ErrLDAP(x)); | |
c55b0902 | 1744 | local_printfx("ERR message=\"(SearchIPLDAP: %s)\"\n", ErrLDAP(x)); |
194ccc9c | 1745 | } else if (x == LDAP_ERR_SUCCESS) { |
7a545fdb | 1746 | debug("SearchIPLDAP(-, %s) -> %s\n", edui_ldap.userid, ErrLDAP(x)); |
f53969cc | 1747 | local_printfx("OK user=%s\n", edui_ldap.userid); /* Got userid --> OK user=<userid> */ |
194ccc9c CT |
1748 | } else { |
1749 | debug("SearchIPLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); | |
1750 | local_printfx("BH message=\"(SearchIPLDAP: %s)\"\n", ErrLDAP(x)); | |
f86504f1 AJ |
1751 | } |
1752 | } | |
1753 | /* Clear for next query */ | |
7a545fdb | 1754 | memset(bufc, '\0', sizeof(bufc)); |
f86504f1 AJ |
1755 | } |
1756 | } | |
1757 | } else { | |
fe1e5c91 | 1758 | debug("StringSplit() -> Error: %" PRIuSIZE "\n", i); |
194ccc9c | 1759 | local_printfx("BH message=\"(StringSplit Error %" PRIuSIZE ")\"\n", i); |
f86504f1 AJ |
1760 | } |
1761 | } else { | |
1762 | /* No group to match against, only an IP */ | |
1763 | x = ConvertIP(&edui_ldap, bufa); | |
1764 | if (x < 0) { | |
6ca7324f | 1765 | debug("ConvertIP() -> %s\n", ErrLDAP(x)); |
194ccc9c | 1766 | local_printfx("BH message=\"(ConvertIP: %s)\"\n", ErrLDAP(x)); |
f86504f1 | 1767 | } else { |
88f2cf55 | 1768 | debug("ConvertIP(-, %s) -> Result[%d]: %s\n", bufa, x, edui_ldap.search_ip); |
f86504f1 AJ |
1769 | /* Do search */ |
1770 | x = SearchFilterLDAP(&edui_ldap, NULL); | |
1771 | if (x < 0) { | |
6ca7324f | 1772 | debug("SearchFilterLDAP() -> %s\n", ErrLDAP(x)); |
194ccc9c | 1773 | local_printfx("BH message=\"(SearchFilterLDAP: %s)\"\n", ErrLDAP(x)); |
f86504f1 AJ |
1774 | } else { |
1775 | edui_ldap.err = -1; | |
6ca7324f AJ |
1776 | debug("SearchFilterLDAP(-, NULL) -> Length: %u\n", x); |
1777 | x = SearchLDAP(&edui_ldap, edui_ldap.scope, edui_ldap.search_filter, (char **) &search_attrib); | |
f86504f1 | 1778 | if (x != LDAP_ERR_SUCCESS) { |
6ca7324f | 1779 | debug("SearchLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(x)); |
194ccc9c | 1780 | local_printfx("BH message=\"(SearchLDAP: %s)\"\n", ErrLDAP(x)); |
f86504f1 AJ |
1781 | } else { |
1782 | edui_ldap.err = -1; | |
6ca7324f | 1783 | debug("SearchLDAP(-, %d, %s, -) -> %s\n", edui_conf.scope, edui_ldap.search_filter, ErrLDAP(x)); |
7a545fdb | 1784 | x = SearchIPLDAP(&edui_ldap); |
194ccc9c CT |
1785 | if (x == LDAP_ERR_NOTFOUND) { |
1786 | debug("SearchIPLDAP() -> %s\n", ErrLDAP(x)); | |
c55b0902 | 1787 | local_printfx("ERR message=\"(SearchIPLDAP: %s)\"\n", ErrLDAP(x)); |
194ccc9c | 1788 | } else if (x == LDAP_ERR_SUCCESS) { |
7a545fdb | 1789 | debug("SearchIPLDAP(-, %s) -> %s\n", edui_ldap.userid, ErrLDAP(x)); |
f53969cc | 1790 | local_printfx("OK user=%s\n", edui_ldap.userid); /* Got a userid --> OK user=<userid> */ |
194ccc9c CT |
1791 | } else if (x != LDAP_ERR_SUCCESS) { |
1792 | debug("SearchIPLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err)); | |
1793 | local_printfx("BH message=\"(SearchIPLDAP: %s)\"\n", ErrLDAP(x)); | |
f86504f1 AJ |
1794 | } |
1795 | } | |
1796 | } | |
1797 | /* Clear for next query */ | |
7a545fdb | 1798 | memset(bufc, '\0', sizeof(bufc)); |
f86504f1 AJ |
1799 | } |
1800 | } | |
1801 | ||
1802 | /* Clear buffer and close for next data, if not persistent */ | |
1803 | edui_ldap.err = -1; | |
7a545fdb | 1804 | memset(bufa, '\0', sizeof(bufa)); |
f86504f1 AJ |
1805 | if (!(edui_ldap.status & LDAP_PERSIST_S)) { |
1806 | x = CloseLDAP(&edui_ldap); | |
6ca7324f | 1807 | debug("CloseLDAP(-) -> %s\n", ErrLDAP(x)); |
f86504f1 AJ |
1808 | } |
1809 | } | |
1810 | ||
6ca7324f | 1811 | debug("Terminating.\n"); |
915c866f CN |
1812 | return 1; |
1813 | } | |
1814 | ||
1815 | /* "main()" - function */ | |
1816 | int | |
1817 | main(int argc, char **argv) | |
1818 | { | |
2c3d5aec A |
1819 | int x; |
1820 | x = MainSafe(argc, argv); | |
1821 | return x; | |
f86504f1 | 1822 | } |
f53969cc | 1823 |