ext_edirectory_userip_acl.cc
Go to the documentation of this file.
1 /*
2  * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
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
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  *
31  * ext_edirectory_userip_acl.cc -- Rev 2011-03-28
32  *
33  * - Misc code cleanups using "static", and 64-bit SLES fix for SearchFilterLDAP()
34  *
35  */
36 
37 /* Squid-3.X includes */
38 #include "squid.h"
40 #include "rfc1738.h"
41 #include "util.h"
42 
43 #define EDUI_PROGRAM_NAME "ext_edirectory_userip_acl"
44 #define EDUI_PROGRAM_VERSION "2.1"
45 
46 /* System includes */
47 #ifndef _GNU_SOURCE
48 #define _GNU_SOURCE
49 #endif
50 #ifndef __USE_GNU
51 #define __USE_GNU
52 #endif
53 #include <cctype>
54 #include <cerrno>
55 #include <csignal>
56 #include <cstdarg>
57 #include <cstdlib>
58 #include <cstring>
59 #include <ctime>
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
70 
71 #ifdef HELPER_INPUT_BUFFER
72 #define EDUI_MAXLEN HELPER_INPUT_BUFFER
73 #else
74 #define EDUI_MAXLEN 4096 /* Modified to improve performance, unless HELPER_INPUT_BUFFER exists */
75 #endif
76 
77 /* ldap compile options */
78 #define USE_LDAP_INIT
79 #ifndef NETSCAPE_SSL
80 # define NETSCAPE_SSL
81 #endif
82 
83 /* define LDAP_AUTH_TLS
84  * - ldap.h Hack for cleaner code, if it does not provide it.
85  */
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 */
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
101 
102 /* conf_t - Program configuration struct typedef */
103 typedef struct {
104  char program[EDUI_MAXLEN];
106  char host[EDUI_MAXLEN];
107  char attrib[EDUI_MAXLEN];
108  char dn[EDUI_MAXLEN];
109  char passwd[EDUI_MAXLEN];
110  char search_filter[EDUI_MAXLEN]; /* Base search_filter that gets copied to edui_ldap_t */
111  int ver;
112  int scope;
113  int port;
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;
157  char host[EDUI_MAXLEN];
158  char dn[EDUI_MAXLEN];
159  char passwd[EDUI_MAXLEN];
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 */
162  char userid[EDUI_MAXLEN]; /* Resulting userid */
163  unsigned int status;
164  unsigned int port;
165  unsigned long type; /* Type of bind */
166  int ver;
167  int scope;
168  int err; /* LDAP error code */
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 
174 /* Global function prototypes */
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);
178 static void DisplayVersion();
179 static void DisplayUsage();
180 static void InitConf();
181 static void DisplayConf();
182 static void InitLDAP(edui_ldap_t *);
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 *);
192 const char *ErrLDAP(int);
193 extern "C" void SigTrap(int);
194 
195 /* Global variables */
196 const char *search_attrib[] = { "cn", "uid", "networkAddress", "groupMembership", NULL };
199 time_t edui_now;
200 time_t edui_elap;
201 
202 /* local_printfx() -
203  *
204  * Print formatted message to stderr AND stdout, without preformatting.
205  *
206  * - Exists as a hack, because SEND_OK() does not appear to work here.
207  *
208  */
209 static void
210 local_printfx(const char *msg,...)
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')
217  xstrncpy(prog, EDUI_PROGRAM_NAME, sizeof(prog));
218  else
219  xstrncpy(prog, edui_conf.program, sizeof(prog));
220 
221  if (msg == NULL) {
222  /* FAIL */
223  debug("local_printfx() FAILURE, no data.\n");
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';
232  ++x;
233  fputs(dbuf, stdout);
234  *(dbuf) = '\0';
235  } else {
236  /* FAIL */
237  debug("local_printfx() FAILURE: %" PRIuSIZE "\n", x);
238  }
239 
240  /* stdout needs to be flushed for it to work with Squid */
241  fflush(stdout);
242 }
243 
244 /*
245  * StringSplit() - <string-to-split> <char> <split-object> <obj-size>
246  *
247  * Breaks down string, splitting out element <char> into <split-object>, and removing it from string.
248  * Will not exceed size tolerances.
249  *
250  */
251 static int
252 StringSplit(char *In_Str, char chr, char *Out_Str, size_t Out_Sz)
253 {
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) {
262  ++p;
263  }
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) {
278  ++p;
279  ++i;
280  } else {
281  // chr not found (or \0 found first). Wipe whole input buffer.
282  memset(In_Str, 0, In_Len);
283 // return (-3);
284 // Returning <0 breaks current ConvertIP() code for last object
285  return (i);
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);
293 }
294 
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  */
302 static int
303 BinarySplit(void *In_Obj, size_t In_Sz, char chr, void *Out_Obj, size_t Out_Sz)
304 {
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) {
315  ++p;
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) {
331  ++p;
332  ++i;
333  } else {
334  // chr not found
335  memset(In_Obj, 0, In_Sz);
336 // return (-3);
337 // Returning <0 breaks current code for last object
338  return (i);
339  }
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);
346 }
347 
348 /* Displays version information */
349 static void
351 {
352  local_printfx("Squid eDirectory IP Lookup Helper %s. Copyright (C) 2009-2011 Chad E. Naugle\n", EDUI_PROGRAM_VERSION);
353 }
354 
355 /* Displays program usage information */
356 static void
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");
374  local_printfx(" -s <scope> : Specify LDAP Search Scope (base, one, sub; defaults to 'one').\n");
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 */
386 static void
388 {
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';
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 
403  /* Set defaults from compile-time-options, if provided, but depriciated. */
404 #ifdef EDUI_BASE_DN
405  xstrncpy(edui_conf.basedn, EDUI_BASE_DN, sizeof(edui_conf.basedn));
406 #endif
407 #ifdef EDUI_DEFAULT_HOST
408  xstrncpy(edui_conf.host, EDUI_DEFAULT_HOST, sizeof(edui_conf.host));
409 #endif
410 #ifdef EDUI_BIND_DN
411  xstrncpy(edui_conf.dn, EDUI_BIND_DN, sizeof(edui_conf.dn));
412 #endif
413 #ifdef EDUI_BIND_PASS
414  xstrncpy(edui_conf.passwd, EDUI_BIND_PASS, sizeof(edui_conf.passwd));
415 #endif
416 #ifdef EDUI_USER_ATTRIB
417  xstrncpy(edui_conf.attrib, EDUI_USER_ATTRIB, sizeof(edui_conf.attrib));
418 #endif
419 #ifdef EDUI_SEARCH_FILTER
420  xstrncpy(edui_conf.search_filter, EDUI_SEARCH_FILTER, sizeof(edui_conf.search_filter));
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 */
462 static void
464 {
465  if (!(edui_conf.mode & EDUI_MODE_DEBUG))
466  return;
467  DisplayVersion();
468  local_printfx("\n");
469  local_printfx("Configuration:\n");
470  local_printfx(" EDUI_MAXLEN: %u\n", EDUI_MAXLEN);
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  }
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");
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  */
548 static void
550 {
551  if (l == NULL) return;
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;
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';
566  memset(l->search_ip, '\0', sizeof(l->search_ip));
567  l->status = 0;
568  l->status |= LDAP_INIT_S;
569  l->port = 0;
570  l->scope = -1;
571  l->type = 0;
572  l->err = -1; /* Set error to LDAP_SUCCESS by default */
573  l->ver = 0;
574  l->idle_time = 0;
575  l->num_ent = 0; /* Number of entries in l->lm */
576  l->num_val = 0; /* Number of entries in l->val */
577 
578  /* Set default settings from conf */
579  if (edui_conf.basedn[0] != '\0')
580  xstrncpy(l->basedn, edui_conf.basedn, sizeof(l->basedn));
581  if (edui_conf.host[0] != '\0')
582  xstrncpy(l->host, edui_conf.host, sizeof(l->host));
583  if (edui_conf.port != 0)
584  l->port = edui_conf.port;
585  if (edui_conf.dn[0] != '\0')
586  xstrncpy(l->dn, edui_conf.dn, sizeof(l->dn));
587  if (edui_conf.passwd[0] != '\0')
588  xstrncpy(l->passwd, edui_conf.passwd, sizeof(l->passwd));
589  if (edui_conf.search_filter[0] != '\0')
590  xstrncpy(l->search_filter, edui_conf.search_filter, sizeof(l->search_filter));
591  if (!(edui_conf.scope < 0))
592  l->scope = edui_conf.scope;
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  */
600 static int
601 OpenLDAP(edui_ldap_t *l, char *h, unsigned int p)
602 {
603  if ((l == NULL) || (h == NULL)) return LDAP_ERR_NULL;
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 */
607 
608  xstrncpy(l->host, h, sizeof(l->host));
609  if (p > 0)
610  l->port = p;
611  else
612  l->port = LDAP_PORT; /* Default is port 389 */
613 
614 #ifdef NETSCAPE_SSL
615  if (l->port == LDAPS_PORT)
616  l->status |= (LDAP_SSL_S | LDAP_TLS_S); /* SSL Port: 636 */
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;
626  return LDAP_ERR_CONNECT; /* Unable to connect */
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  */
641 static int
643 {
644  int s;
645  if (l == NULL) return LDAP_ERR_NULL;
646  if (l->lp == NULL) return LDAP_ERR_NULL;
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 */
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;
663  l->idle_time = 0;
664  l->err = s; /* Set LDAP error code */
665  return LDAP_ERR_SUCCESS;
666  } else {
667  l->err = s; /* Set LDAP error code */
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  */
677 static int
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;
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 */
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;
692  l->err = x; /* Set LDAP error code */
693  return LDAP_ERR_SUCCESS;
694  } else {
695  l->err = x; /* Set LDAP error code */
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  */
705 static int
706 BindLDAP(edui_ldap_t *l, char *dn, char *pw, unsigned int t)
707 {
708  int s;
709  if (l == NULL) return LDAP_ERR_NULL;
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 */
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 */
719  xstrncpy(l->dn, dn, sizeof(l->dn));
720  strncat(l->dn, ",", 1);
721  strncat(l->dn, l->basedn, strlen(l->basedn));
722  } else
723  xstrncpy(l->dn, dn, sizeof(l->dn));
724  }
725  if (pw != NULL)
726  xstrncpy(l->passwd, pw, sizeof(l->passwd));
727 
728  /* Type */
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;
739 #ifdef LDAP_AUTH_KRBV4
740  case LDAP_AUTH_KRBV4:
741  l->type = t;
742  break;
743 #endif
744 #ifdef LDAP_AUTH_KRBV41
745  case LDAP_AUTH_KRBV41:
746  l->type = t;
747  break;
748 #endif
749 #ifdef LDAP_AUTH_KRBV42
750  case LDAP_AUTH_KRBV42:
751  l->type = t;
752  break;
753 #endif
754 #ifdef LDAP_AUTH_TLS
755  case LDAP_AUTH_TLS: /* Added for chicken switch to TLS-enabled without using SSL */
756  l->type = t;
757  break;
758 #endif
759  default:
760  l->type = LDAP_AUTH_NONE;
761  break; /* Default to anonymous bind */
762  }
763 
764  /* Bind */
765 #if defined(LDAP_AUTH_TLS) && defined(NETSCAPE_SSL) && HAVE_LDAP_START_TLS_S
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) {
772  l->status |= LDAP_BIND_S; /* Success */
773  l->err = s; /* Set LDAP error code */
774  return LDAP_ERR_SUCCESS;
775  } else {
776  l->err = s; /* Set LDAP error code */
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  *
787  * PENDING -- CHANGE OVER TO inet*_pton, but inet6_pton does not provide the correct syntax
788  *
789  */
790 static int
791 ConvertIP(edui_ldap_t *l, char *ip)
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;
798  int i, j, t, swi; /* IPv6 "::" cut over toggle */
799  if (l == NULL) return LDAP_ERR_NULL;
800  if (ip == NULL) return LDAP_ERR_PARAM;
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 */
804 
805  y = memchr((void *)ip, ':', EDUI_MAXLEN);
806  z = memchr((void *)ip, '.', EDUI_MAXLEN);
807  if ((y != NULL) && (z != NULL)) {
808  y = NULL;
809  z = NULL;
810  return LDAP_ERR_INVALID;
811  }
812  if ((y != NULL) && (edui_conf.mode & EDUI_MODE_IPV4)) {
813  /* IPv4 Mode forced */
814  return LDAP_ERR_INVALID;
815  } else if (y != NULL) {
816  /* Set IPv6 mode */
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;
822  }
823  if ((z != NULL) && (edui_conf.mode & EDUI_MODE_IPV6)) {
824  /* IPv6 Mode forced */
825  return LDAP_ERR_INVALID;
826  } else if (z != NULL) {
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;
833  }
834  s = strlen(ip);
835  *(bufa) = '\0';
836  *(bufb) = '\0';
837  *(obj) = '\0';
838  /* StringSplit() will zero out bufa & obj at each call */
839  memset(l->search_ip, '\0', sizeof(l->search_ip));
840  xstrncpy(bufa, ip, sizeof(bufa)); /* To avoid segfaults, use bufa instead of ip */
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 */
846  xstrncpy(bufb, bufa, sizeof(bufb));
847  *(bufa) = '\0';
848  ++swi; /* Indicates that there is a bufb */
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] = ':';
852  strncat(bufb, bufa, strlen(bufa));
853  *(bufa) = '\0';
854  ++swi; /* Indicates that there is a bufb */
855  } else {
856  p = strstr(bufa, "::");
857  if (p != NULL) {
858  /* Found it, break bufa down and split into bufb here */
859  *(bufb) = '\0';
860  i = strlen(p);
861  memcpy(bufb, p, i);
862  *p = '\0';
863  bufb[i] = '\0';
864  ++swi; /* Indicates that there is a bufb */
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 */
874  t = StringSplit(bufa, '.', obj, sizeof(obj));
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)))
879  return LDAP_ERR_OOB; /* Out of bounds -- Invalid address */
880  memset(hexc, '\0', sizeof(hexc));
881  int hlen = snprintf(hexc, sizeof(hexc), "%02X", (int)x);
882  strncat(l->search_ip, hexc, hlen);
883  } else
884  break; /* reached end of octet */
885  } else if (l->status & LDAP_IPV6_S) {
886  /* Break down IPv6 address */
887  if (swi > 1)
888  t = StringSplit(bufb, ':', obj, sizeof(obj)); /* After "::" */
889  else
890  t = StringSplit(bufa, ':', obj, sizeof(obj)); /* Before "::" */
891  /* Convert octet by size (t) - and fill 0's */
892  switch (t) { /* IPv6 is already in HEX, copy contents */
893  case 4:
894  hexc[0] = (char) toupper((int)obj[0]);
895  i = (int)hexc[0];
896  if (!isxdigit(i))
897  return LDAP_ERR_OOB; /* Out of bounds */
898  hexc[1] = (char) toupper((int)obj[1]);
899  i = (int)hexc[1];
900  if (!isxdigit(i))
901  return LDAP_ERR_OOB; /* Out of bounds */
902  hexc[2] = '\0';
903  strncat(l->search_ip, hexc, 2);
904  hexc[0] = (char) toupper((int)obj[2]);
905  i = (int)hexc[0];
906  if (!isxdigit(i))
907  return LDAP_ERR_OOB; /* Out of bounds */
908  hexc[1] = (char) toupper((int)obj[3]);
909  i = (int)hexc[1];
910  if (!isxdigit(i))
911  return LDAP_ERR_OOB; /* Out of bounds */
912  hexc[2] = '\0';
913  strncat(l->search_ip, hexc, 2);
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))
920  return LDAP_ERR_OOB; /* Out of bounds */
921  hexc[2] = '\0';
922  strncat(l->search_ip, hexc, 2);
923  hexc[0] = (char) toupper((int)obj[1]);
924  i = (int)hexc[0];
925  if (!isxdigit(i))
926  return LDAP_ERR_OOB; /* Out of bounds */
927  hexc[1] = (char) toupper((int)obj[2]);
928  i = (int)hexc[1];
929  if (!isxdigit(i))
930  return LDAP_ERR_OOB; /* Out of bounds */
931  hexc[2] = '\0';
932  strncat(l->search_ip, hexc, 2);
933  break;
934  case 2:
935  strncat(l->search_ip, "00", 2);
936  hexc[0] = (char) toupper((int)obj[0]);
937  i = (int)hexc[0];
938  if (!isxdigit(i))
939  return LDAP_ERR_OOB; /* Out of bounds */
940  hexc[1] = (char) toupper((int)obj[1]);
941  i = (int)hexc[1];
942  if (!isxdigit(i))
943  return LDAP_ERR_OOB; /* Out of bounds */
944  hexc[2] = '\0';
945  strncat(l->search_ip, hexc, 2);
946  break;
947  case 1:
948  strncat(l->search_ip, "00", 2);
949  hexc[0] = '0';
950  hexc[1] = (char) toupper((int)obj[0]);
951  i = (int)hexc[1];
952  if (!isxdigit(i))
953  return LDAP_ERR_OOB; /* Out of bounds */
954  hexc[2] = '\0';
955  strncat(l->search_ip, hexc, 2);
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)) {
964  /* We are *AT* the split, pad in some 0000 */
965  t = strlen(bufb);
966  /* How many ':' exist in bufb ? */
967  j = 0;
968  for (i = 0; i < t; ++i) {
969  if (bufb[i] == ':')
970  ++j;
971  }
972  --j; /* Preceding "::" doesn't count */
973  t = 8 - (strlen(l->search_ip) / 4) - j; /* Remainder */
974  if (t > 0) {
975  for (i = 0; i < t; ++i)
976  strncat(l->search_ip, "0000", 4);
977  }
978  }
979  }
980  if ((bufa[0] == '\0') && (swi > 0)) {
981  s = strlen(bufb);
982  ++swi;
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)) {
991  strncat(l->search_ip, "0000", 4);
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)) {
1001  strncat(l->search_ip, "00", 2);
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  */
1019 static int
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 */
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));
1046  *(l->search_filter) = '\0';
1047  xstrncpy(l->search_filter, edui_conf.search_filter, sizeof(l->search_filter));
1048  *(l->userid) = '\0';
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;
1053  l->err = LDAP_SUCCESS;
1054  return LDAP_ERR_SUCCESS;
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  */
1063 static int
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;
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 */
1074 
1075  /* Zero out if not already */
1076  memset(bufa, '\0', sizeof(bufa));
1077  // using memset() for 'bufa' fixes the 64-bit issue
1078  *(bufb) = '\0';
1079  *(bufc) = '\0';
1080  *(bufd) = '\0';
1081  *(bufg) = '\0';
1082 
1083  s = strlen(l->search_ip);
1084  bufc[0] = '\134';
1085  swi = 0;
1086  j = 1;
1087  for (i = 0; i < s; ++i) {
1088  if (swi == 2) {
1089  bufc[j] = '\134';
1090  ++j;
1091  bufc[j] = l->search_ip[i];
1092  ++j;
1093  swi = 1;
1094  } else {
1095  bufc[j] = l->search_ip[i];
1096  ++j;
1097  ++swi;
1098  }
1099  }
1100  if (group == NULL) {
1101  /* No groupMembership= to add, yay! */
1102  xstrncpy(bufa, "(&", sizeof(bufa));
1103  strncat(bufa, edui_conf.search_filter, strlen(edui_conf.search_filter));
1104  /* networkAddress */
1105  snprintf(bufb, sizeof(bufb), "(|(networkAddress=1\\23%s)", bufc);
1106  if (l->status & LDAP_IPV4_S) {
1107  int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \
1108  bufc, bufc);
1109  strncat(bufb, bufd, ln);
1110  } else if (l->status & LDAP_IPV6_S) {
1111  int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \
1112  bufc, bufc);
1113  strncat(bufb, bufd, ln);
1114  } else
1115  strncat(bufb, ")", 1);
1116  strncat(bufa, bufb, strlen(bufb));
1117  strncat(bufa, ")", 1);
1118  } else {
1119  /* Needs groupMembership= to add... */
1120  xstrncpy(bufa, "(&(&", sizeof(bufa));
1121  strncat(bufa, edui_conf.search_filter, strlen(edui_conf.search_filter));
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)) {
1125  strncat(bufg, ",", 1);
1126  strncat(bufg, l->basedn, strlen(l->basedn));
1127  }
1128  strncat(bufg, ")", 1);
1129  strncat(bufa, bufg, strlen(bufg));
1130  /* networkAddress */
1131  snprintf(bufb, sizeof(bufb), "(|(networkAddress=1\\23%s)", bufc);
1132  if (l->status & LDAP_IPV4_S) {
1133  int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=8\\23\\00\\00%s)(networkAddress=9\\23\\00\\00%s))", \
1134  bufc, bufc);
1135  strncat(bufb, bufd, ln);
1136  } else if (l->status & LDAP_IPV6_S) {
1137  int ln = snprintf(bufd, sizeof(bufd), "(networkAddress=10\\23\\00\\00%s)(networkAddress=11\\23\\00\\00%s))", \
1138  bufc, bufc);
1139  strncat(bufb, bufd, ln);
1140  } else
1141  strncat(bufb, ")", 1);
1142  strncat(bufa, bufb, strlen(bufb));
1143  strncat(bufa, "))", 2);
1144  }
1145  s = strlen(bufa);
1146  xstrncpy(l->search_filter, bufa, sizeof(l->search_filter));
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  */
1157 static int
1158 SearchLDAP(edui_ldap_t *l, int scope, char *filter, char **attrs)
1159 {
1160  int s;
1161  char ft[EDUI_MAXLEN];
1162  if (l == NULL) return LDAP_ERR_NULL;
1163  if ((scope < 0) || (filter == NULL)) return LDAP_ERR_PARAM; /* If attrs is NULL, then all attrs will return */
1164  if (l->lp == NULL) return LDAP_ERR_POINTER;
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 */
1170  if (l->lm != NULL)
1171  ldap_msgfree(l->lm); /* Make sure l->lm is empty */
1172 
1173  xstrncpy(ft, filter, sizeof(ft));
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:
1187  /* Only search ONE by default */
1188  s = ldap_search_s(l->lp, l->basedn, LDAP_SCOPE_ONELEVEL, ft, attrs, 0, &(l->lm));
1189  break;
1190  }
1191  if (s == LDAP_SUCCESS) {
1192  l->status |= (LDAP_SEARCH_S); /* Mark as searched */
1193  l->err = s;
1194  l->idle_time = 0; /* Connection in use, reset idle timer */
1195  l->num_ent = ldap_count_entries(l->lp, l->lm); /* Counted */
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 /*
1205  * SearchIPLDAP() - <edui_ldap_t>
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  */
1211 static int
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;
1220  if (l == NULL) return LDAP_ERR_NULL;
1221  if (l->lp == NULL) return LDAP_ERR_POINTER;
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 */
1226  if (l->num_ent <= 0) {
1227  debug("l->num_ent: %d\n", l->num_ent);
1228  return LDAP_ERR_DATA; /* No entries found */
1229  }
1230  if (l->val != NULL)
1231  ldap_value_free_len(l->val); /* Clear data before populating */
1232  l->num_val = 0;
1233  if (l->status & LDAP_VAL_S)
1234  l->status &= ~(LDAP_VAL_S); /* Clear VAL bit */
1235  if (edui_conf.attrib[0] == '\0')
1236  xstrncpy(edui_conf.attrib, "cn", sizeof(edui_conf.attrib)); /* Make sure edui_conf.attrib is set */
1237 
1238  /* Sift through entries */
1239  struct berval **ber = NULL;
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");
1242  ber = ldap_get_values_len(l->lp, ent, edui_conf.attrib); /* edui_conf.attrib is the <userid> mapping */
1243  if (l->val != NULL) {
1244  x = ldap_count_values_len(l->val); /* We got x values ... */
1245  l->num_val = x;
1246  if (x > 0) {
1247  /* Display all values */
1248  for (i = 0; i < x; ++i) {
1249  j = l->val[i]->bv_len;
1250  memcpy(bufa, l->val[i]->bv_val, j);
1251  z = BinarySplit(bufa, j, '#', bufb, sizeof(bufb));
1252  /* BINARY DEBUGGING *
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);
1268  * BINARY DEBUGGING */
1269  z = j - z - 1;
1270  j = atoi(bufb);
1271  if (j == 1) {
1272  /* IPv4 address (eDirectory 8.7 and below) */
1273  /* bufa is the address, just compare it */
1274  if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S))
1275  break; /* Not looking for IPv4 */
1276  for (k = 0; k < z; ++k) {
1277  c = (int) bufa[k];
1278  if (c < 0)
1279  c = c + 256;
1280  int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
1281  if (k == 0)
1282  xstrncpy(bufb, hexc, sizeof(bufb));
1283  else
1284  strncat(bufb, hexc, hlen);
1285  }
1286  y = strlen(bufb);
1287  /* Compare value with IP */
1288  if (memcmp(l->search_ip, bufb, y) == 0) {
1289  /* We got a match! - Scan 'ber' for 'cn' values */
1290  z = ldap_count_values_len(ber);
1291  for (j = 0; j < z; ++j) {
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));
1294  /* Using bv_len of min() breaks the result by 2 chars */
1295  }
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);
1303  return LDAP_ERR_SUCCESS; /* We got our userid */
1304  }
1305  /* Not matched, continue */
1306  } else if ((j == 8) || (j == 9)) {
1307  /* IPv4 (UDP/TCP) address (eDirectory 8.8 and higher) */
1308  /* bufa + 2 is the address (skip 2 digit port) */
1309  if (!(l->status & LDAP_IPV4_S) || (l->status & LDAP_IPV6_S))
1310  break; /* Not looking for IPv4 */
1311  for (k = 2; k < z; ++k) {
1312  c = (int) bufa[k];
1313  if (c < 0)
1314  c = c + 256;
1315  int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
1316  if (k == 2)
1317  xstrncpy(bufb, hexc, sizeof(bufb));
1318  else
1319  strncat(bufb, hexc, hlen);
1320  }
1321  y = strlen(bufb);
1322  /* Compare value with IP */
1323  if (memcmp(l->search_ip, bufb, y) == 0) {
1324  /* We got a match! - Scan 'ber' for 'cn' values */
1325  z = ldap_count_values_len(ber);
1326  for (j = 0; j < z; ++j) {
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));
1329  /* Using bv_len of min() breaks the result by 2 chars */
1330  }
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);
1338  return LDAP_ERR_SUCCESS; /* We got our userid */
1339  }
1340  /* Not matched, continue */
1341  } else if ((j == 10) || (j == 11)) {
1342  /* IPv6 (UDP/TCP) address (eDirectory 8.8 and higher) */
1343  /* bufa + 2 is the address (skip 2 digit port) */
1344  if (!(l->status & LDAP_IPV6_S))
1345  break; /* Not looking for IPv6 */
1346  for (k = 2; k < z; ++k) {
1347  c = (int) bufa[k];
1348  if (c < 0)
1349  c = c + 256;
1350  int hlen = snprintf(hexc, sizeof(hexc), "%02X", c);
1351  if (k == 2)
1352  xstrncpy(bufb, hexc, sizeof(bufb));
1353  else
1354  strncat(bufb, hexc, hlen);
1355  }
1356  y = strlen(bufb);
1357  /* Compare value with IP */
1358  if (memcmp(l->search_ip, bufb, y) == 0) {
1359  /* We got a match! - Scan 'ber' for 'cn' values */
1360  z = ldap_count_values_len(ber);
1361  for (j = 0; j < z; ++j) {
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));
1364  /* Using bv_len of min() breaks the result by 2 chars */
1365  }
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);
1373  return LDAP_ERR_SUCCESS; /* We got our userid */
1374  }
1375  /* Not matched, continue */
1376  }
1377 // else {
1378  /* Others are unsupported */
1379 // }
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  }
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);
1408  return LDAP_ERR_NOTFOUND; /* Not found ... Sorry :) */
1409 }
1410 
1411 /*
1412  * ErrLDAP() - <errno>
1413  *
1414  * Returns error description of error code
1415  *
1416  */
1417 const char
1418 *ErrLDAP(int e)
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 
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)
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 
1476  debug("Terminating, Signal: %d\n", s);
1477  exit(EXIT_SUCCESS);
1478 }
1479 
1480 /*
1481  * MainSafe() - <argc> <argv>
1482  *
1483  * "Safe" version of main()
1484  *
1485  */
1486 static int
1487 MainSafe(int argc, char **argv)
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));
1503  memset(&sv, 0, sizeof(sv));
1504 
1505  InitConf();
1506  xstrncpy(edui_conf.program, argv[0], sizeof(edui_conf.program));
1507  edui_now = -1;
1508  t = -1;
1509 
1510  /* Scan args */
1511  if (k > 1) {
1512  for (i = 1; i < k; ++i) {
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]);
1525  for (j = 1; j < s; ++j) {
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))
1535  edui_conf.mode |= EDUI_MODE_DEBUG; /* Don't set mode more than once */
1536  debug_enabled = 1; /* Official Squid-3 Debug Mode */
1537  break;
1538  case '4':
1539  if (!(edui_conf.mode & EDUI_MODE_IPV4) || !(edui_conf.mode & EDUI_MODE_IPV6))
1540  edui_conf.mode |= EDUI_MODE_IPV4; /* Don't set mode more than once */
1541  break;
1542  case '6':
1543  if (!(edui_conf.mode & EDUI_MODE_IPV4) || !(edui_conf.mode & EDUI_MODE_IPV6))
1544  edui_conf.mode |= EDUI_MODE_IPV6; /* Don't set mode more than once */
1545  break;
1546  case 'Z':
1547  if (!(edui_conf.mode & EDUI_MODE_TLS))
1548  edui_conf.mode |= EDUI_MODE_TLS; /* Don't set mode more than once */
1549  break;
1550  case 'P':
1551  if (!(edui_conf.mode & EDUI_MODE_PERSIST))
1552  edui_conf.mode |= EDUI_MODE_PERSIST; /* Don't set mode more than once */
1553  break;
1554  case 'v':
1555  ++i; /* Set LDAP version */
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':
1569  ++i; /* Set Persistent timeout */
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':
1581  ++i; /* Set Base DN */
1582  if (argv[i] != NULL)
1583  xstrncpy(edui_conf.basedn, argv[i], sizeof(edui_conf.basedn));
1584  else {
1585  local_printfx("No parameters given for 'b'.\n");
1586  DisplayUsage();
1587  return 1;
1588  }
1589  break;
1590  case 'H':
1591  ++i; /* Set Hostname */
1592  if (argv[i] != NULL)
1593  xstrncpy(edui_conf.host, argv[i], sizeof(edui_conf.host));
1594  else {
1595  local_printfx("No parameters given for 'H'.\n");
1596  DisplayUsage();
1597  return 1;
1598  }
1599  break;
1600  case 'p':
1601  ++i; /* Set port */
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':
1611  ++i; /* Set Bind DN */
1612  if (argv[i] != NULL)
1613  xstrncpy(edui_conf.dn, argv[i], sizeof(edui_conf.dn));
1614  else {
1615  local_printfx("No parameters given for 'D'.\n");
1616  DisplayUsage();
1617  return 1;
1618  }
1619  break;
1620  case 'W':
1621  ++i; /* Set Bind PWD */
1622  if (argv[i] != NULL)
1623  xstrncpy(edui_conf.passwd, argv[i], sizeof(edui_conf.passwd));
1624  else {
1625  local_printfx("No parameters given for 'W'.\n");
1626  DisplayUsage();
1627  return 1;
1628  }
1629  break;
1630  case 'F':
1631  ++i; /* Set Search Filter */
1632  if (argv[i] != NULL)
1633  xstrncpy(edui_conf.search_filter, argv[i], sizeof(edui_conf.search_filter));
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))
1642  edui_conf.mode |= EDUI_MODE_GROUP; /* Don't set mode more than once */
1643  break;
1644  case 's':
1645  ++i; /* Set Scope Level */
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
1654  edui_conf.scope = 1; /* Default is 'one' */
1655  } else {
1656  local_printfx("No parameters given for 's'.\n");
1657  DisplayUsage();
1658  return 1;
1659  }
1660  break;
1661  case 'u':
1662  ++i; /* Set Search Attribute */
1663  if (argv[i] != NULL) {
1664  xstrncpy(edui_conf.attrib, argv[i], sizeof(edui_conf.attrib));
1665  } else {
1666  local_printfx("No parameters given for 'u'.\n");
1667  DisplayUsage();
1668  return 1;
1669  }
1670  break;
1671  case '-': /* We got a second '-' ... ignore */
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 */
1687  if (edui_conf.host[0] == '\0') /* Default to localhost */
1688  xstrncpy(edui_conf.host, "localhost", sizeof(edui_conf.host));
1689  if (edui_conf.port < 0)
1690  edui_conf.port = LDAP_PORT; /* Default: LDAP_PORT */
1691  if ((edui_conf.mode & EDUI_MODE_IPV4) && (edui_conf.mode & EDUI_MODE_IPV6))
1692  edui_conf.mode &= ~(EDUI_MODE_IPV6); /* Default to IPv4 */
1693  if (edui_conf.ver < 0)
1694  edui_conf.ver = 2;
1695  if (!(edui_conf.mode & EDUI_MODE_TLS))
1696  edui_conf.mode |= EDUI_MODE_TLS; /* eDirectory requires TLS mode */
1697  if ((edui_conf.mode & EDUI_MODE_TLS) && (edui_conf.ver < 3))
1698  edui_conf.ver = 3; /* TLS requires version 3 */
1699  if (edui_conf.persist_timeout < 0)
1700  edui_conf.persist_timeout = 600; /* Default: 600 seconds (10 minutes) */
1701  if (edui_conf.scope < 0)
1702  edui_conf.scope = 1; /* Default: one */
1703  if (edui_conf.search_filter[0] == '\0')
1704  xstrncpy(edui_conf.search_filter, "(&(objectclass=User)(networkAddress=*))", sizeof(edui_conf.search_filter));
1705  if (edui_conf.attrib[0] == '\0')
1706  xstrncpy(edui_conf.attrib, "cn", sizeof(edui_conf.attrib));
1707  if (edui_conf.basedn[0] == '\0') {
1708  local_printfx("FATAL: No '-b' option provided (Base DN).\n");
1709  DisplayUsage();
1710  return 1;
1711  }
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);
1724 
1725  DisplayConf();
1726  /* Done with arguments */
1727 
1728  /* Set elap timer */
1729  time(&edui_now);
1730  t = edui_now;
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;
1739  t = edui_now;
1740  } else
1741  edui_elap = 0;
1742  k = strlen(bufa);
1743  /* BINARY DEBUGGING *
1744  local_printfx("while() -> bufa[%" PRIuSIZE "]: %s", k, bufa);
1745  for (i = 0; i < k; ++i)
1746  local_printfx("%02X", bufa[i]);
1747  local_printfx("\n");
1748  * BINARY DEBUGGING */
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)) {
1760  debug("while() -> Search group is missing. (required)\n");
1761  local_printfx("BH message=\"(Search Group Required)\"\n");
1762  continue;
1763  }
1764  x = 0;
1765 
1766  /* Open LDAP connection */
1767  if (!(edui_ldap.status & LDAP_INIT_S)) {
1768  InitLDAP(&edui_ldap);
1769  debug("InitLDAP() -> %s\n", ErrLDAP(LDAP_ERR_SUCCESS));
1770  if (edui_conf.mode & EDUI_MODE_PERSIST) /* Setup persistant mode */
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)) {
1777  debug("while() -> Connection timed out after %d seconds\n", (int)(edui_ldap.idle_time));
1778  x = CloseLDAP(&edui_ldap);
1779  debug("CloseLDAP(-) -> %s\n", ErrLDAP(x));
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 */
1786  debug("OpenLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1787  } else {
1788  debug("OpenLDAP(-, %s, %d) -> %s\n", edui_conf.host, edui_conf.port, ErrLDAP(x));
1789  x = SetVerLDAP(&edui_ldap, edui_conf.ver);
1790  if (x != LDAP_ERR_SUCCESS) {
1791  /* Failed to set version */
1792  debug("SetVerLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1793  } else
1794  debug("SetVerLDAP(-, %d) -> %s\n", edui_conf.ver, ErrLDAP(x));
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 */
1803  debug("BindLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1804  local_printfx("BH message=\"(BindLDAP: %s - %s)\"\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1805  continue;
1806  } else
1807  debug("BindLDAP(-, %s, %s, (LDAP_AUTH_TLS)) -> %s\n", edui_conf.dn, edui_conf.passwd, ErrLDAP(x));
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 */
1814  debug("BindLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1815  local_printfx("BH message=\"(BindLDAP: %s - %s)\"\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1816  continue;
1817  } else
1818  debug("BindLDAP(-, %s, %s, (LDAP_AUTH_SIMPLE)) -> %s\n", edui_conf.dn, edui_conf.passwd, ErrLDAP(x));
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 */
1824  debug("BindLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1825  local_printfx("BH message=\"(BindLDAP: %s - %s)\"\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1826  continue;
1827  } else
1828  debug("BindLDAP(-, -, -, (LDAP_AUTH_NONE)) -> %s\n", ErrLDAP(x));
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 */
1836  debug("ResetLDAP() -> %s\n", ErrLDAP(x));
1837  } else
1838  debug("ResetLDAP() -> %s\n", ErrLDAP(x));
1839  }
1840  if (x != LDAP_ERR_SUCCESS) {
1841  /* Everything failed --> ERR */
1842  debug("while() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1843  CloseLDAP(&edui_ldap);
1844  local_printfx("BH message=\"(General Failure: %s)\"\n", ErrLDAP(x));
1845  continue;
1846  }
1847  edui_ldap.err = -1;
1848  /* If we got a group string, split it */
1849  if (p != NULL) {
1850  /* Split string */
1851  debug("StringSplit(%s, ' ', %s, %" PRIuSIZE ")\n", bufa, bufb, sizeof(bufb));
1852  i = StringSplit(bufa, ' ', bufb, sizeof(bufb));
1853  if (i > 0) {
1854  debug("StringSplit(%s, %s) done. Result: %" PRIuSIZE "\n", bufa, bufb, i);
1855  /* Got a group to match against */
1856  x = ConvertIP(&edui_ldap, bufb);
1857  if (x < 0) {
1858  debug("ConvertIP() -> %s\n", ErrLDAP(x));
1859  local_printfx("BH message=\"(ConvertIP: %s)\"\n", ErrLDAP(x));
1860  } else {
1861  edui_ldap.err = -1;
1862  debug("ConvertIP(-, %s) -> Result[%d]: %s\n", bufb, x, edui_ldap.search_ip);
1863  x = SearchFilterLDAP(&edui_ldap, bufa);
1864  if (x < 0) {
1865  debug("SearchFilterLDAP() -> %s\n", ErrLDAP(x));
1866  local_printfx("BH message=\"(SearchFilterLDAP: %s)\"\n", ErrLDAP(x));
1867  } else {
1868  /* Do Search */
1869  edui_ldap.err = -1;
1870  debug("SearchFilterLDAP(-, %s) -> Length: %u\n", bufa, x);
1871  x = SearchLDAP(&edui_ldap, edui_ldap.scope, edui_ldap.search_filter, (char **) &search_attrib);
1872  if (x != LDAP_ERR_SUCCESS) {
1873  debug("SearchLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(edui_ldap.err));
1874  local_printfx("BH message=\"(SearchLDAP: %s)\"\n", ErrLDAP(x));
1875  } else {
1876  edui_ldap.err = -1;
1877  debug("SearchLDAP(-, %d, %s, -) -> %s\n", edui_conf.scope, edui_ldap.search_filter, ErrLDAP(x));
1878  x = SearchIPLDAP(&edui_ldap);
1879  if (x == LDAP_ERR_NOTFOUND) {
1880  debug("SearchIPLDAP() -> %s\n", ErrLDAP(x));
1881  local_printfx("ERR message=\"(SearchIPLDAP: %s)\"\n", ErrLDAP(x));
1882  } else if (x == LDAP_ERR_SUCCESS) {
1883  debug("SearchIPLDAP(-, %s) -> %s\n", edui_ldap.userid, ErrLDAP(x));
1884  local_printfx("OK user=%s\n", edui_ldap.userid); /* Got userid --> OK user=<userid> */
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));
1888  }
1889  }
1890  /* Clear for next query */
1891  memset(bufc, '\0', sizeof(bufc));
1892  }
1893  }
1894  } else {
1895  debug("StringSplit() -> Error: %" PRIuSIZE "\n", i);
1896  local_printfx("BH message=\"(StringSplit Error %" PRIuSIZE ")\"\n", i);
1897  }
1898  } else {
1899  /* No group to match against, only an IP */
1900  x = ConvertIP(&edui_ldap, bufa);
1901  if (x < 0) {
1902  debug("ConvertIP() -> %s\n", ErrLDAP(x));
1903  local_printfx("BH message=\"(ConvertIP: %s)\"\n", ErrLDAP(x));
1904  } else {
1905  debug("ConvertIP(-, %s) -> Result[%d]: %s\n", bufa, x, edui_ldap.search_ip);
1906  /* Do search */
1907  x = SearchFilterLDAP(&edui_ldap, NULL);
1908  if (x < 0) {
1909  debug("SearchFilterLDAP() -> %s\n", ErrLDAP(x));
1910  local_printfx("BH message=\"(SearchFilterLDAP: %s)\"\n", ErrLDAP(x));
1911  } else {
1912  edui_ldap.err = -1;
1913  debug("SearchFilterLDAP(-, NULL) -> Length: %u\n", x);
1914  x = SearchLDAP(&edui_ldap, edui_ldap.scope, edui_ldap.search_filter, (char **) &search_attrib);
1915  if (x != LDAP_ERR_SUCCESS) {
1916  debug("SearchLDAP() -> %s (LDAP: %s)\n", ErrLDAP(x), ldap_err2string(x));
1917  local_printfx("BH message=\"(SearchLDAP: %s)\"\n", ErrLDAP(x));
1918  } else {
1919  edui_ldap.err = -1;
1920  debug("SearchLDAP(-, %d, %s, -) -> %s\n", edui_conf.scope, edui_ldap.search_filter, ErrLDAP(x));
1921  x = SearchIPLDAP(&edui_ldap);
1922  if (x == LDAP_ERR_NOTFOUND) {
1923  debug("SearchIPLDAP() -> %s\n", ErrLDAP(x));
1924  local_printfx("ERR message=\"(SearchIPLDAP: %s)\"\n", ErrLDAP(x));
1925  } else if (x == LDAP_ERR_SUCCESS) {
1926  debug("SearchIPLDAP(-, %s) -> %s\n", edui_ldap.userid, ErrLDAP(x));
1927  local_printfx("OK user=%s\n", edui_ldap.userid); /* Got a userid --> OK user=<userid> */
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));
1931  }
1932  }
1933  }
1934  /* Clear for next query */
1935  memset(bufc, '\0', sizeof(bufc));
1936  }
1937  }
1938 
1939  /* Clear buffer and close for next data, if not persistent */
1940  edui_ldap.err = -1;
1941  memset(bufa, '\0', sizeof(bufa));
1942  if (!(edui_ldap.status & LDAP_PERSIST_S)) {
1943  x = CloseLDAP(&edui_ldap);
1944  debug("CloseLDAP(-) -> %s\n", ErrLDAP(x));
1945  }
1946  }
1947 
1948  debug("Terminating.\n");
1949  return 1;
1950 }
1951 
1952 /* "main()" - function */
1953 int
1954 main(int argc, char **argv)
1955 {
1956  int x;
1957  x = MainSafe(argc, argv);
1958  return x;
1959 }
1960 
#define LDAP_SSL_S
#define LDAP_TLS_S
int main(int argc, char **argv)
char userid[EDUI_MAXLEN]
#define LDAP_ERR_OTHER
static int StringSplit(char *, char, char *, size_t)
#define LDAP_IDLE_S
#define EDUI_MODE_IPV4
static int BinarySplit(void *, size_t, char, void *, size_t)
#define LDAP_OPEN_S
char program[EDUI_MAXLEN]
const char * search_attrib[]
#define LDAP_AUTH_TLS
#define EDUI_MODE_INIT
void SigTrap(int)
static int BindLDAP(edui_ldap_t *, char *, char *, unsigned int)
#define LDAP_SEARCH_S
int debug_enabled
Definition: debug.cc:13
int i
Definition: membanger.c:49
static void InitLDAP(edui_ldap_t *)
time_t edui_now
#define LDAP_ERR_NULL
#define LDAP_PERSIST_S
static int ConvertIP(edui_ldap_t *, char *)
#define LDAP_VAL_S
char * p
Definition: membanger.c:43
char host[EDUI_MAXLEN]
#define LDAP_BIND_S
#define LDAP_IPV4_S
#define LDAP_ERR_NOTFOUND
#define EDUI_MODE_IPV6
static const char * basedn
static int CloseLDAP(edui_ldap_t *)
#define LDAP_ERR_PARAM
static void InitConf()
#define LDAP_ERR_NOT_SEARCHED
#define LDAP_ERR_OPEN
#define LDAP_ERR_INVALID
static void DisplayVersion()
#define EDUI_MODE_DEBUG
#define LDAP_INIT_S
#define EDUI_PROGRAM_VERSION
char search_filter[EDUI_MAXLEN]
#define LDAP_ERR_SUCCESS
char passwd[EDUI_MAXLEN]
char dn[EDUI_MAXLEN]
char attrib[EDUI_MAXLEN]
#define LDAP_ERR_CONNECT
#define EDUI_MODE_PERSIST
#define LDAP_ERR_SEARCHED
static int OpenLDAP(edui_ldap_t *, char *, unsigned int)
char search_filter[EDUI_MAXLEN]
#define EDUI_MODE_GROUP
static int debug
Definition: tcp-banger3.c:105
#define LDAP_ERR_POINTER
char * xstrncpy(char *dst, const char *src, size_t n)
Definition: xstring.cc:37
static int SearchLDAP(edui_ldap_t *, int, char *, char **)
char host[EDUI_MAXLEN]
static int SearchFilterLDAP(edui_ldap_t *, char *)
static int ResetLDAP(edui_ldap_t *)
static edui_conf_t edui_conf
struct berval ** val
static int SearchIPLDAP(edui_ldap_t *)
#define LDAP_ERR_FAILED
#define EDUI_PROGRAM_NAME
#define EDUI_MODE_KILL
#define EDUI_MAXLEN
bool SIGHDLR int STUB void int
Definition: stub_tools.cc:68
char basedn[EDUI_MAXLEN]
char search_ip[EDUI_MAXLEN]
static int MainSafe(int argc, char **argv)
#define EDUI_MODE_TLS
#define LDAP_ERR_DATA
#define LDAP_ERR_OOB
const char * ErrLDAP(int)
static edui_ldap_t edui_ldap
char basedn[EDUI_MAXLEN]
int const char size_t
Definition: stub_liblog.cc:84
char dn[EDUI_MAXLEN]
char passwd[EDUI_MAXLEN]
static void DisplayConf()
static void local_printfx(const char *,...)
#define LDAP_IPV6_S
#define LDAP_ERR_PERSIST
static void DisplayUsage()
static int SetVerLDAP(edui_ldap_t *, int)
time_t edui_elap
#define LDAP_ERR_INIT
#define NULL
Definition: types.h:166
#define LDAP_ERR_BIND

 

Introduction

Documentation

Support

Miscellaneous

Web Site Translations

Mirrors