]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/external_acl/ldap_group/squid_ldap_group.c
A simple external_acl helper to match LDAP groups
[thirdparty/squid.git] / helpers / external_acl / ldap_group / squid_ldap_group.c
CommitLineData
8f7b71f7 1/*
2 * squid_ldap_match: lookup group membership in LDAP
3 *
4 * Author: Flavio Pescuma <flavio@marasystems.com>
5 * MARA Systems AB, Sweden
6 *
7 * Based on squid_ldap_auth by Glen Newton
8 *
9 * Dependencies: You need to get the OpenLDAP libraries
10 * from http://www.openldap.org
11 *
12 * License: squid_ldap_match is free software; you can redistribute it
13 * and/or modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2,
15 * or (at your option) any later version.
16 *
17 * Changes:
18 * Version 2.0
19 * 2002-01-22: Henrik Nordstrom <hno@marasystems.com>
20 * Added optional third query argument for search RDN
21 * 2002-01-22: Henrik Nordstrom <hno@marasystems.com>
22 * Removed unused options, and fully changed name
23 * to squid_ldap_match.
24 * Version 1.0
25 * 2001-07-17: Flavio Pescuma <flavio@marasystems.com>
26 * Using the main function from squid_ldap_auth
27 * wrote squid_ldap_match. This program replaces
28 * the %a and %v (ldapfilter.conf) from the filter
29 * template supplied with -f with the two arguments
30 * sent by squid. Returns OK if the ldap_search
31 * using the composed filter succeeds.
32 *
33 * OLD Change: (from squid_ldap_auth.c)
34 * 2001-05-02: Henrik Nordstrom <hno@squid-cache.org>
35 * - Support newer OpenLDAP 2.x libraries using the
36 * revised Internet Draft API which unfortunately
37 * is not backwards compatible with RFC1823..
38 * 2001-04-15: Henrik Nordstrom <hno@squid-cache.org>
39 * - Added command line option for basedn
40 * - Added the ability to search for the user DN
41 * 2001-04-16: Henrik Nordstrom <hno@squid-cache.org>
42 * - Added -D binddn -w bindpasswd.
43 * 2001-04-17: Henrik Nordstrom <hno@squid-cache.org>
44 * - Added -R to disable referrals
45 * - Added -a to control alias dereferencing
46 * 2001-04-17: Henrik Nordstrom <hno@squid-cache.org>
47 * - Added -u, DN username attribute name
48 * 2001-04-18: Henrik Nordstrom <hno@squid-cache.org>
49 * - Allow full filter specifications in -f
50 */
51
52#include <stdio.h>
53#include <string.h>
54#include <stdlib.h>
55#include <lber.h>
56#include <ldap_cdefs.h>
57#include <ldap.h>
58
59/* Change this to your search base */
60static char *basedn;
61static char *searchfilter = NULL;
62static char *binddn = NULL;
63static char *bindpasswd = NULL;
64static int searchscope = LDAP_SCOPE_SUBTREE;
65static int persistent = 0;
66static int noreferrals = 0;
67static int debug = 0;
68static int aliasderef = LDAP_DEREF_NEVER;
69
70static int searchLDAP(LDAP * ld, char *group, char *user, char *grouprdn);
71
72/* Yuck.. we need to glue to different versions of the API */
73
74#if defined(LDAP_API_VERSION) && LDAP_API_VERSION > 1823
75static int squid_ldap_errno(LDAP *ld)
76{
77 int err = 0;
78 ldap_get_option(ld, LDAP_OPT_ERROR_NUMBER, &err);
79 return err;
80}
81static void squid_ldap_set_aliasderef(LDAP *ld, int deref)
82{
83 ldap_set_option(ld, LDAP_OPT_DEREF, &deref);
84}
85static void squid_ldap_set_referrals(LDAP *ld, int referrals)
86{
87 int *value = referrals ? LDAP_OPT_ON : LDAP_OPT_OFF;
88 ldap_set_option(ld, LDAP_OPT_REFERRALS, value);
89}
90#else
91static int squid_ldap_errno(LDAP *ld)
92{
93 return ld->ld_errno;
94}
95static void squid_ldap_set_aliasderef(LDAP *ld, int deref)
96{
97 ld->ld_deref = deref;
98}
99static void squid_ldap_set_referrals(LDAP *ld, int referrals)
100{
101 if (referrals)
102 ld->ld_options |= ~LDAP_OPT_REFERRALS;
103 else
104 ld->ld_options &= ~LDAP_OPT_REFERRALS;
105}
106#endif
107
108int
109main(int argc, char **argv)
110{
111 char buf[256];
112 char *user, *group, *grouprdn;
113 char *ldapServer;
114 LDAP *ld = NULL;
115 int tryagain,rc;
116
117 setbuf(stdout, NULL);
118
119 while (argc > 2 && argv[1][0] == '-') {
120 char *value = "";
121 char option = argv[1][1];
122 switch(option) {
123 case 'p':
124 case 'R':
125 break;
126 default:
127 if (strlen(argv[1]) > 2) {
128 value = argv[1]+2;
129 } else {
130 value = argv[2];
131 argv++;
132 argc--;
133 }
134 break;
135 }
136 argv++;
137 argc--;
138 switch(option) {
139 case 'b':
140 basedn = value;
141 break;
142 case 'f':
143 searchfilter = value;
144 break;
145 case 's':
146 if (strcmp(value, "base") == 0)
147 searchscope = LDAP_SCOPE_BASE;
148 else if (strcmp(value, "one") == 0)
149 searchscope = LDAP_SCOPE_ONELEVEL;
150 else if (strcmp(value, "sub") == 0)
151 searchscope = LDAP_SCOPE_SUBTREE;
152 else {
153 fprintf(stderr, "squid_ldap_match: ERROR: Unknown search scope '%s'\n", value);
154 exit(1);
155 }
156 break;
157 case 'a':
158 if (strcmp(value, "never") == 0)
159 aliasderef = LDAP_DEREF_NEVER;
160 else if (strcmp(value, "always") == 0)
161 aliasderef = LDAP_DEREF_ALWAYS;
162 else if (strcmp(value, "search") == 0)
163 aliasderef = LDAP_DEREF_SEARCHING;
164 else if (strcmp(value, "find") == 0)
165 aliasderef = LDAP_DEREF_FINDING;
166 else {
167 fprintf(stderr, "squid_ldap_match: ERROR: Unknown alias dereference method '%s'\n", value);
168 exit(1);
169 }
170 break;
171 case 'D':
172 binddn = value;
173 break;
174 case 'w':
175 bindpasswd = value;
176 break;
177 case 'p':
178 persistent = !persistent;
179 break;
180 case 'R':
181 noreferrals = !noreferrals;
182 break;
183 case 'd':
184 debug = 1;
185 break;
186 default:
187 fprintf(stderr, "squid_ldap_match: ERROR: Unknown command line option '%c'\n", option);
188 exit(1);
189 }
190 }
191
192 if (!basedn || !searchfilter || argc != 2) {
193 fprintf(stderr, "Usage: squid_ldap_match [options] ldap_server_name\n\n");
194 fprintf(stderr, "\t-b basedn (REQUIRED)\tbase dn under where to search\n");
195 fprintf(stderr, "\t-f filter (REQUIRED)\tsearch filter pattern\n");
196 fprintf(stderr, "\t-s base|one|sub\t\tsearch scope\n");
197 fprintf(stderr, "\t-D binddn\t\tDN to bind as to perform searches\n");
198 fprintf(stderr, "\t-w bindpasswd\t\tpassword for binddn\n");
199 fprintf(stderr, "\t-p\t\t\tpersistent LDAP connection\n");
200 fprintf(stderr, "\t-R\t\t\tdo not follow referrals\n");
201 fprintf(stderr, "\t-a never|always|search|find\n\t\t\t\twhen to dereference aliases\n");
202 fprintf(stderr, "\n");
203 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");
204 exit(1);
205 }
206
207 ldapServer = (char *) argv[1];
208
209 while (fgets(buf, 256, stdin) != NULL) {
210 user = strtok(buf, " \n\r");
211 group = strtok(NULL, " \n\r");
212 grouprdn = strtok(NULL, " \n\r");
213
214 if (!user || !group) {
215 printf("ERR\n");
216 continue;
217 }
218
219 tryagain = 1;
220recover:
221 if (ld == NULL) {
222 if ((ld = ldap_init(ldapServer, LDAP_PORT)) == NULL) {
223 fprintf(stderr, "\nUnable to connect to LDAP server:%s port:%d\n",
224 ldapServer, LDAP_PORT);
225 exit(1);
226 }
227 squid_ldap_set_referrals(ld, !noreferrals);
228 squid_ldap_set_aliasderef(ld, aliasderef);
229 }
230 rc = ldap_simple_bind_s(ld, binddn, bindpasswd);
231 if (rc != LDAP_SUCCESS) {
232 fprintf(stderr, "squid_ldap_match: WARNING, could not bind to binddn '%s'\n", ldap_err2string(rc));
233 exit(1);
234 }
235 if (debug) printf("Binding OK\n");
236 if (searchLDAP(ld, group, user, grouprdn) != 0) {
237 if (tryagain) {
238 tryagain = 0;
239 ldap_unbind(ld);
240 ld = NULL;
241 goto recover;
242 }
243 printf("ERR\n");
244 } else {
245 printf("OK\n");
246 }
247 if (!persistent || (squid_ldap_errno(ld) != LDAP_SUCCESS && squid_ldap_errno(ld) != LDAP_INVALID_CREDENTIALS)) {
248 ldap_unbind(ld);
249 ld = NULL;
250 }
251 }
252 if (ld)
253 ldap_unbind(ld);
254 return 0;
255}
256
257static int
258searchLDAP(LDAP * ld, char *group, char *member, char *grouprdn)
259{
260int rc;
261char filter[256];
262static char searchbase[256];
263LDAPMessage *res = NULL;
264LDAPMessage *entry;
265
266 if (grouprdn)
267 snprintf(searchbase, sizeof(searchbase), "%s,%s", grouprdn, basedn);
268 else
269 snprintf(searchbase, sizeof(searchbase), "%s", basedn);
270
271 ldap_build_filter( filter, sizeof(filter), searchfilter, NULL, NULL, group, member, NULL );
272 if (debug) printf("filter %s\n",filter);
273
274
275 if (ldap_search_s(ld, searchbase , searchscope, filter, NULL, 1, &res) != LDAP_SUCCESS) {
276 int rc = ldap_result2error(ld, res, 0);
277 if (noreferrals && rc == LDAP_PARTIAL_RESULTS) {
278 /* Everything is fine. This is expected when referrals
279 * are disabled.
280 */
281 } else {
282 fprintf(stderr, "squid_ldap_match: WARNING, LDAP search error '%s'\n", ldap_err2string(rc));
283 }
284 ldap_msgfree(res);
285 return 1;
286 }
287 entry = ldap_first_entry(ld, res);
288 if (!entry) {
289 ldap_msgfree(res);
290 return 1;
291 }
292
293 ldap_msgfree(res);
294 return 0;
295}