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