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