]>
Commit | Line | Data |
---|---|---|
3e5d7cdf | 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 | * | |
ba4fe07c AJ |
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 | * | |
3e5d7cdf | 27 | * ----------------------------------------------------------------------------- |
28 | */ | |
29 | /* | |
30 | * Hosted at http://sourceforge.net/projects/squidkerbauth | |
31 | */ | |
f7f3304a | 32 | #include "squid.h" |
27bc2077 AJ |
33 | #include "compat/getaddrinfo.h" |
34 | #include "compat/getnameinfo.h" | |
602d9612 | 35 | #include "rfc1738.h" |
d1f95b42 | 36 | |
3ad12bda | 37 | #if HAVE_GSSAPI |
e9658d82 | 38 | |
4ebcf1ce | 39 | #include "negotiate_kerberos.h" |
3e5d7cdf | 40 | |
3ad12bda AJ |
41 | char * |
42 | gethost_name(void) | |
26ac0430 | 43 | { |
e6aa9181 | 44 | /* |
b1218840 AJ |
45 | * char hostname[sysconf(_SC_HOST_NAME_MAX)]; |
46 | */ | |
3d62cc61 | 47 | char hostname[1024]; |
3ad12bda AJ |
48 | struct addrinfo *hres = NULL, *hres_list; |
49 | int rc, count; | |
26ac0430 | 50 | |
bc30ad64 | 51 | rc = gethostname(hostname, sizeof(hostname)-1); |
26ac0430 | 52 | if (rc) { |
2e881a6f A |
53 | fprintf(stderr, "%s| %s: ERROR: resolving hostname '%s' failed\n", |
54 | LogTime(), PROGRAM, hostname); | |
55 | return NULL; | |
26ac0430 | 56 | } |
27bc2077 | 57 | rc = getaddrinfo(hostname, NULL, NULL, &hres); |
26ac0430 | 58 | if (rc != 0) { |
2e881a6f A |
59 | fprintf(stderr, |
60 | "%s| %s: ERROR: resolving hostname with getaddrinfo: %s failed\n", | |
61 | LogTime(), PROGRAM, gai_strerror(rc)); | |
62 | return NULL; | |
26ac0430 | 63 | } |
3ad12bda AJ |
64 | hres_list = hres; |
65 | count = 0; | |
26ac0430 | 66 | while (hres_list) { |
755494da | 67 | ++count; |
2e881a6f | 68 | hres_list = hres_list->ai_next; |
26ac0430 | 69 | } |
27bc2077 | 70 | rc = getnameinfo(hres->ai_addr, hres->ai_addrlen, hostname, |
2e881a6f | 71 | sizeof(hostname), NULL, 0, 0); |
26ac0430 | 72 | if (rc != 0) { |
2e881a6f A |
73 | fprintf(stderr, |
74 | "%s| %s: ERROR: resolving ip address with getnameinfo: %s failed\n", | |
75 | LogTime(), PROGRAM, gai_strerror(rc)); | |
76 | freeaddrinfo(hres); | |
77 | return NULL; | |
3e5d7cdf | 78 | } |
27bc2077 | 79 | freeaddrinfo(hres); |
bc30ad64 | 80 | hostname[sizeof(hostname)-1] = '\0'; |
3ad12bda | 81 | return (xstrdup(hostname)); |
3e5d7cdf | 82 | } |
83 | ||
3ad12bda AJ |
84 | int |
85 | check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, | |
4ebcf1ce | 86 | const char *function, int log, int sout) |
26ac0430 AJ |
87 | { |
88 | if (GSS_ERROR(major_status)) { | |
2e881a6f A |
89 | OM_uint32 maj_stat, min_stat; |
90 | OM_uint32 msg_ctx = 0; | |
91 | gss_buffer_desc status_string; | |
92 | char buf[1024]; | |
93 | size_t len; | |
94 | ||
95 | len = 0; | |
96 | msg_ctx = 0; | |
08885c7f | 97 | do { |
2e881a6f A |
98 | /* convert major status code (GSS-API error) to text */ |
99 | maj_stat = gss_display_status(&min_stat, major_status, | |
100 | GSS_C_GSS_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); | |
08885c7f | 101 | if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) { |
2e881a6f A |
102 | if (sizeof(buf) > len + status_string.length + 1) { |
103 | snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value); | |
104 | len += status_string.length; | |
105 | } | |
08885c7f MM |
106 | } else |
107 | msg_ctx = 0; | |
2e881a6f | 108 | gss_release_buffer(&min_stat, &status_string); |
08885c7f | 109 | } while (msg_ctx); |
2e881a6f A |
110 | if (sizeof(buf) > len + 2) { |
111 | snprintf(buf + len, (sizeof(buf) - len), "%s", ". "); | |
112 | len += 2; | |
113 | } | |
114 | msg_ctx = 0; | |
08885c7f | 115 | do { |
2e881a6f A |
116 | /* convert minor status code (underlying routine error) to text */ |
117 | maj_stat = gss_display_status(&min_stat, minor_status, | |
118 | GSS_C_MECH_CODE, GSS_C_NULL_OID, &msg_ctx, &status_string); | |
08885c7f | 119 | if (maj_stat == GSS_S_COMPLETE && status_string.length > 0) { |
2e881a6f A |
120 | if (sizeof(buf) > len + status_string.length) { |
121 | snprintf(buf + len, (sizeof(buf) - len), "%s", (char *) status_string.value); | |
122 | len += status_string.length; | |
123 | } | |
08885c7f MM |
124 | } else |
125 | msg_ctx = 0; | |
2e881a6f | 126 | gss_release_buffer(&min_stat, &status_string); |
08885c7f | 127 | } while (msg_ctx); |
2e881a6f | 128 | debug((char *) "%s| %s: ERROR: %s failed: %s\n", LogTime(), PROGRAM, function, buf); |
4ebcf1ce MM |
129 | if (sout) |
130 | fprintf(stdout, "BH %s failed: %s\n", function, buf); | |
2e881a6f A |
131 | if (log) |
132 | fprintf(stderr, "%s| %s: INFO: User not authenticated\n", LogTime(), | |
133 | PROGRAM); | |
134 | return (1); | |
3e5d7cdf | 135 | } |
3ad12bda | 136 | return (0); |
3e5d7cdf | 137 | } |
138 | ||
3ad12bda AJ |
139 | int |
140 | main(int argc, char *const argv[]) | |
3e5d7cdf | 141 | { |
26ac0430 | 142 | char buf[MAX_AUTHTOKEN_LEN]; |
3ad12bda AJ |
143 | char *c, *p; |
144 | char *user = NULL; | |
4ebcf1ce MM |
145 | char *rfc_user = NULL; |
146 | #if HAVE_PAC_SUPPORT | |
147 | char ad_groups[MAX_PAC_GROUP_SIZE]; | |
148 | char *ag=NULL; | |
149 | krb5_context context = NULL; | |
150 | krb5_error_code ret; | |
151 | krb5_pac pac; | |
1a22a39e | 152 | #if USE_HEIMDAL_KRB5 |
4ebcf1ce MM |
153 | gss_buffer_desc data_set = GSS_C_EMPTY_BUFFER; |
154 | #else | |
155 | gss_buffer_desc type_id = GSS_C_EMPTY_BUFFER; | |
156 | #endif | |
157 | #endif | |
158 | long length = 0; | |
3ad12bda | 159 | static int err = 0; |
e673ba3a | 160 | int opt, log = 0, norealm = 0; |
3ad12bda AJ |
161 | OM_uint32 ret_flags = 0, spnego_flag = 0; |
162 | char *service_name = (char *) "HTTP", *host_name = NULL; | |
26ac0430 AJ |
163 | char *token = NULL; |
164 | char *service_principal = NULL; | |
165 | OM_uint32 major_status, minor_status; | |
3ad12bda AJ |
166 | gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT; |
167 | gss_name_t client_name = GSS_C_NO_NAME; | |
168 | gss_name_t server_name = GSS_C_NO_NAME; | |
169 | gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL; | |
170 | gss_buffer_desc service = GSS_C_EMPTY_BUFFER; | |
171 | gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER; | |
172 | gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER; | |
173 | const unsigned char *kerberosToken = NULL; | |
3ad12bda AJ |
174 | const unsigned char *spnegoToken = NULL; |
175 | size_t spnegoTokenLength = 0; | |
26ac0430 | 176 | |
3ad12bda AJ |
177 | setbuf(stdout, NULL); |
178 | setbuf(stdin, NULL); | |
26ac0430 | 179 | |
6989c6dc | 180 | while (-1 != (opt = getopt(argc, argv, "dirs:h"))) { |
2e881a6f A |
181 | switch (opt) { |
182 | case 'd': | |
183 | debug_enabled = 1; | |
184 | break; | |
185 | case 'i': | |
186 | log = 1; | |
187 | break; | |
188 | case 'r': | |
189 | norealm = 1; | |
190 | break; | |
191 | case 's': | |
192 | service_principal = xstrdup(optarg); | |
193 | break; | |
194 | case 'h': | |
195 | fprintf(stderr, "Usage: \n"); | |
196 | fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n"); | |
197 | fprintf(stderr, "-d full debug\n"); | |
198 | fprintf(stderr, "-i informational messages\n"); | |
199 | fprintf(stderr, "-r remove realm from username\n"); | |
200 | fprintf(stderr, "-s service principal name\n"); | |
201 | fprintf(stderr, "-h help\n"); | |
202 | fprintf(stderr, | |
203 | "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n"); | |
204 | fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n"); | |
205 | exit(0); | |
206 | default: | |
207 | fprintf(stderr, "%s| %s: WARNING: unknown option: -%c.\n", LogTime(), | |
208 | PROGRAM, opt); | |
209 | } | |
3e5d7cdf | 210 | } |
211 | ||
b1218840 | 212 | debug((char *) "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, SQUID_KERB_AUTH_VERSION); |
3ad12bda | 213 | if (service_principal && strcasecmp(service_principal, "GSS_C_NO_NAME")) { |
2e881a6f A |
214 | service.value = service_principal; |
215 | service.length = strlen((char *) service.value); | |
26ac0430 | 216 | } else { |
2e881a6f A |
217 | host_name = gethost_name(); |
218 | if (!host_name) { | |
219 | fprintf(stderr, | |
220 | "%s| %s: FATAL: Local hostname could not be determined. Please specify the service principal\n", | |
221 | LogTime(), PROGRAM); | |
222 | fprintf(stdout, "BH hostname error\n"); | |
223 | exit(-1); | |
224 | } | |
225 | service.value = xmalloc(strlen(service_name) + strlen(host_name) + 2); | |
226 | snprintf((char *) service.value, strlen(service_name) + strlen(host_name) + 2, | |
227 | "%s@%s", service_name, host_name); | |
228 | service.length = strlen((char *) service.value); | |
4ebcf1ce | 229 | xfree(host_name); |
3e5d7cdf | 230 | } |
231 | ||
26ac0430 | 232 | while (1) { |
2e881a6f A |
233 | if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) { |
234 | if (ferror(stdin)) { | |
235 | debug((char *) "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n", | |
236 | LogTime(), PROGRAM, ferror(stdin), | |
237 | strerror(ferror(stdin))); | |
238 | ||
239 | fprintf(stdout, "BH input error\n"); | |
240 | exit(1); /* BIIG buffer */ | |
241 | } | |
242 | fprintf(stdout, "BH input error\n"); | |
243 | exit(0); | |
244 | } | |
245 | c = (char *) memchr(buf, '\n', sizeof(buf) - 1); | |
246 | if (c) { | |
247 | *c = '\0'; | |
248 | length = c - buf; | |
249 | } else { | |
250 | err = 1; | |
251 | } | |
252 | if (err) { | |
253 | debug((char *) "%s| %s: ERROR: Oversized message\n", LogTime(), PROGRAM); | |
254 | fprintf(stdout, "BH Oversized message\n"); | |
255 | err = 0; | |
256 | continue; | |
257 | } | |
4ebcf1ce | 258 | debug((char *) "%s| %s: DEBUG: Got '%s' from squid (length: %ld).\n", LogTime(), PROGRAM, buf, length); |
2e881a6f A |
259 | |
260 | if (buf[0] == '\0') { | |
261 | debug((char *) "%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM); | |
262 | fprintf(stdout, "BH Invalid request\n"); | |
263 | continue; | |
264 | } | |
265 | if (strlen(buf) < 2) { | |
266 | debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf); | |
267 | fprintf(stdout, "BH Invalid request\n"); | |
268 | continue; | |
269 | } | |
270 | if (!strncmp(buf, "QQ", 2)) { | |
271 | gss_release_buffer(&minor_status, &input_token); | |
272 | gss_release_buffer(&minor_status, &output_token); | |
273 | gss_release_buffer(&minor_status, &service); | |
274 | gss_release_cred(&minor_status, &server_creds); | |
275 | if (server_name) | |
276 | gss_release_name(&minor_status, &server_name); | |
277 | if (client_name) | |
278 | gss_release_name(&minor_status, &client_name); | |
279 | if (gss_context != GSS_C_NO_CONTEXT) | |
280 | gss_delete_sec_context(&minor_status, &gss_context, NULL); | |
281 | if (kerberosToken) { | |
282 | /* Allocated by parseNegTokenInit, but no matching free function exists.. */ | |
283 | if (!spnego_flag) | |
4ebcf1ce | 284 | xfree(kerberosToken); |
2e881a6f A |
285 | } |
286 | if (spnego_flag) { | |
287 | /* Allocated by makeNegTokenTarg, but no matching free function exists.. */ | |
4ebcf1ce | 288 | xfree(spnegoToken); |
2e881a6f | 289 | } |
4ebcf1ce | 290 | xfree(token); |
2e881a6f A |
291 | fprintf(stdout, "BH quit command\n"); |
292 | exit(0); | |
293 | } | |
294 | if (strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2)) { | |
295 | debug((char *) "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf); | |
296 | fprintf(stdout, "BH Invalid request\n"); | |
297 | continue; | |
298 | } | |
299 | if (!strncmp(buf, "YR", 2)) { | |
300 | if (gss_context != GSS_C_NO_CONTEXT) | |
301 | gss_delete_sec_context(&minor_status, &gss_context, NULL); | |
302 | gss_context = GSS_C_NO_CONTEXT; | |
303 | } | |
304 | if (strlen(buf) <= 3) { | |
305 | debug((char *) "%s| %s: ERROR: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf); | |
306 | fprintf(stdout, "BH Invalid negotiate request\n"); | |
307 | continue; | |
308 | } | |
4ebcf1ce | 309 | input_token.length = (size_t)base64_decode_len(buf+3); |
2e881a6f A |
310 | debug((char *) "%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n", |
311 | LogTime(), PROGRAM, buf + 3, (int) input_token.length); | |
312 | input_token.value = xmalloc(input_token.length); | |
313 | ||
4ebcf1ce | 314 | input_token.length = (size_t)base64_decode((char *) input_token.value, (unsigned int)input_token.length, buf+3); |
2e881a6f A |
315 | |
316 | if ((input_token.length >= sizeof ntlmProtocol + 1) && | |
317 | (!memcmp(input_token.value, ntlmProtocol, sizeof ntlmProtocol))) { | |
318 | debug((char *) "%s| %s: WARNING: received type %d NTLM token\n", | |
319 | LogTime(), PROGRAM, | |
320 | (int) *((unsigned char *) input_token.value + | |
321 | sizeof ntlmProtocol)); | |
322 | fprintf(stdout, "BH received type %d NTLM token\n", | |
323 | (int) *((unsigned char *) input_token.value + | |
324 | sizeof ntlmProtocol)); | |
325 | goto cleanup; | |
326 | } | |
327 | if (service_principal) { | |
328 | if (strcasecmp(service_principal, "GSS_C_NO_NAME")) { | |
329 | major_status = gss_import_name(&minor_status, &service, | |
330 | (gss_OID) GSS_C_NULL_OID, &server_name); | |
331 | ||
332 | } else { | |
333 | server_name = GSS_C_NO_NAME; | |
334 | major_status = GSS_S_COMPLETE; | |
4ebcf1ce | 335 | minor_status = 0; |
2e881a6f A |
336 | } |
337 | } else { | |
338 | major_status = gss_import_name(&minor_status, &service, | |
339 | gss_nt_service_name, &server_name); | |
340 | } | |
341 | ||
4ebcf1ce | 342 | if (check_gss_err(major_status, minor_status, "gss_import_name()", log, 1)) |
2e881a6f A |
343 | goto cleanup; |
344 | ||
345 | major_status = | |
346 | gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE, | |
347 | GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds, NULL, NULL); | |
4ebcf1ce | 348 | if (check_gss_err(major_status, minor_status, "gss_acquire_cred()", log, 1)) |
2e881a6f A |
349 | goto cleanup; |
350 | ||
351 | major_status = gss_accept_sec_context(&minor_status, | |
352 | &gss_context, | |
353 | server_creds, | |
354 | &input_token, | |
355 | GSS_C_NO_CHANNEL_BINDINGS, | |
356 | &client_name, NULL, &output_token, &ret_flags, NULL, NULL); | |
357 | ||
2e881a6f A |
358 | if (output_token.length) { |
359 | spnegoToken = (const unsigned char *) output_token.value; | |
360 | spnegoTokenLength = output_token.length; | |
4ebcf1ce | 361 | token = (char *) xmalloc((size_t)base64_encode_len((int)spnegoTokenLength)); |
2e881a6f A |
362 | if (token == NULL) { |
363 | debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM); | |
364 | fprintf(stdout, "BH Not enough memory\n"); | |
365 | goto cleanup; | |
366 | } | |
4ebcf1ce MM |
367 | base64_encode_str(token, base64_encode_len((int)spnegoTokenLength), |
368 | (const char *) spnegoToken, (int)spnegoTokenLength); | |
2e881a6f | 369 | |
4ebcf1ce | 370 | if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1)) |
2e881a6f A |
371 | goto cleanup; |
372 | if (major_status & GSS_S_CONTINUE_NEEDED) { | |
373 | debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM); | |
374 | fprintf(stdout, "TT %s\n", token); | |
375 | goto cleanup; | |
376 | } | |
377 | gss_release_buffer(&minor_status, &output_token); | |
378 | major_status = | |
379 | gss_display_name(&minor_status, client_name, &output_token, | |
380 | NULL); | |
381 | ||
4ebcf1ce | 382 | if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1)) |
2e881a6f A |
383 | goto cleanup; |
384 | user = (char *) xmalloc(output_token.length + 1); | |
385 | if (user == NULL) { | |
386 | debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM); | |
387 | fprintf(stdout, "BH Not enough memory\n"); | |
388 | goto cleanup; | |
389 | } | |
390 | memcpy(user, output_token.value, output_token.length); | |
391 | user[output_token.length] = '\0'; | |
392 | if (norealm && (p = strchr(user, '@')) != NULL) { | |
393 | *p = '\0'; | |
394 | } | |
4ebcf1ce MM |
395 | |
396 | #if HAVE_PAC_SUPPORT | |
397 | ret = krb5_init_context(&context); | |
398 | if (!check_k5_err(context, "krb5_init_context", ret)) { | |
1a22a39e | 399 | #if USE_HEIMDAL_KRB5 |
4ebcf1ce MM |
400 | #define ADWIN2KPAC 128 |
401 | major_status = gsskrb5_extract_authz_data_from_sec_context(&minor_status, | |
402 | gss_context, ADWIN2KPAC, &data_set); | |
403 | if (!check_gss_err(major_status, minor_status, | |
404 | "gsskrb5_extract_authz_data_from_sec_context()", log, 0)) { | |
405 | ret = krb5_pac_parse(context, data_set.value, data_set.length, &pac); | |
406 | gss_release_buffer(&minor_status, &data_set); | |
407 | if (!check_k5_err(context, "krb5_pac_parse", ret)) { | |
408 | ag = get_ad_groups((char *)&ad_groups, context, pac); | |
409 | krb5_pac_free(context, pac); | |
410 | } | |
411 | krb5_free_context(context); | |
412 | } | |
413 | #else | |
414 | type_id.value = (void *)"mspac"; | |
415 | type_id.length = strlen((char *)type_id.value); | |
416 | #define KRB5PACLOGONINFO 1 | |
417 | major_status = gss_map_name_to_any(&minor_status, client_name, KRB5PACLOGONINFO, &type_id, (gss_any_t *)&pac); | |
418 | if (!check_gss_err(major_status, minor_status, "gss_map_name_to_any()", log, 0)) { | |
419 | ag = get_ad_groups((char *)&ad_groups,context, pac); | |
420 | } | |
421 | (void)gss_release_any_name_mapping(&minor_status, client_name, &type_id, (gss_any_t *)&pac); | |
422 | krb5_free_context(context); | |
423 | #endif | |
424 | } | |
425 | if (ag) { | |
426 | debug((char *) "%s| %s: DEBUG: Groups %s\n", LogTime(), PROGRAM, ag); | |
427 | } | |
428 | #endif | |
2e881a6f | 429 | fprintf(stdout, "AF %s %s\n", token, user); |
4ebcf1ce MM |
430 | rfc_user = rfc1738_escape(user); |
431 | debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token, rfc_user); | |
2e881a6f A |
432 | if (log) |
433 | fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(), | |
8288b253 | 434 | PROGRAM, rfc1738_escape(user)); |
2e881a6f A |
435 | goto cleanup; |
436 | } else { | |
4ebcf1ce | 437 | if (check_gss_err(major_status, minor_status, "gss_accept_sec_context()", log, 1)) |
2e881a6f A |
438 | goto cleanup; |
439 | if (major_status & GSS_S_CONTINUE_NEEDED) { | |
440 | debug((char *) "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM); | |
441 | fprintf(stdout, "NA %s\n", token); | |
442 | goto cleanup; | |
443 | } | |
444 | gss_release_buffer(&minor_status, &output_token); | |
445 | major_status = | |
446 | gss_display_name(&minor_status, client_name, &output_token, | |
447 | NULL); | |
448 | ||
4ebcf1ce | 449 | if (check_gss_err(major_status, minor_status, "gss_display_name()", log, 1)) |
2e881a6f A |
450 | goto cleanup; |
451 | /* | |
452 | * Return dummy token AA. May need an extra return tag then AF | |
453 | */ | |
454 | user = (char *) xmalloc(output_token.length + 1); | |
455 | if (user == NULL) { | |
456 | debug((char *) "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM); | |
457 | fprintf(stdout, "BH Not enough memory\n"); | |
458 | goto cleanup; | |
459 | } | |
460 | memcpy(user, output_token.value, output_token.length); | |
461 | user[output_token.length] = '\0'; | |
462 | if (norealm && (p = strchr(user, '@')) != NULL) { | |
463 | *p = '\0'; | |
464 | } | |
465 | fprintf(stdout, "AF %s %s\n", "AA==", user); | |
8288b253 | 466 | debug((char *) "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", rfc1738_escape(user)); |
2e881a6f A |
467 | if (log) |
468 | fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(), | |
8288b253 | 469 | PROGRAM, rfc1738_escape(user)); |
2e881a6f A |
470 | |
471 | } | |
472 | cleanup: | |
473 | gss_release_buffer(&minor_status, &input_token); | |
474 | gss_release_buffer(&minor_status, &output_token); | |
475 | gss_release_cred(&minor_status, &server_creds); | |
476 | if (server_name) | |
477 | gss_release_name(&minor_status, &server_name); | |
478 | if (client_name) | |
479 | gss_release_name(&minor_status, &client_name); | |
480 | if (kerberosToken) { | |
481 | /* Allocated by parseNegTokenInit, but no matching free function exists.. */ | |
482 | if (!spnego_flag) | |
4ebcf1ce | 483 | safe_free(kerberosToken); |
2e881a6f A |
484 | } |
485 | if (spnego_flag) { | |
486 | /* Allocated by makeNegTokenTarg, but no matching free function exists.. */ | |
4ebcf1ce | 487 | safe_free(spnegoToken); |
2e881a6f | 488 | } |
4ebcf1ce MM |
489 | safe_free(token); |
490 | safe_free(user); | |
2e881a6f | 491 | continue; |
3e5d7cdf | 492 | } |
3e5d7cdf | 493 | } |
6989c6dc | 494 | #else |
074d6a40 | 495 | #include <cstdlib> |
6989c6dc AJ |
496 | #ifndef MAX_AUTHTOKEN_LEN |
497 | #define MAX_AUTHTOKEN_LEN 65535 | |
498 | #endif | |
499 | int | |
500 | main(int argc, char *const argv[]) | |
501 | { | |
502 | setbuf(stdout, NULL); | |
503 | setbuf(stdin, NULL); | |
504 | char buf[MAX_AUTHTOKEN_LEN]; | |
505 | while (1) { | |
2e881a6f A |
506 | if (fgets(buf, sizeof(buf) - 1, stdin) == NULL) { |
507 | fprintf(stdout, "BH input error\n"); | |
508 | exit(0); | |
509 | } | |
510 | fprintf(stdout, "BH Kerberos authentication not supported\n"); | |
6989c6dc AJ |
511 | } |
512 | } | |
3ad12bda | 513 | #endif /* HAVE_GSSAPI */ |