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