2 * -----------------------------------------------------------------------------
4 * Author: Markus Moeller (markus_moeller at compuserve.com)
6 * Copyright (C) 2007 Markus Moeller. All rights reserved.
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.
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.
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.
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.
27 * -----------------------------------------------------------------------------
30 * Hosted at http://sourceforge.net/projects/squidkerbauth
33 #include "helpers/defines.h"
45 init_args(struct main_args
*margs
)
60 margs
->ddomain
= NULL
;
66 void clean_gd(struct gdstruct
*gdsp
);
67 void clean_nd(struct ndstruct
*ndsp
);
68 void clean_ls(struct ndstruct
*lssp
);
71 clean_gd(struct gdstruct
*gdsp
)
73 struct gdstruct
*p
= NULL
, *pp
= NULL
;
102 clean_nd(struct ndstruct
*ndsp
)
104 struct ndstruct
*p
= NULL
, *pp
= NULL
;
120 if (pp
&& pp
->next
) {
133 clean_ls(struct lsstruct
*lssp
)
135 struct lsstruct
*p
= NULL
, *pp
= NULL
;
151 if (pp
&& pp
->next
) {
164 clean_args(struct main_args
*margs
)
206 if (margs
->ddomain
) {
207 xfree(margs
->ddomain
);
208 margs
->ddomain
= NULL
;
211 clean_gd(margs
->groups
);
212 margs
->groups
= NULL
;
215 clean_nd(margs
->ndoms
);
219 clean_ls(margs
->lservs
);
220 margs
->lservs
= NULL
;
227 main(int argc
, char *const argv
[])
230 char *user
, *domain
, *group
;
231 char *up
=NULL
, *dp
=NULL
, *np
=NULL
;
232 char *nuser
, *nuser8
= NULL
, *netbios
;
235 struct main_args margs
;
237 setbuf(stdout
, NULL
);
242 while (-1 != (opt
= getopt(argc
, argv
, "diasg:D:N:S:u:U:t:T:p:l:b:m:h"))) {
254 margs
.ssl
= (char *) "yes";
257 margs
.glist
= xstrdup(optarg
);
260 margs
.ddomain
= xstrdup(optarg
);
263 margs
.nlist
= xstrdup(optarg
);
266 margs
.luser
= xstrdup(optarg
);
269 margs
.ulist
= xstrdup(optarg
);
272 margs
.ulist
= xstrdup(optarg
);
275 margs
.tlist
= xstrdup(optarg
);
278 margs
.lpass
= xstrdup(optarg
);
280 memset(optarg
, 'X', strlen(optarg
));
283 margs
.lurl
= xstrdup(optarg
);
286 margs
.lbind
= xstrdup(optarg
);
289 margs
.mdepth
= atoi(optarg
);
292 margs
.llist
= xstrdup(optarg
);
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");
334 warn((char *) "%s| %s: WARNING: unknown option: -%c.\n", LogTime(), PROGRAM
, opt
);
338 debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM
, KERBEROS_LDAP_GROUP_VERSION
);
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");
347 debug((char *) "%s| %s: INFO: no group list given expect it from stdin\n", LogTime(), PROGRAM
);
351 if (create_nd(&margs
)) {
352 debug((char *) "%s| %s: FATAL: Error in netbios list: %s\n", LogTime(), PROGRAM
, margs
.nlist
? margs
.nlist
: "NULL");
357 if (create_ls(&margs
)) {
358 debug((char *) "%s| %s: Error in ldap server list: %s\n", LogTime(), PROGRAM
, margs
.llist
? margs
.llist
: "NULL");
364 if (fgets(buf
, sizeof(buf
) - 1, stdin
) == NULL
) {
366 debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM
, ferror(stdin
),
367 strerror(ferror(stdin
)));
371 exit(1); /* BIIG buffer */
377 c
= (char *) memchr(buf
, '\n', sizeof(buf
) - 1);
381 SEND_ERR("Invalid input. CR missing");
382 debug((char *) "%s| %s: ERR\n", LogTime(), PROGRAM
);
386 user
= strtok(buf
, " \n");
388 debug((char *) "%s| %s: INFO: No Username given\n", LogTime(), PROGRAM
);
389 SEND_ERR("Invalid request. No Username");
392 rfc1738_unescape(user
);
393 nuser
= strchr(user
, '\\');
395 nuser8
= strstr(user
, "%5C");
396 if (!nuser
&& !nuser8
)
397 nuser8
= strstr(user
, "%5c");
398 domain
= strrchr(user
, '@');
399 if (nuser
|| nuser8
) {
408 up
= xstrdup(rfc1738_escape(nuser
));
409 np
= xstrdup(rfc1738_escape(netbios
));
411 debug((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM
, up
, np
);
413 log((char *) "%s| %s: INFO: Got User: %s Netbios Name: %s\n", LogTime(), PROGRAM
, up
, np
);
414 domain
= get_netbios_name(&margs
, netbios
);
423 up
= xstrdup(rfc1738_escape(user
));
425 dp
= xstrdup(rfc1738_escape(domain
));
426 if (!domain
&& margs
.ddomain
) {
427 domain
= xstrdup(margs
.ddomain
);
428 dp
= xstrdup(rfc1738_escape(domain
));
430 debug((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM
, up
, dp
);
432 log((char *) "%s| %s: INFO: Got User: %s set default domain: %s\n", LogTime(), PROGRAM
, up
, dp
);
435 debug((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM
, up
, domain
? dp
: "NULL");
437 log((char *) "%s| %s: INFO: Got User: %s Domain: %s\n", LogTime(), PROGRAM
, up
, domain
? dp
: "NULL");
441 if (!strcmp(user
, "QQ") && domain
&& !strcmp(domain
, "QQ")) {
446 if ((group
= strtok(NULL
, " \n")) != NULL
) {
447 debug((char *) "%s| %s: INFO: Read group list %s from stdin\n", LogTime(), PROGRAM
, group
);
448 rfc1738_unescape(group
);
450 clean_gd(margs
.groups
);
453 margs
.glist
= xstrdup(group
);
454 if (create_gd(&margs
)) {
455 SEND_ERR("Error in group list");
456 debug((char *) "%s| %s: FATAL: Error in group list: %s\n", LogTime(), PROGRAM
, margs
.glist
? margs
.glist
: "NULL");
460 SEND_ERR("No group list received on stdin");
461 debug((char *) "%s| %s: FATAL: No group list received on stdin\n", LogTime(), PROGRAM
);
465 if (check_memberof(&margs
, user
, domain
)) {
467 debug((char *) "%s| %s: DEBUG: OK\n", LogTime(), PROGRAM
);
470 debug((char *) "%s| %s: DEBUG: ERR\n", LogTime(), PROGRAM
);
480 *s
= toupper((unsigned char) *s
);
489 main(int argc
, char *const argv
[])
491 setbuf(stdout
, NULL
);
495 if (fgets(buf
, sizeof(buf
) - 1, stdin
) == NULL
) {
497 fprintf(stdout
, "ERR\n");
498 fprintf(stderr
, "LDAP group authorisation not supported\n");