Index: squid/helpers/basic_auth/LDAP/squid_ldap_auth.8 diff -c squid/helpers/basic_auth/LDAP/squid_ldap_auth.8:1.7 squid/helpers/basic_auth/LDAP/squid_ldap_auth.8:1.7.2.1 *** squid/helpers/basic_auth/LDAP/squid_ldap_auth.8:1.7 Fri Oct 5 16:30:38 2001 --- squid/helpers/basic_auth/LDAP/squid_ldap_auth.8 Thu May 8 14:15:55 2003 *************** *** 1,4 **** ! .TH squid_ldap_auth 8 "25 September 2001" "Squid LDAP Auth" . .SH NAME squid_ldap_auth - Squid LDAP authentication helper --- 1,4 ---- ! .TH squid_ldap_auth 8 "1 Mars 2003" "Squid LDAP Auth" . .SH NAME squid_ldap_auth - Squid LDAP authentication helper *************** *** 68,73 **** --- 68,83 ---- Squid configuration file. . .TP + .BI "-D " "binddn " "-W " "secretfile " + The DN and the name of a file containing the password + to bind as while performing searches. + .IP + Less insecure version of the former parameter pair with two advantages: + The password does not occur in the process listing, + and the password is not being compromised if someone gets the squid + configuration file without getting the secretfile. + . + .TP .BI -P Use a persistent LDAP connection. Normally the LDAP connection is only open while validating a username to preserve resources *************** *** 93,104 **** --- 103,134 ---- the base object . .TP + .BI -H " ldapuri" + Specity the LDAP server to connect to by LDAP URI (requires OpenLDAP libraries) + . + .TP .BI -h " ldapserver" Specify the LDAP server to connect to .TP .BI -p " ldapport" Specify an alternate TCP port where the ldap server is listening if other than the default LDAP port 389. + . + .TP + .BI -Z + Use TLS encryption + . + .TP + .BI -S certpath + Enable LDAP over SSL (requires Netscape LDAP API libraries) + . + .TP + .BI -c connect_timeout + Specify timeout used when connecting to LDAP servers (requires + Netscape LDAP API libraries) + .TP + .BI -t search_timeout + Specify time limit on LDAP search operations . .SH EXAMPLES For directories using the RFC2307 layout with a single domain, all Index: squid/helpers/basic_auth/LDAP/squid_ldap_auth.c diff -c squid/helpers/basic_auth/LDAP/squid_ldap_auth.c:1.21.2.4 squid/helpers/basic_auth/LDAP/squid_ldap_auth.c:1.21.2.5 *** squid/helpers/basic_auth/LDAP/squid_ldap_auth.c:1.21.2.4 Mon May 5 18:37:31 2003 --- squid/helpers/basic_auth/LDAP/squid_ldap_auth.c Thu May 8 14:15:55 2003 *************** *** 1,20 **** /* * squid_ldap_auth: authentication via ldap for squid proxy server * ! * Maintainer: Henrik Nordstrom * ! * Author: Glen Newton * glen.newton@nrc.ca * Advanced Services * CISTI * National Research Council * * Usage: squid_ldap_auth -b basedn [-s searchscope] * [-f searchfilter] [-D binddn -w bindpasswd] * [-u attr] [-h host] [-p port] [-P] [-R] [ldap_server_name[:port]] ... * * Dependencies: You need to get the OpenLDAP libraries ! * from http://www.openldap.org * * License: squid_ldap_auth is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License --- 1,28 ---- /* * squid_ldap_auth: authentication via ldap for squid proxy server * ! * Authors: ! * Henrik Nordstrom ! * hno@squid-cache.org * ! * Glen Newton * glen.newton@nrc.ca * Advanced Services * CISTI * National Research Council + * + * with contributions from others mentioned in the Changes section below * * Usage: squid_ldap_auth -b basedn [-s searchscope] * [-f searchfilter] [-D binddn -w bindpasswd] * [-u attr] [-h host] [-p port] [-P] [-R] [ldap_server_name[:port]] ... * * Dependencies: You need to get the OpenLDAP libraries ! * from http://www.openldap.org or another compatible LDAP C-API ! * implementation. ! * ! * If you want to make a TLS enabled connection you will also need the ! * OpenSSL libraries linked into openldap. See http://www.openssl.org/ * * License: squid_ldap_auth is free software; you can redistribute it * and/or modify it under the terms of the GNU General Public License *************** *** 22,27 **** --- 30,47 ---- * or (at your option) any later version. * * Changes: + * 2003-03-01: David J N Begley + * - Support for Netscape API method of ldap over SSL + * connections + * - Timeout option for better recovery when using + * multiple LDAP servers + * 2003-03-01: Christoph Lechleitner + * - Added -W option to read bindpasswd from file + * 2003-03-01: Juerg Michel + * - Added support for ldap URI via the -H option + * (requires OpenLDAP) + * 2001-12-12: Michael Cunningham + * - Added TLS support and partial ldap version 3 support. * 2001-10-04: Henrik Nordstrom * - Be consistent with the other helpers in how * spaces are managed. If there is space characters *************** *** 55,61 **** #include "util.h" ! /* Change this to your search base */ static char *basedn; static char *searchfilter = NULL; static char *binddn = NULL; --- 75,83 ---- #include "util.h" ! #define PROGRAM_NAME "squid_ldap_auth" ! ! /* Global options */ static char *basedn; static char *searchfilter = NULL; static char *binddn = NULL; *************** *** 65,72 **** --- 87,105 ---- static int persistent = 0; static int noreferrals = 0; static int aliasderef = LDAP_DEREF_NEVER; + #if defined(NETSCAPE_SSL) + static char *sslpath = NULL; + static int sslinit = 0; + #endif + static int connect_timeout = 0; + static int timelimit = LDAP_NO_LIMIT; + + /* Added for TLS support and version 3 */ + static int use_tls = 0; + static int version = -1; static int checkLDAP(LDAP * ld, char *userid, char *password); + static int readSecret(char *filename); /* Yuck.. we need to glue to different versions of the API */ *************** *** 89,95 **** int *value = referrals ? LDAP_OPT_ON : LDAP_OPT_OFF; ldap_set_option(ld, LDAP_OPT_REFERRALS, value); } ! #else static int squid_ldap_errno(LDAP * ld) --- 122,150 ---- int *value = referrals ? LDAP_OPT_ON : LDAP_OPT_OFF; ldap_set_option(ld, LDAP_OPT_REFERRALS, value); } ! static void ! squid_ldap_set_timelimit(LDAP *ld, int timelimit) ! { ! ldap_set_option(ld, LDAP_OPT_TIMELIMIT, &timelimit); ! } ! static void ! squid_ldap_set_connect_timeout(LDAP *ld, int timelimit) ! { ! #if defined(LDAP_OPT_NETWORK_TIMEOUT) ! struct timeval tv; ! tv.tv_sec = timelimit; ! tv.tv_usec = 0; ! ldap_set_option(ld, LDAP_OPT_NETWORK_TIMEOUT, &tv); ! #elif defined(LDAP_X_OPT_CONNECT_TIMEOUT) ! timelimit *= 1000; ! ldap_set_option(ld, LDAP_X_OPT_CONNECT_TIMEOUT, &timelimit); ! #endif ! } ! static void ! squid_ldap_memfree(char *p) ! { ! ldap_memfree(p); ! } #else static int squid_ldap_errno(LDAP * ld) *************** *** 109,114 **** --- 164,189 ---- else ld->ld_options &= ~LDAP_OPT_REFERRALS; } + static void squid_ldap_set_timelimit(LDAP *ld, int timelimit) + { + ld->ld_timelimit = timelimit; + } + static void + squid_ldap_set_connect_timeout(LDAP *ld, int timelimit) + { + fprintf(stderr, "Connect timeouts not supported in your LDAP library\n"); + } + static void + squid_ldap_memfree(char *p) + { + free(p); + } + #endif + + #ifdef LDAP_API_FEATURE_X_OPENLDAP + #if LDAP_VENDOR_VERSION > 194 + #define HAS_URI_SUPPORT 1 + #endif #endif int *************** *** 129,134 **** --- 204,211 ---- switch (option) { case 'P': case 'R': + case 'z': + case 'Z': break; default: if (strlen(argv[1]) > 2) { *************** *** 144,149 **** --- 221,232 ---- argv++; argc--; switch (option) { + case 'H': + #if !HAS_URI_SUPPORT + fprintf(stderr, "ERROR: Your LDAP library does not have URI support\n"); + exit(1); + #endif + /* Fall thru to -h */ case 'h': if (ldapServer) { int len = strlen(ldapServer) + 1 + strlen(value) + 1; *************** *** 172,181 **** else if (strcmp(value, "sub") == 0) searchscope = LDAP_SCOPE_SUBTREE; else { ! fprintf(stderr, "squid_ldap_auth: ERROR: Unknown search scope '%s'\n", value); exit(1); } break; case 'a': if (strcmp(value, "never") == 0) aliasderef = LDAP_DEREF_NEVER; --- 255,280 ---- else if (strcmp(value, "sub") == 0) searchscope = LDAP_SCOPE_SUBTREE; else { ! fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown search scope '%s'\n", value); exit(1); } break; + case 'E': + #if defined(NETSCAPE_SSL) + sslpath = value; + if (port == LDAP_PORT) + port = LDAPS_PORT; + #else + fprintf(stderr, PROGRAM_NAME " ERROR: -E unsupported with this LDAP library\n"); + exit(1); + #endif + break; + case 'c': + connect_timeout = atoi(value); + break; + case 't': + timelimit = atoi(value); + break; case 'a': if (strcmp(value, "never") == 0) aliasderef = LDAP_DEREF_NEVER; *************** *** 186,192 **** else if (strcmp(value, "find") == 0) aliasderef = LDAP_DEREF_FINDING; else { ! fprintf(stderr, "squid_ldap_auth: ERROR: Unknown alias dereference method '%s'\n", value); exit(1); } break; --- 285,291 ---- else if (strcmp(value, "find") == 0) aliasderef = LDAP_DEREF_FINDING; else { ! fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown alias dereference method '%s'\n", value); exit(1); } break; *************** *** 196,201 **** --- 295,303 ---- case 'w': bindpasswd = value; break; + case 'W': + readSecret (value); + break; case 'P': persistent = !persistent; break; *************** *** 205,212 **** case 'R': noreferrals = !noreferrals; break; default: ! fprintf(stderr, "squid_ldap_auth: ERROR: Unknown command line option '%c'\n", option); exit(1); } } --- 307,338 ---- case 'R': noreferrals = !noreferrals; break; + #ifdef LDAP_VERSION3 + case 'v': + switch( atoi(value) ) { + case 2: + version = LDAP_VERSION2; + break; + case 3: + version = LDAP_VERSION3; + break; + default: + fprintf( stderr, "Protocol version should be 2 or 3\n"); + exit(1); + } + break; + case 'Z': + if ( version == LDAP_VERSION2 ) { + fprintf( stderr, "TLS (-Z) is incompatible with version %d\n", + version); + exit(1); + } + version = LDAP_VERSION3; + use_tls = 1; + break; + #endif default: ! fprintf(stderr, PROGRAM_NAME ": ERROR: Unknown command line option '%c'\n", option); exit(1); } } *************** *** 229,249 **** ldapServer = "localhost"; if (!basedn) { ! fprintf(stderr, "Usage: squid_ldap_auth -b basedn [options] [ldap_server_name[:port]]...\n\n"); fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under which to search\n"); fprintf(stderr, "\t-f filter\t\tsearch filter to locate user DN\n"); fprintf(stderr, "\t-u userattr\t\tusername DN attribute\n"); fprintf(stderr, "\t-s base|one|sub\t\tsearch scope\n"); fprintf(stderr, "\t-D binddn\t\tDN to bind as to perform searches\n"); fprintf(stderr, "\t-w bindpasswd\t\tpassword for binddn\n"); fprintf(stderr, "\t-h server\t\tLDAP server (defaults to localhost)\n"); fprintf(stderr, "\t-p port\t\t\tLDAP server port\n"); fprintf(stderr, "\t-P\t\t\tpersistent LDAP connection\n"); fprintf(stderr, "\t-R\t\t\tdo not follow referrals\n"); fprintf(stderr, "\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n"); fprintf(stderr, "\n"); fprintf(stderr, "\tIf no search filter is specified, then the dn =user,basedn\n\twill be used (same as specifying a search filter of '=',\n\tbut quicker as as there is no need to search for the user DN)\n\n"); ! fprintf(stderr, "\tIf you need to bind as a user to perform searches then use the\n\t-D binddn -w bindpasswd options\n\n"); exit(1); } while (fgets(buf, 256, stdin) != NULL) { --- 355,388 ---- ldapServer = "localhost"; if (!basedn) { ! fprintf(stderr, "Usage: " PROGRAM_NAME " -b basedn [options] [ldap_server_name[:port]]...\n\n"); fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under which to search\n"); fprintf(stderr, "\t-f filter\t\tsearch filter to locate user DN\n"); fprintf(stderr, "\t-u userattr\t\tusername DN attribute\n"); fprintf(stderr, "\t-s base|one|sub\t\tsearch scope\n"); fprintf(stderr, "\t-D binddn\t\tDN to bind as to perform searches\n"); fprintf(stderr, "\t-w bindpasswd\t\tpassword for binddn\n"); + fprintf(stderr, "\t-W secretfile\t\tread password for binddn from file secretfile\n"); + #if HAS_URI_SUPPORT + fprintf(stderr, "\t-H URI\t\t\tLDAPURI (defaults to ldap://localhost)\n"); + #endif fprintf(stderr, "\t-h server\t\tLDAP server (defaults to localhost)\n"); fprintf(stderr, "\t-p port\t\t\tLDAP server port\n"); fprintf(stderr, "\t-P\t\t\tpersistent LDAP connection\n"); + #if defined(NETSCAPE_SSL) + fprintf(stderr, "\t-E sslcertpath\t\tenable LDAP over SSL\n"); + #endif + fprintf(stderr, "\t-c timeout\t\tconnect timeout\n"); + fprintf(stderr, "\t-t timelimit\t\tsearch time limit\n"); fprintf(stderr, "\t-R\t\t\tdo not follow referrals\n"); fprintf(stderr, "\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n"); + #ifdef LDAP_VERSION3 + fprintf(stderr, "\t-v 2|3\t\t\tLDAP version\n"); + fprintf(stderr, "\t-Z\t\t\tTLS encrypt the LDAP connection, requires LDAP version 3\n"); + #endif fprintf(stderr, "\n"); fprintf(stderr, "\tIf no search filter is specified, then the dn =user,basedn\n\twill be used (same as specifying a search filter of '=',\n\tbut quicker as as there is no need to search for the user DN)\n\n"); ! 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"); exit(1); } while (fgets(buf, 256, stdin) != NULL) { *************** *** 259,269 **** --- 398,456 ---- tryagain = 1; recover: if (ld == NULL) { + #if HAS_URI_SUPPORT + if (strstr(ldapServer, "://") != NULL) { + int rc = ldap_initialize( &ld, ldapServer ); + if( rc != LDAP_SUCCESS ) { + fprintf(stderr, "\nUnable to connect to LDAPURI:%s\n", ldapServer); + break; + } + } else + #endif + #if NETSCAPE_SSL + if (sslpath) { + if ( !sslinit && (ldapssl_client_init(sslpath, NULL) != LDAP_SUCCESS)) { + fprintf(stderr, "\nUnable to initialise SSL with cert path %s\n", + sslpath); + exit(1); + } else { + sslinit++; + } + if ((ld = ldapssl_init(ldapServer, port, 1)) == NULL) { + fprintf(stderr, "\nUnable to connect to SSL LDAP server: %s port:%d\n", + ldapServer, port); + exit(1); + } + } else + #endif if ((ld = ldap_init(ldapServer, port)) == NULL) { fprintf(stderr, "\nUnable to connect to LDAP server:%s port:%d\n", ldapServer, port); exit(1); } + + if (connect_timeout) + squid_ldap_set_connect_timeout(ld, connect_timeout); + + #ifdef LDAP_VERSION3 + if (version == -1 ) { + version = LDAP_VERSION2; + } + + if( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &version ) + != LDAP_OPT_SUCCESS ) + { + fprintf( stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n", + version ); + exit(1); + } + + if ( use_tls && ( version == LDAP_VERSION3 ) && ( ldap_start_tls_s( ld, NULL, NULL ) == LDAP_SUCCESS )) { + fprintf( stderr, "Could not Activate TLS connection\n"); + exit(1); + } + #endif + squid_ldap_set_timelimit(ld, timelimit); squid_ldap_set_referrals(ld, !noreferrals); squid_ldap_set_aliasderef(ld, aliasderef); } *************** *** 311,317 **** if (binddn) { rc = ldap_simple_bind_s(ld, binddn, bindpasswd); if (rc != LDAP_SUCCESS) { ! fprintf(stderr, "squid_ldap_auth: WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc)); return 1; } } --- 498,504 ---- if (binddn) { rc = ldap_simple_bind_s(ld, binddn, bindpasswd); if (rc != LDAP_SUCCESS) { ! fprintf(stderr, PROGRAM_NAME ": WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc)); return 1; } } *************** *** 323,329 **** * are disabled. */ } else { ! fprintf(stderr, "squid_ldap_auth: WARNING, LDAP search error '%s'\n", ldap_err2string(rc)); ldap_msgfree(res); return 1; } --- 510,522 ---- * are disabled. */ } else { ! fprintf(stderr, PROGRAM_NAME ": WARNING, LDAP search error '%s'\n", ldap_err2string(rc)); ! #if defined(NETSCAPE_SSL) ! if (sslpath && ((rc == LDAP_SERVER_DOWN) || (rc == LDAP_CONNECT_ERROR))) { ! int sslerr = PORT_GetError(); ! fprintf(stderr, PROGRAM_NAME ": WARNING, SSL error %d (%s)\n", sslerr, ldapssl_err2string(sslerr)); ! } ! #endif ldap_msgfree(res); return 1; } *************** *** 335,346 **** } userdn = ldap_get_dn(ld, entry); if (!userdn) { ! fprintf(stderr, "squid_ldap_auth: ERROR, could not get user DN for '%s'\n", userid); ldap_msgfree(res); return 1; } snprintf(dn, sizeof(dn), "%s", userdn); ! free(userdn); ldap_msgfree(res); } else { snprintf(dn, sizeof(dn), "%s=%s,%s", userattr, userid, basedn); --- 528,539 ---- } userdn = ldap_get_dn(ld, entry); if (!userdn) { ! fprintf(stderr, PROGRAM_NAME ": ERROR, could not get user DN for '%s'\n", userid); ldap_msgfree(res); return 1; } snprintf(dn, sizeof(dn), "%s", userdn); ! squid_ldap_memfree(userdn); ldap_msgfree(res); } else { snprintf(dn, sizeof(dn), "%s=%s,%s", userattr, userid, basedn); *************** *** 350,353 **** --- 543,579 ---- return 1; return 0; + } + + int readSecret(char *filename) + { + char buf[BUFSIZ]; + char *e=0; + FILE *f; + + if(!(f=fopen(filename, "r"))) { + fprintf(stderr, PROGRAM_NAME " ERROR: Can not read secret file %s\n", filename); + return 1; + } + + if( !fgets(buf, sizeof(buf)-1, f)) { + fprintf(stderr, PROGRAM_NAME " ERROR: Secret file %s is empty\n", filename); + fclose(f); + return 1; + } + + /* strip whitespaces on end */ + if((e = strrchr(buf, '\n'))) *e = 0; + if((e = strrchr(buf, '\r'))) *e = 0; + + bindpasswd = (char *) calloc(sizeof(char), strlen(buf)+1); + if (bindpasswd) { + strcpy(bindpasswd, buf); + } else { + fprintf(stderr, PROGRAM_NAME " ERROR: can not allocate memory\n"); + } + + fclose(f); + + return 0; }