]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
Broken: define and use stub_libauth.cc
[thirdparty/squid.git] / helpers / external_acl / kerberos_ldap_group / kerberos_ldap_group.cc
1 /*
2 * -----------------------------------------------------------------------------
3 *
4 * Author: Markus Moeller (markus_moeller at compuserve.com)
5 *
6 * Copyright (C) 2007 Markus Moeller. All rights reserved.
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA.
21 *
22 * As a special exemption, M Moeller gives permission to link this program
23 * with MIT, Heimdal or other GSS/Kerberos libraries, and distribute
24 * the resulting executable, without including the source code for
25 * the Libraries in the source distribution.
26 *
27 * -----------------------------------------------------------------------------
28 */
29 /*
30 * Hosted at http://sourceforge.net/projects/squidkerbauth
31 */
32 #include "squid.h"
33 #include "helpers/defines.h"
34 #include "rfc1738.h"
35 #include "util.h"
36
37 #ifdef HAVE_LDAP
38
39 #include "support.h"
40 #ifdef HAVE_CTYPE_H
41 #include <ctype.h>
42 #endif
43
44 void
45 init_args(struct main_args *margs)
46 {
47 margs->nlist = NULL;
48 margs->glist = NULL;
49 margs->llist = NULL;
50 margs->ulist = NULL;
51 margs->tlist = NULL;
52 margs->luser = NULL;
53 margs->lpass = NULL;
54 margs->lbind = NULL;
55 margs->lurl = NULL;
56 margs->ssl = NULL;
57 margs->rc_allow = 0;
58 margs->AD = 0;
59 margs->mdepth = 5;
60 margs->ddomain = NULL;
61 margs->groups = NULL;
62 margs->ndoms = NULL;
63 margs->lservs = NULL;
64 }
65
66 void clean_gd(struct gdstruct *gdsp);
67 void clean_nd(struct ndstruct *ndsp);
68 void clean_ls(struct lsstruct *lssp);
69
70 void
71 clean_gd(struct gdstruct *gdsp)
72 {
73 struct gdstruct *p = NULL, *pp = NULL;
74
75 p = gdsp;
76 while (p) {
77 while (p->next) {
78 pp = p;
79 p = p->next;
80 }
81 safe_free(p->group);
82 safe_free(p->domain);
83 if (pp)
84 safe_free(pp->next);
85 if (p == gdsp)
86 safe_free(gdsp);
87 p = gdsp;
88 }
89 }
90
91 void
92 clean_nd(struct ndstruct *ndsp)
93 {
94 struct ndstruct *p = NULL, *pp = NULL;
95
96 p = ndsp;
97 while (p) {
98 while (p->next) {
99 pp = p;
100 p = p->next;
101 }
102 safe_free(p->netbios);
103 safe_free(p->domain);
104 if (pp)
105 safe_free(pp->next);
106 if (p == ndsp)
107 safe_free(ndsp);
108 p = ndsp;
109 }
110 }
111
112 void
113 clean_ls(struct lsstruct *lssp)
114 {
115 struct lsstruct *p = NULL, *pp = NULL;
116
117 p = lssp;
118 while (p) {
119 while (p->next) {
120 pp = p;
121 p = p->next;
122 }
123 safe_free(p->lserver);
124 safe_free(p->domain);
125 if (pp)
126 safe_free(pp->next);
127 if (p == lssp)
128 safe_free(lssp);
129 p = lssp;
130 }
131 }
132
133 void
134 clean_args(struct main_args *margs)
135 {
136 safe_free(margs->glist);
137 safe_free(margs->ulist);
138 safe_free(margs->tlist);
139 safe_free(margs->nlist);
140 safe_free(margs->llist);
141 safe_free(margs->luser);
142 safe_free(margs->lpass);
143 safe_free(margs->lbind);
144 safe_free(margs->lurl);
145 safe_free(margs->ssl);
146 safe_free(margs->ddomain);
147 if (margs->groups) {
148 clean_gd(margs->groups);
149 margs->groups = NULL;
150 }
151 if (margs->ndoms) {
152 clean_nd(margs->ndoms);
153 margs->ndoms = NULL;
154 }
155 if (margs->lservs) {
156 clean_ls(margs->lservs);
157 margs->lservs = NULL;
158 }
159 }
160
161 void strup(char *s);
162
163 int
164 main(int argc, char *const argv[])
165 {
166 char buf[6400];
167 char *user, *domain, *group;
168 char *up=NULL, *dp=NULL, *np=NULL;
169 char *nuser, *nuser8 = NULL, *netbios;
170 char *c;
171 int opt;
172 struct main_args margs;
173
174 setbuf(stdout, NULL);
175 setbuf(stdin, NULL);
176
177 init_args(&margs);
178
179 while (-1 != (opt = getopt(argc, argv, "diasg:D:N:S:u:U:t:T:p:l:b:m:h"))) {
180 switch (opt) {
181 case 'd':
182 debug_enabled = 1;
183 break;
184 case 'i':
185 log_enabled = 1;
186 break;
187 case 'a':
188 margs.rc_allow = 1;
189 break;
190 case 's':
191 margs.ssl = (char *) "yes";
192 break;
193 case 'g':
194 margs.glist = xstrdup(optarg);
195 break;
196 case 'D':
197 margs.ddomain = xstrdup(optarg);
198 break;
199 case 'N':
200 margs.nlist = xstrdup(optarg);
201 break;
202 case 'u':
203 margs.luser = xstrdup(optarg);
204 break;
205 case 'U':
206 margs.ulist = xstrdup(optarg);
207 break;
208 case 't':
209 margs.ulist = xstrdup(optarg);
210 break;
211 case 'T':
212 margs.tlist = xstrdup(optarg);
213 break;
214 case 'p':
215 margs.lpass = xstrdup(optarg);
216 /* Hide Password */
217 memset(optarg, 'X', strlen(optarg));
218 break;
219 case 'l':
220 margs.lurl = xstrdup(optarg);
221 break;
222 case 'b':
223 margs.lbind = xstrdup(optarg);
224 break;
225 case 'm':
226 margs.mdepth = atoi(optarg);
227 break;
228 case 'S':
229 margs.llist = xstrdup(optarg);
230 break;
231 case 'h':
232 fprintf(stderr, "Usage: \n");
233 fprintf(stderr, "squid_kerb_ldap [-d] [-i] -g group list [-D domain] [-N netbios domain map] [-s] [-u ldap user] [-p ldap user password] [-l ldap url] [-b ldap bind path] [-a] [-m max depth] [-h]\n");
234 fprintf(stderr, "-d full debug\n");
235 fprintf(stderr, "-i informational messages\n");
236 fprintf(stderr, "-g group list\n");
237 fprintf(stderr, "-t group list (only group name hex UTF-8 format)\n");
238 fprintf(stderr, "-T group list (all in hex UTF-8 format - except seperator @)\n");
239 fprintf(stderr, "-D default domain\n");
240 fprintf(stderr, "-N netbios to dns domain map\n");
241 fprintf(stderr, "-S ldap server to dns domain map\n");
242 fprintf(stderr, "-u ldap user\n");
243 fprintf(stderr, "-p ldap user password\n");
244 fprintf(stderr, "-l ldap url\n");
245 fprintf(stderr, "-b ldap bind path\n");
246 fprintf(stderr, "-s use SSL encryption with Kerberos authentication\n");
247 fprintf(stderr, "-a allow SSL without cert verification\n");
248 fprintf(stderr, "-m maximal depth for recursive searches\n");
249 fprintf(stderr, "-h help\n");
250 fprintf(stderr, "The ldap url, ldap user and ldap user password details are only used if the kerberised\n");
251 fprintf(stderr, "access fails(e.g. unknown domain) or if the username does not contain a domain part\n");
252 fprintf(stderr, "and no default domain is provided.\n");
253 fprintf(stderr, "If the ldap url starts with ldaps:// it is either start_tls or simple SSL\n");
254 fprintf(stderr, "The group list can be:\n");
255 fprintf(stderr, "group - In this case group can be used for all keberised and non kerberised ldap servers\n");
256 fprintf(stderr, "group@ - In this case group can be used for all keberised ldap servers\n");
257 fprintf(stderr, "group@domain - In this case group can be used for ldap servers of domain domain\n");
258 fprintf(stderr, "group1@domain1:group2@domain2:group3@:group4 - A list is build with a colon as seperator\n");
259 fprintf(stderr, "Group membership is determined with AD servers through the users memberof attribute which\n");
260 fprintf(stderr, "is followed to the top (e.g. if the group is a member of a group)\n");
261 fprintf(stderr, "Group membership is determined with non AD servers through the users memberuid (assuming\n");
262 fprintf(stderr, "PosixGroup) or primary group membership (assuming PosixAccount)\n");
263 fprintf(stderr, "The ldap server list can be:\n");
264 fprintf(stderr, "server - In this case server can be used for all Kerberos domains\n");
265 fprintf(stderr, "server@ - In this case server can be used for all Kerberos domains\n");
266 fprintf(stderr, "server@domain - In this case server can be used for Kerberos domain domain\n");
267 fprintf(stderr, "server1a@domain1:server1b@domain1:server2@domain2:server3@:server4 - A list is build with a colon as seperator\n");
268 clean_args(&margs);
269 exit(0);
270 default:
271 warn((char *) "%s| %s: WARNING: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
272 }
273 }
274
275 debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, KERBEROS_LDAP_GROUP_VERSION);
276 int gopt = 0;
277 if (create_gd(&margs)) {
278 if ( margs.glist != NULL ) {
279 debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL");
280 SEND_ERR("");
281 clean_args(&margs);
282 exit(1);
283 } else {
284 debug((char *) "%s| %s: INFO: no group list given expect it from stdin\n", LogTime(), PROGRAM);
285 gopt = 1;
286 }
287 }
288 if (create_nd(&margs)) {
289 debug((char *) "%s| %s: FATAL: Error in netbios list: %s\n", LogTime(), PROGRAM, margs.nlist ? margs.nlist : "NULL");
290 SEND_ERR("");
291 clean_args(&margs);
292 exit(1);
293 }
294 if (create_ls(&margs)) {
295 debug((char *) "%s| %s: Error in ldap server list: %s\n", LogTime(), PROGRAM, margs.llist ? margs.llist : "NULL");
296 SEND_ERR("");
297 clean_args(&margs);
298 exit(1);
299 }
300 while (1) {
301 if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
302 if (ferror(stdin)) {
303 debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
304 strerror(ferror(stdin)));
305
306 SEND_ERR("");
307 clean_args(&margs);
308 exit(1); /* BIIG buffer */
309 }
310 SEND_ERR("");
311 clean_args(&margs);
312 exit(0);
313 }
314 c = (char *) memchr(buf, '\n', sizeof(buf) - 1);
315 if (c) {
316 *c = '\0';
317 } else {
318 SEND_ERR("Invalid input. CR missing");
319 debug((char *) "%s| %s: ERR\n", LogTime(), PROGRAM);
320 continue;
321 }
322
323 user = strtok(buf, " \n");
324 if (!user) {
325 debug((char *) "%s| %s: INFO: No Username given\n", LogTime(), PROGRAM);
326 SEND_ERR("Invalid request. No Username");
327 continue;
328 }
329 rfc1738_unescape(user);
330 nuser = strchr(user, '\\');
331 if (!nuser)
332 nuser8 = strstr(user, "%5C");
333 if (!nuser && !nuser8)
334 nuser8 = strstr(user, "%5c");
335 domain = strrchr(user, '@');
336 if (nuser || nuser8) {
337 if (nuser) {
338 *nuser = '\0';
339 ++nuser;
340 } else {
341 *nuser8 = '\0';
342 nuser = nuser8 + 3;
343 }
344 netbios = user;
345 up = xstrdup(rfc1738_escape(nuser));
346 np = xstrdup(rfc1738_escape(netbios));
347 if (debug_enabled)
348 debug((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, up, np);
349 else
350 log((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, up, np);
351 domain = get_netbios_name(&margs, netbios);
352 user = nuser;
353 safe_free(up);
354 safe_free(np);
355 } else if (domain) {
356 strup(domain);
357 *domain = '\0';
358 ++domain;
359 }
360 up = xstrdup(rfc1738_escape(user));
361 if (domain)
362 dp = xstrdup(rfc1738_escape(domain));
363 if (!domain && margs.ddomain) {
364 domain = xstrdup(margs.ddomain);
365 dp = xstrdup(rfc1738_escape(domain));
366 if (debug_enabled)
367 debug((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM, up, dp);
368 else
369 log((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM, up, dp);
370 }
371 if (debug_enabled)
372 debug((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, up, domain ? dp : "NULL");
373 else
374 log((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, up, domain ? dp : "NULL");
375
376 safe_free(up);
377 safe_free(dp);
378 if (!strcmp(user, "QQ") && domain && !strcmp(domain, "QQ")) {
379 clean_args(&margs);
380 exit(-1);
381 }
382 if (gopt) {
383 if ((group = strtok(NULL, " \n")) != NULL) {
384 debug((char *) "%s| %s: INFO: Read group list %s from stdin\n", LogTime(), PROGRAM, group);
385 rfc1738_unescape(group);
386 if (margs.groups) {
387 clean_gd(margs.groups);
388 margs.groups = NULL;
389 }
390 margs.glist = xstrdup(group);
391 if (create_gd(&margs)) {
392 SEND_ERR("Error in group list");
393 debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL");
394 continue;
395 }
396 } else {
397 SEND_ERR("No group list received on stdin");
398 debug((char *) "%s| %s: FATAL: No group list received on stdin\n", LogTime(), PROGRAM);
399 continue;
400 }
401 }
402 if (check_memberof(&margs, user, domain)) {
403 SEND_OK("");
404 debug((char *) "%s| %s: DEBUG: OK\n", LogTime(), PROGRAM);
405 } else {
406 SEND_ERR("");
407 debug((char *) "%s| %s: DEBUG: ERR\n", LogTime(), PROGRAM);
408 }
409 }
410
411 }
412
413 void
414 strup(char *s)
415 {
416 while (*s) {
417 *s = (char)toupper((unsigned char) *s);
418 ++s;
419 }
420 }
421
422 #else
423 #include <stdio.h>
424 #include <stdlib.h>
425 int
426 main(int argc, char *const argv[])
427 {
428 setbuf(stdout, NULL);
429 setbuf(stdin, NULL);
430 char buf[6400];
431 while (1) {
432 if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
433 }
434 fprintf(stdout, "ERR\n");
435 fprintf(stderr, "LDAP group authorisation not supported\n");
436 }
437 }
438 #endif