98#define LDAP_DEPRECATED 1
106#if _SQUID_WINDOWS_ && !_SQUID_CYGWIN_
107#define snprintf _snprintf
111#define LDAPAPI __cdecl
114#ifndef LDAP_OPT_X_TLS
115#define LDAP_OPT_X_TLS 0x6000
120#undef ldap_start_tls_s
122#define LDAP_START_TLS_S "ldap_start_tls_sW"
123typedef WINLDAPAPI
ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlW *, IN PLDAPControlW *);
125#define LDAP_START_TLS_S "ldap_start_tls_sA"
126typedef WINLDAPAPI
ULONG(LDAPAPI * PFldap_start_tls_s) (IN PLDAP, OUT PULONG, OUT LDAPMessage **, IN PLDAPControlA *, IN PLDAPControlA *);
128PFldap_start_tls_s Win32_ldap_start_tls_s;
129#define ldap_start_tls_s(l,s,c) Win32_ldap_start_tls_s(l, nullptr, nullptr,s,c)
137#ifndef LDAP_SECURITY_ERROR
138#define LDAP_SECURITY_ERROR(err) (0x2f <= (err) && (err) <= 0x32)
143#define PROGRAM_NAME "basic_ldap_auth"
157#if defined(NETSCAPE_SSL)
158static const char *sslpath =
nullptr;
159static int sslinit = 0;
168static int checkLDAP(LDAP *
ld,
const char *userid,
const char *password,
const char *
server,
int port);
174#define LDAP_NO_ATTRS "1.1"
177#if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823
182 ldap_get_option(
ld, LDAP_OPT_ERROR_NUMBER, &err);
188 ldap_set_option(
ld, LDAP_OPT_DEREF, &deref);
193 int *value =
static_cast<int*
>(referrals ? LDAP_OPT_ON :LDAP_OPT_OFF);
194 ldap_set_option(
ld, LDAP_OPT_REFERRALS, value);
199 ldap_set_option(
ld, LDAP_OPT_TIMELIMIT, &aTimeLimit);
204#if defined(LDAP_OPT_NETWORK_TIMEOUT)
206 tv.tv_sec = aTimeLimit;
208 ldap_set_option(
ld, LDAP_OPT_NETWORK_TIMEOUT, &tv);
209#elif defined(LDAP_X_OPT_CONNECT_TIMEOUT)
211 ldap_set_option(
ld, LDAP_X_OPT_CONNECT_TIMEOUT, &aTimeLimit);
229 ld->ld_deref = deref;
235 ld->ld_options |= ~LDAP_OPT_REFERRALS;
237 ld->ld_options &= ~LDAP_OPT_REFERRALS;
247 fprintf(stderr,
"Connect timeouts not supported in your LDAP library\n");
257#ifdef LDAP_API_FEATURE_X_OPENLDAP
258#if LDAP_VENDOR_VERSION > 194
259#define HAS_URI_SUPPORT 1
270 if (rc != LDAP_SUCCESS) {
271 fprintf(stderr,
"\nUnable to connect to LDAPURI:%s\n",
ldapServer);
278 if (!sslinit && (ldapssl_client_init(sslpath,
nullptr) != LDAP_SUCCESS)) {
279 fprintf(stderr,
"\nUnable to initialise SSL with cert path %s\n",
286 fprintf(stderr,
"\nUnable to connect to SSL LDAP server: %s port:%d\n",
293 fprintf(stderr,
"\nUnable to connect to LDAP server:%s port:%d\n",
304 if (ldap_set_option(
ld, LDAP_OPT_PROTOCOL_VERSION, &
version) != LDAP_SUCCESS) {
305 fprintf(stderr,
"Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
311 if (
version != LDAP_VERSION3) {
312 fprintf(stderr,
"TLS requires LDAP version 3\n");
314 }
else if (ldap_start_tls_s(
ld,
nullptr,
nullptr) != LDAP_SUCCESS) {
315 fprintf(stderr,
"Could not Activate TLS connection\n");
319 fprintf(stderr,
"TLS not supported with your LDAP library\n");
334 const unsigned char *p = (
const unsigned char *) user;
339 while (p[0] && p[1]) {
364 int port = LDAP_PORT;
366 setbuf(stdout,
nullptr);
368 while (argc > 1 && argv[1][0] ==
'-') {
369 const char *value =
"";
370 char option = argv[1][1];
380 if (strlen(argv[1]) > 2) {
382 }
else if (argc > 2) {
395 fprintf(stderr,
"ERROR: Your LDAP library does not have URI support\n");
401 int len = strlen(
ldapServer) + 1 + strlen(value) + 1;
402 char *newhost =
static_cast<char*
>(
xmalloc(len));
403 snprintf(newhost, len,
"%s %s",
ldapServer, value);
423 if (strcmp(value,
"base") == 0)
425 else if (strcmp(value,
"one") == 0)
427 else if (strcmp(value,
"sub") == 0)
430 fprintf(stderr,
PROGRAM_NAME ": ERROR: Unknown search scope '%s'\n", value);
435#if defined(NETSCAPE_SSL)
437 if (
port == LDAP_PORT)
440 fprintf(stderr,
PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n");
451 if (strcmp(value,
"never") == 0)
453 else if (strcmp(value,
"always") == 0)
455 else if (strcmp(value,
"search") == 0)
457 else if (strcmp(value,
"find") == 0)
460 fprintf(stderr,
PROGRAM_NAME ": ERROR: Unknown alias dereference method '%s'\n", value);
487 switch (atoi(value)) {
495 fprintf(stderr,
"Protocol version should be 2 or 3\n");
500 if (
version == LDAP_VERSION2) {
501 fprintf(stderr,
"TLS (-Z) is incompatible with version %d\n",
513 fprintf(stderr,
PROGRAM_NAME ": ERROR: Unknown command line option '%c'\n", option);
519 char *value = argv[1];
521 int len = strlen(
ldapServer) + 1 + strlen(value) + 1;
522 char *newhost =
static_cast<char*
>(
xmalloc(len));
523 snprintf(newhost, len,
"%s %s",
ldapServer, value);
536 fprintf(stderr,
"Usage: " PROGRAM_NAME " -b basedn [options] [ldap_server_name[:port]]...\n\n");
537 fprintf(stderr,
"\t-b basedn (REQUIRED)\tbase dn under which to search\n");
538 fprintf(stderr,
"\t-f filter\t\tsearch filter to locate user DN\n");
539 fprintf(stderr,
"\t-u userattr\t\tusername DN attribute\n");
540 fprintf(stderr,
"\t-s base|one|sub\t\tsearch scope\n");
541 fprintf(stderr,
"\t-D binddn\t\tDN to bind as to perform searches\n");
542 fprintf(stderr,
"\t-w bindpasswd\t\tpassword for binddn\n");
543 fprintf(stderr,
"\t-W secretfile\t\tread password for binddn from file secretfile\n");
545 fprintf(stderr,
"\t-H URI\t\t\tLDAPURI (defaults to ldap://localhost)\n");
547 fprintf(stderr,
"\t-h server\t\tLDAP server (defaults to localhost)\n");
548 fprintf(stderr,
"\t-p port\t\t\tLDAP server port\n");
549 fprintf(stderr,
"\t-P\t\t\tpersistent LDAP connection\n");
550#if defined(NETSCAPE_SSL)
551 fprintf(stderr,
"\t-E sslcertpath\t\tenable LDAP over SSL\n");
553 fprintf(stderr,
"\t-c timeout\t\tconnect timeout\n");
554 fprintf(stderr,
"\t-t timelimit\t\tsearch time limit\n");
555 fprintf(stderr,
"\t-R\t\t\tdo not follow referrals\n");
556 fprintf(stderr,
"\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n");
558 fprintf(stderr,
"\t-v 2|3\t\t\tLDAP version\n");
559 fprintf(stderr,
"\t-Z\t\t\tTLS encrypt the LDAP connection, requires LDAP version 3\n");
561 fprintf(stderr,
"\t-d\t\t\tenable debug mode\n");
562 fprintf(stderr,
"\n");
563 fprintf(stderr,
"\tIf no search filter is specified, then the dn <userattr>=user,basedn\n\twill be used (same as specifying a search filter of '<userattr>=',\n\tbut quicker as as there is no need to search for the user DN)\n\n");
564 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");
573 HMODULE WLDAP32Handle;
575 WLDAP32Handle = GetModuleHandle(
"wldap32");
576 if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) ==
NULL) {
577 fprintf(stderr,
PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n");
583 while (fgets(buf,
sizeof(buf), stdin) !=
nullptr) {
584 user = strtok(buf,
" \r\n");
585 passwd = strtok(
nullptr,
"\r\n");
591 if (!passwd || !passwd[0]) {
601 tryagain = (
ld !=
nullptr);
607 if (tryagain && e != LDAP_INVALID_CREDENTIALS) {
634 while (
size > 4 && *src) {
645 snprintf(escaped, 3,
"%02x", (
unsigned char) *src);
670 LDAP *bind_ld =
nullptr;
676 debug(
"Blank password given\n");
681 char escaped_login[1024];
682 LDAPMessage *res =
nullptr;
687 LDAP *search_ld = persistent_ld;
695 if (rc != LDAP_SUCCESS) {
696 fprintf(stderr,
PROGRAM_NAME ": WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc));
701 snprintf(filter,
sizeof(filter),
searchfilter, 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);
702 debug(
"user filter '%s', searchbase '%s'\n", filter,
basedn);
704 if (rc != LDAP_SUCCESS) {
709 debug(
"noreferrals && rc == LDAP_PARTIAL_RESULTS\n");
711 fprintf(stderr,
PROGRAM_NAME ": WARNING, LDAP search error '%s'\n", ldap_err2string(rc));
712#if defined(NETSCAPE_SSL)
713 if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) {
714 int sslerr = PORT_GetError();
715 fprintf(stderr,
PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr));
722 entry = ldap_first_entry(search_ld, res);
724 debug(
"Ldap search returned nothing\n");
728 userdn = ldap_get_dn(search_ld, entry);
730 fprintf(stderr,
PROGRAM_NAME ": ERROR, could not get user DN for '%s'\n", userid);
734 snprintf(dn,
sizeof(dn),
"%s", userdn);
747 if (search_ld && search_ld != persistent_ld) {
748 ldap_unbind(search_ld);
757 debug(
"attempting to authenticate user '%s'\n", dn);
759 bind_ld = persistent_ld;
763 if (ldap_compare_s(bind_ld, dn,
passwdattr, password) != LDAP_COMPARE_TRUE) {
766 }
else if (ldap_simple_bind_s(bind_ld, dn, password) != LDAP_SUCCESS)
768 if (bind_ld != persistent_ld) {
769 ldap_unbind(bind_ld);
781 char *passwd =
nullptr;
783 if (!(f = fopen(filename,
"r"))) {
784 fprintf(stderr,
PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename);
787 if (!fgets(buf,
sizeof(buf) - 1, f)) {
788 fprintf(stderr,
PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename);
793 if ((e = strrchr(buf,
'\n')))
795 if ((e = strrchr(buf,
'\r')))
798 passwd = (
char *) calloc(
sizeof(
char), strlen(buf) + 1);
800 fprintf(stderr,
PROGRAM_NAME " ERROR: can not allocate memory\n");
static int ldap_escape_value(char *escaped, int size, const char *src)
#define LDAP_SECURITY_ERROR(err)
static int checkLDAP(LDAP *ld, const char *userid, const char *password, const char *server, int port)
static int readSecret(const char *filename)
static LDAP * open_ldap_connection(const char *ldapServer, int port)
int main(int argc, char **argv)
static const char * bindpasswd
static const char * userattr
static void squid_ldap_set_connect_timeout(LDAP *ld, int timelimit)
static const char * binddn
static void squid_ldap_set_referrals(LDAP *ld, int referrals)
static int connect_timeout
static const char * passwdattr
static void squid_ldap_set_aliasderef(LDAP *ld, int deref)
static const char * searchfilter
static void squid_ldap_memfree(char *p)
static void squid_ldap_set_timelimit(LDAP *ld, int timelimit)
static const char * basedn
static int squid_ldap_errno(LDAP *ld)
static int validUsername(const char *user)
static char server[MAXLINE]
void debug(const char *format,...)
void rfc1738_unescape(char *url)