Exemplo n.º 1
0
/**
 * APR LDAP initialise function
 *
 * This function is responsible for initialising an LDAP
 * connection in a toolkit independant way. It does the
 * job of ldap_init() from the C api.
 *
 * It handles both the SSL and non-SSL case, and attempts
 * to hide the complexity setup from the user. This function
 * assumes that any certificate setup necessary has already
 * been done.
 *
 * If SSL or STARTTLS needs to be enabled, and the underlying
 * toolkit supports it, the following values are accepted for
 * secure:
 *
 * APR_LDAP_NONE: No encryption
 * APR_LDAP_SSL: SSL encryption (ldaps://)
 * APR_LDAP_STARTTLS: Force STARTTLS on ldap://
 */
APU_DECLARE_LDAP(int) apr_ldap_init(apr_pool_t *pool,
                                    LDAP **ldap,
                                    const char *hostname,
                                    int portno,
                                    int secure,
                                    apr_ldap_err_t **result_err)
{

    apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
    *result_err = result;

#if APR_HAS_LDAPSSL_INIT
#if APR_HAS_SOLARIS_LDAPSDK
    /*
     * Using the secure argument should aways be possible.  But as LDAP SDKs
     * tend to have different quirks and bugs, this needs to be tested for
     * for each of them, first. For Solaris LDAP it works, and the method
     * with ldap_set_option doesn't.
     */
    *ldap = ldapssl_init(hostname, portno, secure == APR_LDAP_SSL);
#else
    *ldap = ldapssl_init(hostname, portno, 0);
#endif
#elif APR_HAS_LDAP_SSLINIT
    *ldap = ldap_sslinit((char *)hostname, portno, 0);
#else
    *ldap = ldap_init((char *)hostname, portno);
#endif

    if (*ldap != NULL) {
#if APR_HAS_SOLARIS_LDAPSDK
        if (secure == APR_LDAP_SSL)
            return APR_SUCCESS;
        else
#endif
        return apr_ldap_set_option(pool, *ldap, APR_LDAP_OPT_TLS, &secure, result_err);
    }
    else {
        /* handle the error case */
        apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
        *result_err = result;

        result->reason = "APR LDAP: Unable to initialize the LDAP connection";
        result->rc = -1;
        return APR_EGENERAL;
    }

}
Exemplo n.º 2
0
/**
 * APR LDAP initialise function
 *
 * This function is responsible for initialising an LDAP
 * connection in a toolkit independant way. It does the
 * job of ldap_init() from the C api.
 *
 * It handles both the SSL and non-SSL case, and attempts
 * to hide the complexity setup from the user. This function
 * assumes that any certificate setup necessary has already
 * been done.
 *
 * If SSL or STARTTLS needs to be enabled, and the underlying
 * toolkit supports it, the following values are accepted for
 * secure:
 *
 * APR_LDAP_NONE: No encryption
 * APR_LDAP_SSL: SSL encryption (ldaps://)
 * APR_LDAP_STARTTLS: Force STARTTLS on ldap://
 */
APU_DECLARE_LDAP(int) apr_ldap_init(apr_pool_t *pool,
                                    LDAP **ldap,
                                    const char *hostname,
                                    int portno,
                                    int secure,
                                    apr_ldap_err_t **result_err)
{

    apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
    *result_err = result;

#if APR_HAS_LDAPSSL_INIT
    *ldap = ldapssl_init(hostname, portno, 0);
#elif APR_HAS_LDAP_SSLINIT
    *ldap = ldap_sslinit((char *)hostname, portno, 0);
#else
    *ldap = ldap_init((char *)hostname, portno);
#endif
    if (*ldap != NULL) {
        return apr_ldap_set_option(pool, *ldap, APR_LDAP_OPT_TLS, &secure, result_err);
    }
    else {
        /* handle the error case */
        apr_ldap_err_t *result = (apr_ldap_err_t *)apr_pcalloc(pool, sizeof(apr_ldap_err_t));
        *result_err = result;

        result->reason = "APR LDAP: Unable to initialize the LDAP connection";
        result->rc = -1;
        return APR_EGENERAL;
    }

}
Exemplo n.º 3
0
static CURLcode Curl_ldap(struct connectdata *conn, bool *done)
{
  CURLcode result = CURLE_OK;
  int rc = 0;
  LDAP *server = NULL;
  LDAPURLDesc *ludp = NULL;
  LDAPMessage *ldapmsg = NULL;
  LDAPMessage *entryIterator;
  int num = 0;
  struct SessionHandle *data=conn->data;
  int ldap_proto = LDAP_VERSION3;
  int ldap_ssl = 0;
  char *val_b64 = NULL;
  size_t val_b64_sz = 0;
  curl_off_t dlsize = 0;
#ifdef LDAP_OPT_NETWORK_TIMEOUT
  struct timeval ldap_timeout = {10,0}; /* 10 sec connection/search timeout */
#endif

  *done = TRUE; /* unconditionally */
  infof(data, "LDAP local: LDAP Vendor = %s ; LDAP Version = %d\n",
          LDAP_VENDOR_NAME, LDAP_VENDOR_VERSION);
  infof(data, "LDAP local: %s\n", data->change.url);

#ifdef HAVE_LDAP_URL_PARSE
  rc = ldap_url_parse(data->change.url, &ludp);
#else
  rc = _ldap_url_parse(conn, &ludp);
#endif
  if(rc != 0) {
    failf(data, "LDAP local: %s", ldap_err2string(rc));
    result = CURLE_LDAP_INVALID_URL;
    goto quit;
  }

  /* Get the URL scheme ( either ldap or ldaps ) */
  if(conn->given->flags & PROTOPT_SSL)
    ldap_ssl = 1;
  infof(data, "LDAP local: trying to establish %s connection\n",
          ldap_ssl ? "encrypted" : "cleartext");

#ifdef LDAP_OPT_NETWORK_TIMEOUT
  ldap_set_option(NULL, LDAP_OPT_NETWORK_TIMEOUT, &ldap_timeout);
#endif
  ldap_set_option(NULL, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);

  if(ldap_ssl) {
#ifdef HAVE_LDAP_SSL
#ifdef CURL_LDAP_WIN
    /* Win32 LDAP SDK doesn't support insecure mode without CA! */
    server = ldap_sslinit(conn->host.name, (int)conn->port, 1);
    ldap_set_option(server, LDAP_OPT_SSL, LDAP_OPT_ON);
#else
    int ldap_option;
    char* ldap_ca = data->set.str[STRING_SSL_CAFILE];
#if defined(CURL_HAS_NOVELL_LDAPSDK)
    rc = ldapssl_client_init(NULL, NULL);
    if(rc != LDAP_SUCCESS) {
      failf(data, "LDAP local: ldapssl_client_init %s", ldap_err2string(rc));
      result = CURLE_SSL_CERTPROBLEM;
      goto quit;
    }
    if(data->set.ssl.verifypeer) {
      /* Novell SDK supports DER or BASE64 files. */
      int cert_type = LDAPSSL_CERT_FILETYPE_B64;
      if((data->set.str[STRING_CERT_TYPE]) &&
         (Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "DER")))
        cert_type = LDAPSSL_CERT_FILETYPE_DER;
      if(!ldap_ca) {
        failf(data, "LDAP local: ERROR %s CA cert not set!",
              (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"));
        result = CURLE_SSL_CERTPROBLEM;
        goto quit;
      }
      infof(data, "LDAP local: using %s CA cert '%s'\n",
              (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
              ldap_ca);
      rc = ldapssl_add_trusted_cert(ldap_ca, cert_type);
      if(rc != LDAP_SUCCESS) {
        failf(data, "LDAP local: ERROR setting %s CA cert: %s",
                (cert_type == LDAPSSL_CERT_FILETYPE_DER ? "DER" : "PEM"),
                ldap_err2string(rc));
        result = CURLE_SSL_CERTPROBLEM;
        goto quit;
      }
      ldap_option = LDAPSSL_VERIFY_SERVER;
    }
    else
      ldap_option = LDAPSSL_VERIFY_NONE;
    rc = ldapssl_set_verify_mode(ldap_option);
    if(rc != LDAP_SUCCESS) {
      failf(data, "LDAP local: ERROR setting cert verify mode: %s",
              ldap_err2string(rc));
      result = CURLE_SSL_CERTPROBLEM;
      goto quit;
    }
    server = ldapssl_init(conn->host.name, (int)conn->port, 1);
    if(server == NULL) {
      failf(data, "LDAP local: Cannot connect to %s:%ld",
              conn->host.name, conn->port);
      result = CURLE_COULDNT_CONNECT;
      goto quit;
    }
#elif defined(LDAP_OPT_X_TLS)
    if(data->set.ssl.verifypeer) {
      /* OpenLDAP SDK supports BASE64 files. */
      if((data->set.str[STRING_CERT_TYPE]) &&
         (!Curl_raw_equal(data->set.str[STRING_CERT_TYPE], "PEM"))) {
        failf(data, "LDAP local: ERROR OpenLDAP only supports PEM cert-type!");
        result = CURLE_SSL_CERTPROBLEM;
        goto quit;
      }
      if(!ldap_ca) {
        failf(data, "LDAP local: ERROR PEM CA cert not set!");
        result = CURLE_SSL_CERTPROBLEM;
        goto quit;
      }
      infof(data, "LDAP local: using PEM CA cert: %s\n", ldap_ca);
      rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_CACERTFILE, ldap_ca);
      if(rc != LDAP_SUCCESS) {
        failf(data, "LDAP local: ERROR setting PEM CA cert: %s",
                ldap_err2string(rc));
        result = CURLE_SSL_CERTPROBLEM;
        goto quit;
      }
      ldap_option = LDAP_OPT_X_TLS_DEMAND;
    }
    else
      ldap_option = LDAP_OPT_X_TLS_NEVER;

    rc = ldap_set_option(NULL, LDAP_OPT_X_TLS_REQUIRE_CERT, &ldap_option);
    if(rc != LDAP_SUCCESS) {
      failf(data, "LDAP local: ERROR setting cert verify mode: %s",
              ldap_err2string(rc));
      result = CURLE_SSL_CERTPROBLEM;
      goto quit;
    }
    server = ldap_init(conn->host.name, (int)conn->port);
    if(server == NULL) {
      failf(data, "LDAP local: Cannot connect to %s:%ld",
              conn->host.name, conn->port);
      result = CURLE_COULDNT_CONNECT;
      goto quit;
    }
    ldap_option = LDAP_OPT_X_TLS_HARD;
    rc = ldap_set_option(server, LDAP_OPT_X_TLS, &ldap_option);
    if(rc != LDAP_SUCCESS) {
      failf(data, "LDAP local: ERROR setting SSL/TLS mode: %s",
              ldap_err2string(rc));
      result = CURLE_SSL_CERTPROBLEM;
      goto quit;
    }
/*
    rc = ldap_start_tls_s(server, NULL, NULL);
    if(rc != LDAP_SUCCESS) {
      failf(data, "LDAP local: ERROR starting SSL/TLS mode: %s",
              ldap_err2string(rc));
      result = CURLE_SSL_CERTPROBLEM;
      goto quit;
    }
*/
#else
    /* we should probably never come up to here since configure
       should check in first place if we can support LDAP SSL/TLS */
    failf(data, "LDAP local: SSL/TLS not supported with this version "
            "of the OpenLDAP toolkit\n");
    result = CURLE_SSL_CERTPROBLEM;
    goto quit;
#endif
#endif
#endif /* CURL_LDAP_USE_SSL */
  }
  else {
    server = ldap_init(conn->host.name, (int)conn->port);
    if(server == NULL) {
      failf(data, "LDAP local: Cannot connect to %s:%ld",
              conn->host.name, conn->port);
      result = CURLE_COULDNT_CONNECT;
      goto quit;
    }
  }
#ifdef CURL_LDAP_WIN
  ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
#endif

  rc = ldap_simple_bind_s(server,
                          conn->bits.user_passwd ? conn->user : NULL,
                          conn->bits.user_passwd ? conn->passwd : NULL);
  if(!ldap_ssl && rc != 0) {
    ldap_proto = LDAP_VERSION2;
    ldap_set_option(server, LDAP_OPT_PROTOCOL_VERSION, &ldap_proto);
    rc = ldap_simple_bind_s(server,
                            conn->bits.user_passwd ? conn->user : NULL,
                            conn->bits.user_passwd ? conn->passwd : NULL);
  }
  if(rc != 0) {
    failf(data, "LDAP local: ldap_simple_bind_s %s", ldap_err2string(rc));
    result = CURLE_LDAP_CANNOT_BIND;
    goto quit;
  }

  rc = ldap_search_s(server, ludp->lud_dn, ludp->lud_scope,
                     ludp->lud_filter, ludp->lud_attrs, 0, &ldapmsg);

  if(rc != 0 && rc != LDAP_SIZELIMIT_EXCEEDED) {
    failf(data, "LDAP remote: %s", ldap_err2string(rc));
    result = CURLE_LDAP_SEARCH_FAILED;
    goto quit;
  }

  for(num = 0, entryIterator = ldap_first_entry(server, ldapmsg);
      entryIterator;
      entryIterator = ldap_next_entry(server, entryIterator), num++) {
    BerElement *ber = NULL;
    char  *attribute;       /*! suspicious that this isn't 'const' */
    char  *dn = ldap_get_dn(server, entryIterator);
    int i;

    result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"DN: ", 4);
    if(result)
      goto quit;

    result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)dn, 0);
    if(result)
      goto quit;

    result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
    if(result)
      goto quit;

    dlsize += strlen(dn)+5;

    for(attribute = ldap_first_attribute(server, entryIterator, &ber);
        attribute;
        attribute = ldap_next_attribute(server, entryIterator, ber)) {
      BerValue **vals = ldap_get_values_len(server, entryIterator, attribute);

      if(vals != NULL) {
        for(i = 0; (vals[i] != NULL); i++) {
          result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\t", 1);
          if(result)
            goto quit;

          result = Curl_client_write(conn, CLIENTWRITE_BODY,
                                     (char *)attribute, 0);
          if(result)
            goto quit;

          result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)": ", 2);
          if(result)
            goto quit;
          dlsize += strlen(attribute)+3;

          if((strlen(attribute) > 7) &&
              (strcmp(";binary",
                      (char *)attribute +
                      (strlen((char *)attribute) - 7)) == 0)) {
            /* Binary attribute, encode to base64. */
            CURLcode error = Curl_base64_encode(data,
                                                vals[i]->bv_val,
                                                vals[i]->bv_len,
                                                &val_b64,
                                                &val_b64_sz);
            if(error) {
              ldap_value_free_len(vals);
              ldap_memfree(attribute);
              ldap_memfree(dn);
              if(ber)
                ber_free(ber, 0);
              result = error;
              goto quit;
            }
            if(val_b64_sz > 0) {
              result = Curl_client_write(conn, CLIENTWRITE_BODY, val_b64,
                                         val_b64_sz);
              free(val_b64);
              if(result)
                goto quit;
              dlsize += val_b64_sz;
            }
          }
          else {
            result = Curl_client_write(conn, CLIENTWRITE_BODY, vals[i]->bv_val,
                                       vals[i]->bv_len);
            if(result)
              goto quit;
            dlsize += vals[i]->bv_len;
          }
          result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 0);
          if(result)
            goto quit;
          dlsize++;
        }

        /* Free memory used to store values */
        ldap_value_free_len(vals);
      }
      result = Curl_client_write(conn, CLIENTWRITE_BODY, (char *)"\n", 1);
      if(result)
        goto quit;
      dlsize++;
      Curl_pgrsSetDownloadCounter(data, dlsize);
      ldap_memfree(attribute);
    }
    ldap_memfree(dn);
    if(ber)
       ber_free(ber, 0);
  }

quit:
  if(ldapmsg) {
    ldap_msgfree(ldapmsg);
    LDAP_TRACE (("Received %d entries\n", num));
  }
  if(rc == LDAP_SIZELIMIT_EXCEEDED)
    infof(data, "There are more than %d entries\n", num);
  if(ludp)
    ldap_free_urldesc(ludp);
  if(server)
    ldap_unbind_s(server);
#if defined(HAVE_LDAP_SSL) && defined(CURL_HAS_NOVELL_LDAPSDK)
  if(ldap_ssl)
    ldapssl_client_deinit();
#endif /* HAVE_LDAP_SSL && CURL_HAS_NOVELL_LDAPSDK */

  /* no data to transfer */
  Curl_setup_transfer(conn, -1, -1, FALSE, NULL, -1, NULL);
  connclose(conn, "LDAP connection always disable re-use");

  return result;
}
Exemplo n.º 4
0
int
main( int argc, char **argv )
{
	LDAP		*ld;
	LDAPMessage	*result, *e;
	BerElement	*ber;
	char		*a, *dn;
	char		**vals;
	int		i;

	/* Initialize the client */
	if ( ldapssl_client_init( MY_CERTDB_PATH, NULL ) < 0 ) {
		perror( "ldapssl_client_init" );
		return( 1 );
	}

	/* set the max I/O timeout option to 10 seconds */
	if ( prldap_set_session_option( NULL, NULL, PRLDAP_OPT_IO_MAX_TIMEOUT,
	    10000 /* 10 secs */ ) != LDAP_SUCCESS ) {
		ldap_perror( NULL,
		    "prldap_set_session_option PRLDAP_OPT_IO_MAX_TIMEOUT" );
		exit( 1 );
	}

	/* get a handle to an LDAP connection */
	if ( (ld = ldapssl_init( MY_HOST, MY_SSL_PORT, 1 )) == NULL ) {
		perror( "ldapssl_init" );
		return( 1 );
	}

	/* use LDAPv3 */
	i = LDAP_VERSION3;
	if ( ldap_set_option( ld, LDAP_OPT_PROTOCOL_VERSION, &i ) < 0 ) {
		ldap_perror( ld, "ldap_set_option LDAPv3" );
		ldap_unbind( ld );
		return( 1 );
	}

	/* search for all entries with surname of Jensen */
	if ( ldap_search_s( ld, PEOPLE_BASE, LDAP_SCOPE_SUBTREE,
		"(sn=jensen)", NULL, 0, &result ) != LDAP_SUCCESS ) {
		ldap_perror( ld, "ldap_search_s" );
		if ( result == NULL ) {
			ldap_unbind( ld );
			return( 1 );
		}
	}
	/* for each entry print out name + all attrs and values */
	for ( e = ldap_first_entry( ld, result ); e != NULL;
	    e = ldap_next_entry( ld, e ) ) {
		if ( (dn = ldap_get_dn( ld, e )) != NULL ) {
		    printf( "dn: %s\n", dn );
		    ldap_memfree( dn );
		}
		for ( a = ldap_first_attribute( ld, e, &ber );
		    a != NULL; a = ldap_next_attribute( ld, e, ber ) ) {
			if ((vals = ldap_get_values( ld, e, a)) != NULL ) {
				for ( i = 0; vals[i] != NULL; i++ ) {
				    printf( "%s: %s\n", a, vals[i] );
				}
				ldap_value_free( vals );
			}
			ldap_memfree( a );
		}
		if ( ber != NULL ) {
			ber_free( ber, 0 );
		}
		printf( "\n" );
	}
	ldap_msgfree( result );
	ldap_unbind( ld );
	return( 0 );
}
static void
ldapconnect(void)
{
    int rc;

/* On Windows ldap_start_tls_s is available starting from Windows XP, 
 * so we need to bind at run-time with the function entry point
 */
#ifdef _SQUID_MSWIN_
    if (use_tls) {

	HMODULE WLDAP32Handle;

	WLDAP32Handle = GetModuleHandle("wldap32");
	if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) == NULL) {
	    fprintf(stderr, PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n");
	    exit(1);
	}
    }
#endif

    if (ld == NULL) {
#if HAS_URI_SUPPORT
	if (strstr(ldapServer, "://") != NULL) {
	    rc = ldap_initialize(&ld, ldapServer);
	    if (rc != LDAP_SUCCESS) {
		fprintf(stderr, "\nUnable to connect to LDAPURI:%s\n", ldapServer);
	    }
	} 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);
	}
	if (connect_timeout)
	    squid_ldap_set_connect_timeout(connect_timeout);

#ifdef LDAP_VERSION3
	if (version == -1) {
	    version = LDAP_VERSION2;
	}
	if (ldap_set_option(ld, LDAP_OPT_PROTOCOL_VERSION, &version)
	    != LDAP_SUCCESS) {
	    fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
		version);
	    ldap_unbind(ld);
	    ld = NULL;
	}
	if (use_tls) {
#ifdef LDAP_OPT_X_TLS
	    if ((version == LDAP_VERSION3) && (ldap_start_tls_s(ld, NULL, NULL) == LDAP_SUCCESS)) {
		fprintf(stderr, "Could not Activate TLS connection\n");
		ldap_unbind(ld);
		ld = NULL;
	    }
#else
	    fprintf(stderr, "TLS not supported with your LDAP library\n");
	    ldap_unbind(ld);
	    ld = NULL;
#endif
	}
#endif
	squid_ldap_set_timelimit(timelimit);
	squid_ldap_set_referrals(!noreferrals);
	squid_ldap_set_aliasderef(aliasderef);
	if (binddn && bindpasswd && *binddn && *bindpasswd) {
	    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));
		ldap_unbind(ld);
		ld = NULL;
	    }
	}
	if (debug)
	    fprintf(stderr, "Connected OK\n");
    }
}
Exemplo n.º 6
0
int
main(int argc, char **argv)
{
    char buf[8192];
    char *user, *group, *extension_dn = NULL;
    char *ldapServer = NULL;
    LDAP *ld = NULL;
    int tryagain = 0, rc;
    int port = LDAP_PORT;
    int use_extension_dn = 0;
    int strip_nt_domain = 0;
    int strip_kerberos_realm = 0;

    setbuf(stdout, NULL);

    while (argc > 1 && argv[1][0] == '-') {
	char *value = "";
	char option = argv[1][1];
	switch (option) {
	case 'P':
	case 'R':
	case 'z':
	case 'Z':
	case 'd':
	case 'g':
	case 'S':
	case 'K':
	    break;
	default:
	    if (strlen(argv[1]) > 2) {
		value = argv[1] + 2;
	    } else if (argc > 2) {
		value = argv[2];
		argv++;
		argc--;
	    } else
		value = "";
	    break;
	}
	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;
		char *newhost = malloc(len);
		snprintf(newhost, len, "%s %s", ldapServer, value);
		free(ldapServer);
		ldapServer = newhost;
	    } else {
		ldapServer = strdup(value);
	    }
	    break;
	case 'b':
	    basedn = value;
	    break;
	case 'f':
	    searchfilter = value;
	    break;
	case 'B':
	    userbasedn = value;
	    break;
	case 'F':
	    usersearchfilter = value;
	    break;
	case 'u':
	    userdnattr = value;
	    break;
	case 's':
	    if (strcmp(value, "base") == 0)
		searchscope = LDAP_SCOPE_BASE;
	    else if (strcmp(value, "one") == 0)
		searchscope = LDAP_SCOPE_ONELEVEL;
	    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;
	    else if (strcmp(value, "always") == 0)
		aliasderef = LDAP_DEREF_ALWAYS;
	    else if (strcmp(value, "search") == 0)
		aliasderef = LDAP_DEREF_SEARCHING;
	    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;
	case 'D':
	    binddn = value;
	    break;
	case 'w':
	    bindpasswd = value;
	    break;
	case 'W':
	    readSecret(value);
	    break;
	case 'P':
	    persistent = !persistent;
	    break;
	case 'p':
	    port = atoi(value);
	    break;
	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
	case 'd':
	    debug = 1;
	    break;
	case 'g':
	    use_extension_dn = 1;
	    break;
	case 'S':
	    strip_nt_domain = 1;
	    break;
	case 'K':
	    strip_kerberos_realm = 1;
	    break;
	default:
	    fprintf(stderr, PROGRAM_NAME " ERROR: Unknown command line option '%c'\n", option);
	    exit(1);
	}
    }

    while (argc > 1) {
	char *value = argv[1];
	if (ldapServer) {
	    int len = strlen(ldapServer) + 1 + strlen(value) + 1;
	    char *newhost = malloc(len);
	    snprintf(newhost, len, "%s %s", ldapServer, value);
	    free(ldapServer);
	    ldapServer = newhost;
	} else {
	    ldapServer = strdup(value);
	}
	argc--;
	argv++;
    }

    if (!ldapServer)
	ldapServer = "localhost";

    if (!basedn || !searchfilter) {
	fprintf(stderr, "\n" PROGRAM_NAME " version " PROGRAM_VERSION "\n\n");
	fprintf(stderr, "Usage: " PROGRAM_NAME " -b basedn -f filter [options] ldap_server_name\n\n");
	fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under where to search for groups\n");
	fprintf(stderr, "\t-f filter (REQUIRED)\tgroup search filter pattern. %%u = user,\n\t\t\t\t%%g = group\n");
	fprintf(stderr, "\t-B basedn (REQUIRED)\tbase dn under where to search for users\n");
	fprintf(stderr, "\t-F filter (REQUIRED)\tuser search filter pattern. %%s = login\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 (defaults to %d)\n", LDAP_PORT);
	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\n\t\t\t\tLDAP version 3\n");
#endif
	fprintf(stderr, "\t-g\t\t\tfirst query parameter is base DN extension\n\t\t\t\tfor this query\n");
	fprintf(stderr, "\t-S\t\t\tStrip NT domain from usernames\n");
	fprintf(stderr, "\t-K\t\t\tStrip Kerberos realm from usernames\n");
	fprintf(stderr, "\t-d\t\t\tenable debug mode\n");
	fprintf(stderr, "\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);
    }
/* On Windows ldap_start_tls_s is available starting from Windows XP, 
 * so we need to bind at run-time with the function entry point
 */
#ifdef _SQUID_MSWIN_
    if (use_tls) {

	HMODULE WLDAP32Handle;

	WLDAP32Handle = GetModuleHandle("wldap32");
	if ((Win32_ldap_start_tls_s = (PFldap_start_tls_s) GetProcAddress(WLDAP32Handle, LDAP_START_TLS_S)) == NULL) {
	    fprintf(stderr, PROGRAM_NAME ": ERROR: TLS (-Z) not supported on this platform.\n");
	    exit(1);
	}
    }
#endif

    while (fgets(buf, 256, stdin) != NULL) {
	int found = 0;
	if (!strchr(buf, '\n')) {
	    /* too large message received.. skip and deny */
	    fprintf(stderr, "%s: ERROR: Too large: %s\n", argv[0], buf);
	    while (fgets(buf, sizeof(buf), stdin)) {
		fprintf(stderr, "%s: ERROR: Too large..: %s\n", argv[0], buf);
		if (strchr(buf, '\n') != NULL)
		    break;
	    }
	    goto error;
	}
	user = strtok(buf, " \n");
	if (!user) {
	    fprintf(stderr, "%s: Invalid request\n", argv[0]);
	    goto error;
	}
	rfc1738_unescape(user);
	if (strip_nt_domain) {
	    char *u = strrchr(user, '\\');
	    if (!u)
		u = strrchr(user, '/');
	    if (!u)
		u = strrchr(user, '+');
	    if (u && u[1])
		user = u + 1;
	}
	if (strip_kerberos_realm) {
	    char *u = strchr(user, '@');
	    if (u != NULL) {
		*u = '\0';
	    }
	}
	if (use_extension_dn) {
	    extension_dn = strtok(NULL, " \n");
	    if (!extension_dn) {
		fprintf(stderr, "%s: Invalid request\n", argv[0]);
		goto error;
	    }
	    rfc1738_unescape(extension_dn);
	}
	while (!found && user && (group = strtok(NULL, " \n")) != NULL) {
	    rfc1738_unescape(group);

	  recover:
	    if (ld == NULL) {
#if HAS_URI_SUPPORT
		if (strstr(ldapServer, "://") != NULL) {
		    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);
		    break;
		}
		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_SUCCESS) {
		    fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
			version);
		    ldap_unbind(ld);
		    ld = NULL;
		    break;
		}
		if (use_tls) {
#ifdef LDAP_OPT_X_TLS
		    if (version != LDAP_VERSION3) {
			fprintf(stderr, "TLS requires LDAP version 3\n");
			exit(1);
		    } else if (ldap_start_tls_s(ld, NULL, NULL) != LDAP_SUCCESS) {
			fprintf(stderr, "Could not Activate TLS connection\n");
			ldap_unbind(ld);
			ld = NULL;
			break;
		    }
#else
		    fprintf(stderr, "TLS not supported with your LDAP library\n");
		    exit(1);
#endif
		}
#endif
		squid_ldap_set_timelimit(ld, timelimit);
		squid_ldap_set_referrals(ld, !noreferrals);
		squid_ldap_set_aliasderef(ld, aliasderef);
		if (binddn && bindpasswd && *binddn && *bindpasswd) {
		    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));
			ldap_unbind(ld);
			ld = NULL;
			break;
		    }
		}
		if (debug)
		    fprintf(stderr, "Connected OK\n");
	    }
	    if (searchLDAP(ld, group, user, extension_dn) == 0) {
		found = 1;
		break;
	    } else {
		if (tryagain) {
		    tryagain = 0;
		    ldap_unbind(ld);
		    ld = NULL;
		    goto recover;
		}
	    }
	}
	if (found)
	    printf("OK\n");
	else {
	  error:
	    printf("ERR\n");
	}

	if (ld != NULL) {
	    if (!persistent || (squid_ldap_errno(ld) != LDAP_SUCCESS && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS)) {
		ldap_unbind(ld);
		ld = NULL;
	    } else {
		tryagain = 1;
	    }
	}
    }
    if (ld)
	ldap_unbind(ld);
    return 0;
}
static LDAP *
open_ldap_connection(const char *ldapServer, int port)
{
    LDAP *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);
	    exit(1);
	}
    } 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_SUCCESS) {
	fprintf(stderr, "Could not set LDAP_OPT_PROTOCOL_VERSION %d\n",
	    version);
	exit(1);
    }
    if (use_tls) {
#ifdef LDAP_OPT_X_TLS
	if (version != LDAP_VERSION3) {
	    fprintf(stderr, "TLS requires LDAP version 3\n");
	    exit(1);
	} else if (ldap_start_tls_s(ld, NULL, NULL) != LDAP_SUCCESS) {
	    fprintf(stderr, "Could not Activate TLS connection\n");
	    exit(1);
	}
#else
	fprintf(stderr, "TLS not supported with your LDAP library\n");
	exit(1);
#endif
    }
#endif
    squid_ldap_set_timelimit(ld, timelimit);
    squid_ldap_set_referrals(ld, !noreferrals);
    squid_ldap_set_aliasderef(ld, aliasderef);
    return ld;
}