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