]> git.ipfire.org Git - thirdparty/squid.git/blob - helpers/external_acl/kerberos_ldap_group/kerberos_ldap_group.cc
merge from parent SslServerCertValidator r12337
[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 "util.h"
35 #include "rfc1738.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 ndstruct *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 if (p->group) {
82 xfree(p->group);
83 p->group = NULL;
84 }
85 if (p->domain) {
86 xfree(p->domain);
87 p->domain = NULL;
88 }
89 if (pp && pp->next) {
90 xfree(pp->next);
91 pp->next = NULL;
92 }
93 if (p == gdsp) {
94 xfree(gdsp);
95 gdsp = NULL;
96 }
97 p = gdsp;
98 }
99 }
100
101 void
102 clean_nd(struct ndstruct *ndsp)
103 {
104 struct ndstruct *p = NULL, *pp = NULL;
105
106 p = ndsp;
107 while (p) {
108 while (p->next) {
109 pp = p;
110 p = p->next;
111 }
112 if (p->netbios) {
113 xfree(p->netbios);
114 p->netbios = NULL;
115 }
116 if (p->domain) {
117 xfree(p->domain);
118 p->domain = NULL;
119 }
120 if (pp && pp->next) {
121 xfree(pp->next);
122 pp->next = NULL;
123 }
124 if (p == ndsp) {
125 xfree(ndsp);
126 ndsp = NULL;
127 }
128 p = ndsp;
129 }
130 }
131
132 void
133 clean_ls(struct lsstruct *lssp)
134 {
135 struct lsstruct *p = NULL, *pp = NULL;
136
137 p = lssp;
138 while (p) {
139 while (p->next) {
140 pp = p;
141 p = p->next;
142 }
143 if (p->lserver) {
144 xfree(p->lserver);
145 p->lserver = NULL;
146 }
147 if (p->domain) {
148 xfree(p->domain);
149 p->domain = NULL;
150 }
151 if (pp && pp->next) {
152 xfree(pp->next);
153 pp->next = NULL;
154 }
155 if (p == lssp) {
156 xfree(lssp);
157 lssp = NULL;
158 }
159 p = lssp;
160 }
161 }
162
163 void
164 clean_args(struct main_args *margs)
165 {
166 if (margs->glist) {
167 xfree(margs->glist);
168 margs->glist = NULL;
169 }
170 if (margs->ulist) {
171 xfree(margs->ulist);
172 margs->ulist = NULL;
173 }
174 if (margs->tlist) {
175 xfree(margs->tlist);
176 margs->tlist = NULL;
177 }
178 if (margs->nlist) {
179 xfree(margs->nlist);
180 margs->nlist = NULL;
181 }
182 if (margs->llist) {
183 xfree(margs->llist);
184 margs->llist = NULL;
185 }
186 if (margs->luser) {
187 xfree(margs->luser);
188 margs->luser = NULL;
189 }
190 if (margs->lpass) {
191 xfree(margs->lpass);
192 margs->lpass = NULL;
193 }
194 if (margs->lbind) {
195 xfree(margs->lbind);
196 margs->lbind = NULL;
197 }
198 if (margs->lurl) {
199 xfree(margs->lurl);
200 margs->lurl = NULL;
201 }
202 if (margs->ssl) {
203 xfree(margs->ssl);
204 margs->ssl = NULL;
205 }
206 if (margs->ddomain) {
207 xfree(margs->ddomain);
208 margs->ddomain = NULL;
209 }
210 if (margs->groups) {
211 clean_gd(margs->groups);
212 margs->groups = NULL;
213 }
214 if (margs->ndoms) {
215 clean_nd(margs->ndoms);
216 margs->ndoms = NULL;
217 }
218 if (margs->lservs) {
219 clean_ls(margs->lservs);
220 margs->lservs = NULL;
221 }
222 }
223
224 void strup(char *s);
225
226 int
227 main(int argc, char *const argv[])
228 {
229 char buf[6400];
230 char *user, *domain, *group;
231 char *up=NULL, *dp=NULL, *np=NULL;
232 char *nuser, *nuser8 = NULL, *netbios;
233 char *c;
234 int opt;
235 struct main_args margs;
236
237 setbuf(stdout, NULL);
238 setbuf(stdin, NULL);
239
240 init_args(&margs);
241
242 while (-1 != (opt = getopt(argc, argv, "diasg:D:N:S:u:U:t:T:p:l:b:m:h"))) {
243 switch (opt) {
244 case 'd':
245 debug_enabled = 1;
246 break;
247 case 'i':
248 log_enabled = 1;
249 break;
250 case 'a':
251 margs.rc_allow = 1;
252 break;
253 case 's':
254 margs.ssl = (char *) "yes";
255 break;
256 case 'g':
257 margs.glist = xstrdup(optarg);
258 break;
259 case 'D':
260 margs.ddomain = xstrdup(optarg);
261 break;
262 case 'N':
263 margs.nlist = xstrdup(optarg);
264 break;
265 case 'u':
266 margs.luser = xstrdup(optarg);
267 break;
268 case 'U':
269 margs.ulist = xstrdup(optarg);
270 break;
271 case 't':
272 margs.ulist = xstrdup(optarg);
273 break;
274 case 'T':
275 margs.tlist = xstrdup(optarg);
276 break;
277 case 'p':
278 margs.lpass = xstrdup(optarg);
279 /* Hide Password */
280 memset(optarg, 'X', strlen(optarg));
281 break;
282 case 'l':
283 margs.lurl = xstrdup(optarg);
284 break;
285 case 'b':
286 margs.lbind = xstrdup(optarg);
287 break;
288 case 'm':
289 margs.mdepth = atoi(optarg);
290 break;
291 case 'S':
292 margs.llist = xstrdup(optarg);
293 break;
294 case 'h':
295 fprintf(stderr, "Usage: \n");
296 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");
297 fprintf(stderr, "-d full debug\n");
298 fprintf(stderr, "-i informational messages\n");
299 fprintf(stderr, "-g group list\n");
300 fprintf(stderr, "-t group list (only group name hex UTF-8 format)\n");
301 fprintf(stderr, "-T group list (all in hex UTF-8 format - except seperator @)\n");
302 fprintf(stderr, "-D default domain\n");
303 fprintf(stderr, "-N netbios to dns domain map\n");
304 fprintf(stderr, "-S ldap server to dns domain map\n");
305 fprintf(stderr, "-u ldap user\n");
306 fprintf(stderr, "-p ldap user password\n");
307 fprintf(stderr, "-l ldap url\n");
308 fprintf(stderr, "-b ldap bind path\n");
309 fprintf(stderr, "-s use SSL encryption with Kerberos authentication\n");
310 fprintf(stderr, "-a allow SSL without cert verification\n");
311 fprintf(stderr, "-m maximal depth for recursive searches\n");
312 fprintf(stderr, "-h help\n");
313 fprintf(stderr, "The ldap url, ldap user and ldap user password details are only used if the kerberised\n");
314 fprintf(stderr, "access fails(e.g. unknown domain) or if the username does not contain a domain part\n");
315 fprintf(stderr, "and no default domain is provided.\n");
316 fprintf(stderr, "If the ldap url starts with ldaps:// it is either start_tls or simple SSL\n");
317 fprintf(stderr, "The group list can be:\n");
318 fprintf(stderr, "group - In this case group can be used for all keberised and non kerberised ldap servers\n");
319 fprintf(stderr, "group@ - In this case group can be used for all keberised ldap servers\n");
320 fprintf(stderr, "group@domain - In this case group can be used for ldap servers of domain domain\n");
321 fprintf(stderr, "group1@domain1:group2@domain2:group3@:group4 - A list is build with a colon as seperator\n");
322 fprintf(stderr, "Group membership is determined with AD servers through the users memberof attribute which\n");
323 fprintf(stderr, "is followed to the top (e.g. if the group is a member of a group)\n");
324 fprintf(stderr, "Group membership is determined with non AD servers through the users memberuid (assuming\n");
325 fprintf(stderr, "PosixGroup) or primary group membership (assuming PosixAccount)\n");
326 fprintf(stderr, "The ldap server list can be:\n");
327 fprintf(stderr, "server - In this case server can be used for all Kerberos domains\n");
328 fprintf(stderr, "server@ - In this case server can be used for all Kerberos domains\n");
329 fprintf(stderr, "server@domain - In this case server can be used for Kerberos domain domain\n");
330 fprintf(stderr, "server1a@domain1:server1b@domain1:server2@domain2:server3@:server4 - A list is build with a colon as seperator\n");
331 clean_args(&margs);
332 exit(0);
333 default:
334 warn((char *) "%s| %s: WARNING: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
335 }
336 }
337
338 debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, KERBEROS_LDAP_GROUP_VERSION);
339 int gopt = 0;
340 if (create_gd(&margs)) {
341 if ( margs.glist != NULL ) {
342 debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL");
343 SEND_ERR("");
344 clean_args(&margs);
345 exit(1);
346 } else {
347 debug((char *) "%s| %s: INFO: no group list given expect it from stdin\n", LogTime(), PROGRAM);
348 gopt = 1;
349 }
350 }
351 if (create_nd(&margs)) {
352 debug((char *) "%s| %s: FATAL: Error in netbios list: %s\n", LogTime(), PROGRAM, margs.nlist ? margs.nlist : "NULL");
353 SEND_ERR("");
354 clean_args(&margs);
355 exit(1);
356 }
357 if (create_ls(&margs)) {
358 debug((char *) "%s| %s: Error in ldap server list: %s\n", LogTime(), PROGRAM, margs.llist ? margs.llist : "NULL");
359 SEND_ERR("");
360 clean_args(&margs);
361 exit(1);
362 }
363 while (1) {
364 if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
365 if (ferror(stdin)) {
366 debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
367 strerror(ferror(stdin)));
368
369 SEND_ERR("");
370 clean_args(&margs);
371 exit(1); /* BIIG buffer */
372 }
373 SEND_ERR("");
374 clean_args(&margs);
375 exit(0);
376 }
377 c = (char *) memchr(buf, '\n', sizeof(buf) - 1);
378 if (c) {
379 *c = '\0';
380 } else {
381 SEND_ERR("Invalid input. CR missing");
382 debug((char *) "%s| %s: ERR\n", LogTime(), PROGRAM);
383 continue;
384 }
385
386 user = strtok(buf, " \n");
387 if (!user) {
388 debug((char *) "%s| %s: INFO: No Username given\n", LogTime(), PROGRAM);
389 SEND_ERR("Invalid request. No Username");
390 continue;
391 }
392 rfc1738_unescape(user);
393 nuser = strchr(user, '\\');
394 if (!nuser)
395 nuser8 = strstr(user, "%5C");
396 if (!nuser && !nuser8)
397 nuser8 = strstr(user, "%5c");
398 domain = strrchr(user, '@');
399 if (nuser || nuser8) {
400 if (nuser) {
401 *nuser = '\0';
402 ++nuser;
403 } else {
404 *nuser8 = '\0';
405 nuser = nuser8 + 3;
406 }
407 netbios = user;
408 up = xstrdup(rfc1738_escape(nuser));
409 np = xstrdup(rfc1738_escape(netbios));
410 if (debug_enabled)
411 debug((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, up, np);
412 else
413 log((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM, up, np);
414 domain = get_netbios_name(&margs, netbios);
415 user = nuser;
416 xfree(up);
417 xfree(np);
418 } else if (domain) {
419 strup(domain);
420 *domain = '\0';
421 ++domain;
422 }
423 up = xstrdup(rfc1738_escape(user));
424 if (domain)
425 dp = xstrdup(rfc1738_escape(domain));
426 if (!domain && margs.ddomain) {
427 domain = xstrdup(margs.ddomain);
428 if (debug_enabled)
429 debug((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM, up, dp);
430 else
431 log((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM, up, dp);
432 }
433 if (debug_enabled)
434 debug((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, up, domain ? dp : "NULL");
435 else
436 log((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM, up, domain ? dp : "NULL");
437
438 xfree(up);
439 xfree(dp);
440 if (!strcmp(user, "QQ") && domain && !strcmp(domain, "QQ")) {
441 clean_args(&margs);
442 exit(-1);
443 }
444 if (gopt) {
445 if ((group = strtok(NULL, " \n")) != NULL) {
446 debug((char *) "%s| %s: INFO: Read group list %s from stdin\n", LogTime(), PROGRAM, group);
447 rfc1738_unescape(group);
448 if (margs.groups) {
449 clean_gd(margs.groups);
450 margs.groups = NULL;
451 }
452 margs.glist = xstrdup(group);
453 if (create_gd(&margs)) {
454 SEND_ERR("Error in group list");
455 debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM, margs.glist ? margs.glist : "NULL");
456 continue;
457 }
458 } else {
459 SEND_ERR("No group list received on stdin");
460 debug((char *) "%s| %s: FATAL: No group list received on stdin\n", LogTime(), PROGRAM);
461 continue;
462 }
463 }
464 if (check_memberof(&margs, user, domain)) {
465 SEND_OK("");
466 debug((char *) "%s| %s: DEBUG: OK\n", LogTime(), PROGRAM);
467 } else {
468 SEND_ERR("");
469 debug((char *) "%s| %s: DEBUG: ERR\n", LogTime(), PROGRAM);
470 }
471 }
472
473 }
474
475 void
476 strup(char *s)
477 {
478 while (*s) {
479 *s = toupper((unsigned char) *s);
480 ++s;
481 }
482 }
483
484 #else
485 #include <stdio.h>
486 #include <stdlib.h>
487 int
488 main(int argc, char *const argv[])
489 {
490 setbuf(stdout, NULL);
491 setbuf(stdin, NULL);
492 char buf[6400];
493 while (1) {
494 if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) {
495 }
496 fprintf(stdout, "ERR\n");
497 fprintf(stderr, "LDAP group authorisation not supported\n");
498 }
499 }
500 #endif