16#define LDAP_DEPRECATED 1
20#if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
25#define LDAPAPI __cdecl
29#define LDAP_OPT_X_TLS 0x6000
34#undef ldap_start_tls_s
36#define LDAP_START_TLS_S "ldap_start_tls_sW"
37typedef WINLDAPAPI
ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlW *, IN PLDAPControlW *);
39#define LDAP_START_TLS_S "ldap_start_tls_sA"
40typedef WINLDAPAPI
ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlA *, IN PLDAPControlA *);
42PFldap_start_tls_s Win32_ldap_start_tls_s;
43#define ldap_start_tls_s(l,s,c) Win32_ldap_start_tls_s(l, nullptr, nullptr,s,c)
53#define PROGRAM_NAME "digest_pw_auth(LDAP_backend)"
57static LDAP *
ld =
nullptr;
70static int port = LDAP_PORT;
74#if defined(NETSCAPE_SSL)
75static char *sslpath =
nullptr;
76static int sslinit = 0;
92#if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823
96 ldap_set_option(
ld, LDAP_OPT_DEREF, &deref);
101 int *value =
static_cast<int*
>(referrals ? LDAP_OPT_ON :LDAP_OPT_OFF);
102 ldap_set_option(
ld, LDAP_OPT_REFERRALS, value);
107 ldap_set_option(
ld, LDAP_OPT_TIMELIMIT, &aTimeLimit);
112#if defined(LDAP_OPT_NETWORK_TIMEOUT)
114 tv.tv_sec = aTimeLimit;
116 ldap_set_option(
ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
117#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
119 ldap_set_option(
ld, LDAP_X_OPT_CONNECT_TIMEOUT, &aTimeLimit);
132 ld->ld_deref = deref;
138 ld->ld_options |= ~LDAP_OPT_REFERRALS;
140 ld->ld_options &= ~LDAP_OPT_REFERRALS;
145 ld->ld_timelimit = aTimeLimit;
150 fprintf(stderr,
"ERROR: Connect timeouts not supported in your LDAP library\n");
160#ifdef LDAP_API_FEATURE_X_OPENLDAP
161#if LDAP_VENDOR_VERSION > 194
162#define HAS_URI_SUPPORT 1
170 while (
size > 4 && *src) {
181 std::snprintf(escaped, 3,
"%02x", (
int) *src);
201 LDAPMessage *res =
nullptr;
203 char **values =
nullptr;
204 char **value =
nullptr;
205 char *password =
nullptr;
209 char searchbase[8192];
211 char *universal_password =
nullptr;
212 size_t universal_password_len = 256;
217 char escaped_login[1024];
218 std::snprintf(searchbase,
sizeof(searchbase),
"%s",
userbasedn);
220 std::snprintf(filter,
sizeof(filter),
usersearchfilter, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login, escaped_login);
223 debug(
"user filter '%s', searchbase '%s'\n", filter, searchbase);
225 rc = ldap_search_s(
ld, searchbase,
searchscope, filter,
nullptr, 0, &res);
226 if (rc != LDAP_SUCCESS) {
233 fprintf(stderr,
PROGRAM_NAME " WARNING, LDAP search error '%s'\n", ldap_err2string(rc));
234#if defined(NETSCAPE_SSL)
235 if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) {
236 int sslerr = PORT_GetError();
237 fprintf(stderr,
PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr));
240 fprintf(stderr,
PROGRAM_NAME " WARNING, LDAP search error, trying to recover'%s'\n", ldap_err2string(rc));
258 debug(
"searchbase '%s'\n", searchbase);
259 rc = ldap_search_s(
ld, searchbase,
searchscope,
nullptr,
nullptr, 0, &res);
261 if (rc == LDAP_SUCCESS) {
262 entry = ldap_first_entry(
ld, res);
264 debug(
"ldap dn: %s\n", ldap_get_dn(
ld, entry));
268 universal_password = (
char*)calloc(1, universal_password_len);
269 values = (
char**)calloc(1,
sizeof(
char *));
272 nmas_res =
nds_get_password(
ld, ldap_get_dn(
ld, entry), &universal_password_len, universal_password);
273 if (nmas_res == LDAP_SUCCESS && universal_password) {
274 debug(
"NMAS returned value %s\n", universal_password);
275 values[0] = universal_password;
277 debug(
"Error reading Universal Password: %d = %s\n", nmas_res, ldap_err2string(nmas_res));
280 values = ldap_get_values(
ld, entry,
passattr);
287 debug(
"No attribute value found\n");
289 free(universal_password);
296 const char *t = strtok(*value,
delimiter);
297 if (t && strcmp(t, realm) == 0) {
307 debug(
"password: %s\n", password);
312 free(universal_password);
314 ldap_value_free(values);
319 fprintf(stderr,
PROGRAM_NAME " WARNING, LDAP error '%s'\n", ldap_err2string(rc));
345 HMODULE WLDAP32Handle;
347 WLDAP32Handle = GetModuleHandle(
"wldap32");
348 if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) ==
NULL) {
349 fprintf(stderr,
PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n");
359 if (rc != LDAP_SUCCESS) {
360 fprintf(stderr,
"\nUnable to connect to LDAPURI:%s\n",
ldapServer);
366 if (!sslinit && (ldapssl_client_init(sslpath,
nullptr) != LDAP_SUCCESS)) {
367 fprintf(stderr,
"\nUnable to initialise SSL with cert path %s\n",
374 fprintf(stderr,
"\nUnable to connect to SSL LDAP server: %s port:%d\n",
381 fprintf(stderr,
"\nUnable to connect to LDAP server:%s port:%d\n",
ldapServer,
port);
390 if (ldap_set_option(
ld, LDAP_OPT_PROTOCOL_VERSION, &
version)
392 fprintf(stderr,
"Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
399 if ((
version == LDAP_VERSION3) && (ldap_start_tls_s(
ld,
nullptr,
nullptr) == LDAP_SUCCESS)) {
400 fprintf(stderr,
"Could not Activate TLS connection\n");
405 fprintf(stderr,
"TLS not supported with your LDAP library\n");
416 if (rc != LDAP_SUCCESS) {
417 fprintf(stderr,
PROGRAM_NAME " WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc));
422 debug(
"Connected OK\n");
428 setbuf(stdout,
nullptr);
430 while (argc > 1 && argv[1][0] ==
'-') {
431 const char *value =
"";
432 char option = argv[1][1];
445 if (strlen(argv[1]) > 2) {
447 }
else if (argc > 2) {
460 fprintf(stderr,
"ERROR: Your LDAP library does not have URI support\n");
466 int len = strlen(
ldapServer) + 1 + strlen(value) + 1;
467 char *newhost =
static_cast<char*
>(
xmalloc(len));
468 std::snprintf(newhost, len,
"%s %s",
ldapServer, value);
494 if (strcmp(value,
"base") == 0)
496 else if (strcmp(value,
"one") == 0)
498 else if (strcmp(value,
"sub") == 0)
501 fprintf(stderr,
PROGRAM_NAME " ERROR: Unknown search scope '%s'\n", value);
506#if defined(NETSCAPE_SSL)
508 if (
port == LDAP_PORT)
511 fprintf(stderr,
PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n");
522 if (strcmp(value,
"never") == 0)
524 else if (strcmp(value,
"always") == 0)
526 else if (strcmp(value,
"search") == 0)
528 else if (strcmp(value,
"find") == 0)
531 fprintf(stderr,
PROGRAM_NAME " ERROR: Unknown alias dereference method '%s'\n", value);
555 switch (atoi(value)) {
563 fprintf(stderr,
"Protocol version should be 2 or 3\n");
568 if (
version == LDAP_VERSION2) {
569 fprintf(stderr,
"TLS (-Z) is incompatible with version %d\n",
587 fprintf(stderr,
PROGRAM_NAME " ERROR: Unknown command line option '%c'\n", option);
593 char *value = argv[1];
595 int len = strlen(
ldapServer) + 1 + strlen(value) + 1;
596 char *newhost =
static_cast<char*
>(
xmalloc(len));
597 std::snprintf(newhost, len,
"%s %s",
ldapServer, value);
611 fprintf(stderr,
"Usage: " PROGRAM_NAME " -b basedn -f filter [options] ldap_server_name\n\n");
612 fprintf(stderr,
"\t-A password attribute(REQUIRED)\t\tUser attribute that contains the password\n");
613 fprintf(stderr,
"\t-l password realm delimiter(REQUIRED)\tCharater(s) that divides the password attribute\n\t\t\t\t\t\tin realm and password tokens, default ':' realm:password\n");
614 fprintf(stderr,
"\t-b basedn (REQUIRED)\t\t\tbase dn under where to search for users\n");
615 fprintf(stderr,
"\t-e Encrypted passwords(REQUIRED)\tPassword are stored encrypted using HHA1\n");
616 fprintf(stderr,
"\t-F filter\t\t\t\tuser search filter pattern. %%s = login\n");
617 fprintf(stderr,
"\t-u attribute\t\t\t\tattribute to use in combination with the basedn to create the user DN\n");
618 fprintf(stderr,
"\t-s base|one|sub\t\t\t\tsearch scope\n");
619 fprintf(stderr,
"\t-D binddn\t\t\t\tDN to bind as to perform searches\n");
620 fprintf(stderr,
"\t-w bindpasswd\t\t\t\tpassword for binddn\n");
621 fprintf(stderr,
"\t-W secretfile\t\t\t\tread password for binddn from file secretfile\n");
623 fprintf(stderr,
"\t-H URI\t\t\t\t\tLDAPURI (defaults to ldap://localhost)\n");
625 fprintf(stderr,
"\t-h server\t\t\t\tLDAP server (defaults to localhost)\n");
626 fprintf(stderr,
"\t-p port\t\t\t\t\tLDAP server port (defaults to %d)\n", LDAP_PORT);
627 fprintf(stderr,
"\t-P\t\t\t\t\tpersistent LDAP connection\n");
628#if defined(NETSCAPE_SSL)
629 fprintf(stderr,
"\t-E sslcertpath\t\t\t\tenable LDAP over SSL\n");
631 fprintf(stderr,
"\t-c timeout\t\t\t\tconnect timeout\n");
632 fprintf(stderr,
"\t-t timelimit\t\t\t\tsearch time limit\n");
633 fprintf(stderr,
"\t-R\t\t\t\t\tdo not follow referrals\n");
634 fprintf(stderr,
"\t-a never|always|search|find\t\twhen to dereference aliases\n");
636 fprintf(stderr,
"\t-v 2|3\t\t\t\t\tLDAP version\n");
637 fprintf(stderr,
"\t-Z\t\t\t\t\tTLS encrypt the LDAP connection, requires\n\t\t\t\tLDAP version 3\n");
639 fprintf(stderr,
"\t-S\t\t\t\t\tStrip NT domain from usernames\n");
640 fprintf(stderr,
"\t-n\t\t\t\t\tGet an eDirectory Universal Password from Novell NMAS\n\t\t\t\t\t\t(requires bind credentials, version 3, TLS, and a search filter)\n");
641 fprintf(stderr,
"\n");
642 fprintf(stderr,
"\tIf you need to bind as a user to perform searches then use the\n\t-D binddn -w bindpasswd or -D binddn -W secretfile options\n\n");
654 if (!(f = fopen(filename,
"r"))) {
655 fprintf(stderr,
PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename);
658 if (!fgets(buf,
sizeof(buf) - 1, f)) {
659 fprintf(stderr,
PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename);
664 if ((e = strrchr(buf,
'\n')))
666 if ((e = strrchr(buf,
'\r')))
671 fprintf(stderr,
PROGRAM_NAME " ERROR: can not allocate memory\n");
684 if (password !=
nullptr) {
693 requestData->
error = -1;
void debug(const char *format,...)
static void squid_ldap_set_referrals(int referrals)
static const char * passattr
static int ldap_escape_value(char *escaped, int size, const char *src)
int LDAPArguments(int argc, char **argv)
static int edir_universal_passwd
static const char * bindpasswd
static const char * userbasedn
static const char * usersearchfilter
static const char * delimiter
static const char * binddn
static void squid_ldap_set_timelimit(int aTimeLimit)
void LDAPHHA1(RequestData *requestData)
static void squid_ldap_set_connect_timeout(int aTimeLimit)
static int connect_timeout
static void ldapconnect(void)
static int strip_nt_domain
static const char * userdnattr
static char * getpassword(char *login, char *realm)
static void squid_ldap_set_aliasderef(int deref)
static void squid_ldap_memfree(char *p)
static int readSecret(const char *filename)
static int squid_ldap_errno(LDAP *ld)
int nds_get_password(LDAP *ld, char *object_dn, size_t *pwd_len, char *pwd)
void DigestCalcHA1(const char *pszAlg, const char *pszUserName, const char *pszRealm, const char *pszPassword, const char *pszNonce, const char *pszCNonce, HASH HA1, HASHHEX SessionKey)
char * xstrncpy(char *dst, const char *src, size_t n)