From: hno <> Date: Sun, 23 Jun 2002 20:11:40 +0000 (+0000) Subject: A simple external_acl helper to match LDAP groups X-Git-Tag: SQUID_3_0_PRE1~956 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=8f7b71f7a6c7d51b7621167b0a0f31b5d1f173cc;p=thirdparty%2Fsquid.git A simple external_acl helper to match LDAP groups --- diff --git a/helpers/external_acl/ldap_group/squid_ldap_group.c b/helpers/external_acl/ldap_group/squid_ldap_group.c new file mode 100644 index 0000000000..8aba8a1a96 --- /dev/null +++ b/helpers/external_acl/ldap_group/squid_ldap_group.c @@ -0,0 +1,295 @@ +/* + * squid_ldap_match: lookup group membership in LDAP + * + * Author: Flavio Pescuma + * MARA Systems AB, Sweden + * + * Based on squid_ldap_auth by Glen Newton + * + * Dependencies: You need to get the OpenLDAP libraries + * from http://www.openldap.org + * + * License: squid_ldap_match is free software; you can redistribute it + * and/or modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2, + * or (at your option) any later version. + * + * Changes: + * Version 2.0 + * 2002-01-22: Henrik Nordstrom + * Added optional third query argument for search RDN + * 2002-01-22: Henrik Nordstrom + * Removed unused options, and fully changed name + * to squid_ldap_match. + * Version 1.0 + * 2001-07-17: Flavio Pescuma + * Using the main function from squid_ldap_auth + * wrote squid_ldap_match. This program replaces + * the %a and %v (ldapfilter.conf) from the filter + * template supplied with -f with the two arguments + * sent by squid. Returns OK if the ldap_search + * using the composed filter succeeds. + * + * OLD Change: (from squid_ldap_auth.c) + * 2001-05-02: Henrik Nordstrom + * - Support newer OpenLDAP 2.x libraries using the + * revised Internet Draft API which unfortunately + * is not backwards compatible with RFC1823.. + * 2001-04-15: Henrik Nordstrom + * - Added command line option for basedn + * - Added the ability to search for the user DN + * 2001-04-16: Henrik Nordstrom + * - Added -D binddn -w bindpasswd. + * 2001-04-17: Henrik Nordstrom + * - Added -R to disable referrals + * - Added -a to control alias dereferencing + * 2001-04-17: Henrik Nordstrom + * - Added -u, DN username attribute name + * 2001-04-18: Henrik Nordstrom + * - Allow full filter specifications in -f + */ + +#include +#include +#include +#include +#include +#include + +/* Change this to your search base */ +static char *basedn; +static char *searchfilter = NULL; +static char *binddn = NULL; +static char *bindpasswd = NULL; +static int searchscope = LDAP_SCOPE_SUBTREE; +static int persistent = 0; +static int noreferrals = 0; +static int debug = 0; +static int aliasderef = LDAP_DEREF_NEVER; + +static int searchLDAP(LDAP * ld, char *group, char *user, char *grouprdn); + +/* Yuck.. we need to glue to different versions of the API */ + +#if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823 +static int squid_ldap_errno(LDAP *ld) +{ + int err = 0; + ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err); + return err; +} +static void squid_ldap_set_aliasderef(LDAP *ld, int deref) +{ + ldap_set_option(ld, LDAP_OPT_DEREF, &deref); +} +static void squid_ldap_set_referrals(LDAP *ld, int referrals) +{ + 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) +{ + return ld->ld_errno; +} +static void squid_ldap_set_aliasderef(LDAP *ld, int deref) +{ + ld->ld_deref = deref; +} +static void squid_ldap_set_referrals(LDAP *ld, int referrals) +{ + if (referrals) + ld->ld_options |= ~LDAP_OPT_REFERRALS; + else + ld->ld_options &= ~LDAP_OPT_REFERRALS; +} +#endif + +int +main(int argc, char **argv) +{ + char buf[256]; + char *user, *group, *grouprdn; + char *ldapServer; + LDAP *ld = NULL; + int tryagain,rc; + + setbuf(stdout, NULL); + + while (argc > 2 && argv[1][0] == '-') { + char *value = ""; + char option = argv[1][1]; + switch(option) { + case 'p': + case 'R': + break; + default: + if (strlen(argv[1]) > 2) { + value = argv[1]+2; + } else { + value = argv[2]; + argv++; + argc--; + } + break; + } + argv++; + argc--; + switch(option) { + case 'b': + basedn = value; + break; + case 'f': + searchfilter = 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, "squid_ldap_match: ERROR: Unknown search scope '%s'\n", value); + exit(1); + } + 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, "squid_ldap_match: ERROR: Unknown alias dereference method '%s'\n", value); + exit(1); + } + break; + case 'D': + binddn = value; + break; + case 'w': + bindpasswd = value; + break; + case 'p': + persistent = !persistent; + break; + case 'R': + noreferrals = !noreferrals; + break; + case 'd': + debug = 1; + break; + default: + fprintf(stderr, "squid_ldap_match: ERROR: Unknown command line option '%c'\n", option); + exit(1); + } + } + + if (!basedn || !searchfilter || argc != 2) { + fprintf(stderr, "Usage: squid_ldap_match [options] ldap_server_name\n\n"); + fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under where to search\n"); + fprintf(stderr, "\t-f filter (REQUIRED)\tsearch filter pattern\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-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 you need to bind as a user to perform searches then use the\n\t-D binddn -w bindpasswd options\n\n"); + exit(1); + } + + ldapServer = (char *) argv[1]; + + while (fgets(buf, 256, stdin) != NULL) { + user = strtok(buf, " \n\r"); + group = strtok(NULL, " \n\r"); + grouprdn = strtok(NULL, " \n\r"); + + if (!user || !group) { + printf("ERR\n"); + continue; + } + + tryagain = 1; +recover: + if (ld == NULL) { + if ((ld = ldap_init(ldapServer, LDAP_PORT)) == NULL) { + fprintf(stderr, "\nUnable to connect to LDAP server:%s port:%d\n", + ldapServer, LDAP_PORT); + exit(1); + } + squid_ldap_set_referrals(ld, !noreferrals); + squid_ldap_set_aliasderef(ld, aliasderef); + } + rc = ldap_simple_bind_s(ld, binddn, bindpasswd); + if (rc != LDAP_SUCCESS) { + fprintf(stderr, "squid_ldap_match: WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc)); + exit(1); + } + if (debug) printf("Binding OK\n"); + if (searchLDAP(ld, group, user, grouprdn) != 0) { + if (tryagain) { + tryagain = 0; + ldap_unbind(ld); + ld = NULL; + goto recover; + } + printf("ERR\n"); + } else { + printf("OK\n"); + } + if (!persistent || (squid_ldap_errno(ld) != LDAP_SUCCESS && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS)) { + ldap_unbind(ld); + ld = NULL; + } + } + if (ld) + ldap_unbind(ld); + return 0; +} + +static int +searchLDAP(LDAP * ld, char *group, char *member, char *grouprdn) +{ +int rc; +char filter[256]; +static char searchbase[256]; +LDAPMessage *res = NULL; +LDAPMessage *entry; + + if (grouprdn) + snprintf(searchbase, sizeof(searchbase), "%s,%s", grouprdn, basedn); + else + snprintf(searchbase, sizeof(searchbase), "%s", basedn); + + ldap_build_filter( filter, sizeof(filter), searchfilter, NULL, NULL, group, member, NULL ); + if (debug) printf("filter %s\n",filter); + + + if (ldap_search_s(ld, searchbase , searchscope, filter, NULL, 1, &res) != LDAP_SUCCESS) { + int rc = ldap_result2error(ld, res, 0); + if (noreferrals && rc == LDAP_PARTIAL_RESULTS) { + /* Everything is fine. This is expected when referrals + * are disabled. + */ + } else { + fprintf(stderr, "squid_ldap_match: WARNING, LDAP search error '%s'\n", ldap_err2string(rc)); + } + ldap_msgfree(res); + return 1; + } + entry = ldap_first_entry(ld, res); + if (!entry) { + ldap_msgfree(res); + return 1; + } + + ldap_msgfree(res); + return 0; +}