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