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

 

Introduction

Documentation

Support

Miscellaneous