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