]> git.ipfire.org Git - thirdparty/squid.git/blame - helpers/negotiate_auth/squid_kerb_auth/squid_kerb_auth.c
Updates for running on squid-cache.org
[thirdparty/squid.git] / helpers / negotiate_auth / squid_kerb_auth / squid_kerb_auth.c
CommitLineData
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 */
32#include <string.h>
33#include <stdio.h>
34#include <stdlib.h>
35#include <netdb.h>
36#include <unistd.h>
37#include <time.h>
38#include <sys/time.h>
39
ba4fe07c
AJ
40#include "config.h"
41
42#ifdef HAVE_SQUID
43#ifdef PACKAGE
44#undef PACKAGE
45#endif
46#ifdef PACKAGE_BUGREPORT
47#undef PACKAGE_BUGREPORT
48#endif
49#ifdef PACKAGE_NAME
50#undef PACKAGE_NAME
51#endif
52#ifdef PACKAGE_STRING
53#undef PACKAGE_STRING
54#endif
55#ifdef PACKAGE_TARNAME
56#undef PACKAGE_TARNAME
57#endif
58#ifdef PACKAGE_VERSION
59#undef PACKAGE_VERSION
60#endif
61#ifdef VERSION
62#undef VERSION
63#endif
64#ifdef HAVE_GETADDRINFO_H
102728eb 65#include "getaddrinfo.h"
ba4fe07c
AJ
66#endif
67#ifdef HAVE_GETNAMEINFO_H
102728eb 68#include "getnameinfo.h"
ba4fe07c
AJ
69#endif
70#ifdef HAVE_UTIL_H
71#include "util.h"
72#endif
73#ifdef PACKAGE
74#undef PACKAGE
75#endif
76#ifdef PACKAGE_BUGREPORT
77#undef PACKAGE_BUGREPORT
78#endif
79#ifdef PACKAGE_NAME
80#undef PACKAGE_NAME
81#endif
82#ifdef PACKAGE_STRING
83#undef PACKAGE_STRING
84#endif
85#ifdef PACKAGE_TARNAME
86#undef PACKAGE_TARNAME
87#endif
88#ifdef PACKAGE_VERSION
89#undef PACKAGE_VERSION
90#endif
91#ifdef VERSION
92#undef VERSION
93#endif
94/*
95 * Reset varibles
96 */
97#include "config.h"
98#endif
99#if !defined(HAVE_DECL_XGETADDRINFO) || !HAVE_DECL_XGETADDRINFO
100#define xgetaddrinfo getaddrinfo
101#endif
102#if !defined(HAVE_DECL_XFREEADDRINFO) || !HAVE_DECL_XFREEADDRINFO
103#define xfreeaddrinfo freeaddrinfo
104#endif
105#if !defined(HAVE_DECL_XGAI_STRERROR) || !HAVE_DECL_XGAI_STRERROR
106#define xgai_strerror gai_strerror
107#endif
108#if !defined(HAVE_DECL_XGETNAMEINFO) || !HAVE_DECL_XGETNAMEINFO
109#define xgetnameinfo getnameinfo
110#endif
111#if !defined(HAVE_DECL_XMALLOC) || !HAVE_DECL_XMALLOC
112#define xmalloc malloc
113#endif
114#if !defined(HAVE_DECL_XSTRDUP) || !HAVE_DECL_XSTRDUP
115#define xstrdup strdup
116#endif
117#if !defined(HAVE_DECL_XFREE) || !HAVE_DECL_XFREE
118#define xfree free
119#endif
102728eb 120
3e5d7cdf 121#include "base64.h"
122#ifndef HAVE_SPNEGO
123#include "spnegohelp.h"
124#endif
125
3e5d7cdf 126#define PROGRAM "squid_kerb_auth"
127
ba4fe07c
AJ
128
129#ifndef MAX_AUTHTOKEN_LEN
130#define MAX_AUTHTOKEN_LEN 65535
3e5d7cdf 131#endif
132
ba4fe07c 133int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log);
3e5d7cdf 134char *gethost_name(void);
135static const char *LogTime(void);
136
137static const unsigned char ntlmProtocol [] = {'N', 'T', 'L', 'M', 'S', 'S', 'P', 0};
138
139static const char *LogTime()
140{
141 struct tm *tm;
142 struct timeval now;
143 static time_t last_t = 0;
144 static char buf[128];
145
146 gettimeofday(&now, NULL);
147 if (now.tv_sec != last_t) {
ba4fe07c 148 tm = localtime((time_t *)&now.tv_sec);
3e5d7cdf 149 strftime(buf, 127, "%Y/%m/%d %H:%M:%S", tm);
150 last_t = now.tv_sec;
151 }
152 return buf;
153}
154
155char *gethost_name(void) {
ba4fe07c 156 char hostname[sysconf(_SC_HOST_NAME_MAX)];
3e5d7cdf 157 struct addrinfo *hres=NULL, *hres_list;
158 int rc,count;
159
ba4fe07c 160 rc = gethostname(hostname,sysconf(_SC_HOST_NAME_MAX));
3e5d7cdf 161 if (rc)
162 {
163 fprintf(stderr, "%s| %s: error while resolving hostname '%s'\n", LogTime(), PROGRAM, hostname);
164 return NULL;
165 }
cc192b50 166 rc = xgetaddrinfo(hostname,NULL,NULL,&hres);
3e5d7cdf 167 if (rc != 0) {
cc192b50 168 fprintf(stderr, "%s| %s: error while resolving hostname with getaddrinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc));
3e5d7cdf 169 return NULL;
170 }
171 hres_list=hres;
172 count=0;
173 while (hres_list) {
174 count++;
175 hres_list=hres_list->ai_next;
176 }
ba4fe07c 177 rc = xgetnameinfo (hres->ai_addr, hres->ai_addrlen,hostname, sizeof (hostname), NULL, 0, 0);
3e5d7cdf 178 if (rc != 0) {
cc192b50 179 fprintf(stderr, "%s| %s: error while resolving ip address with getnameinfo: %s\n", LogTime(), PROGRAM, xgai_strerror(rc));
180 xfreeaddrinfo(hres);
3e5d7cdf 181 return NULL ;
182 }
183
cc192b50 184 xfreeaddrinfo(hres);
ba4fe07c
AJ
185 hostname[sysconf(_SC_HOST_NAME_MAX)-1]='\0';
186 return(xstrdup(hostname));
3e5d7cdf 187}
188
ba4fe07c 189int check_gss_err(OM_uint32 major_status, OM_uint32 minor_status, const char* function, int debug, int log) {
3e5d7cdf 190 if (GSS_ERROR(major_status)) {
191 OM_uint32 maj_stat,min_stat;
192 OM_uint32 msg_ctx = 0;
193 gss_buffer_desc status_string;
194 char buf[1024];
195 size_t len;
196
197 len = 0;
198 msg_ctx = 0;
199 while (!msg_ctx) {
200 /* convert major status code (GSS-API error) to text */
201 maj_stat = gss_display_status(&min_stat, major_status,
202 GSS_C_GSS_CODE,
203 GSS_C_NULL_OID,
204 &msg_ctx, &status_string);
205 if (maj_stat == GSS_S_COMPLETE) {
206 if (sizeof(buf) > len + status_string.length + 1) {
207 sprintf(buf+len, "%s", (char*) status_string.value);
208 len += status_string.length;
209 }
210 gss_release_buffer(&min_stat, &status_string);
211 break;
212 }
213 gss_release_buffer(&min_stat, &status_string);
214 }
215 if (sizeof(buf) > len + 2) {
216 sprintf(buf+len, "%s", ". ");
217 len += 2;
218 }
219 msg_ctx = 0;
220 while (!msg_ctx) {
221 /* convert minor status code (underlying routine error) to text */
222 maj_stat = gss_display_status(&min_stat, minor_status,
223 GSS_C_MECH_CODE,
224 GSS_C_NULL_OID,
225 &msg_ctx, &status_string);
226 if (maj_stat == GSS_S_COMPLETE) {
227 if (sizeof(buf) > len + status_string.length ) {
228 sprintf(buf+len, "%s", (char*) status_string.value);
229 len += status_string.length;
230 }
231 gss_release_buffer(&min_stat, &status_string);
232 break;
233 }
234 gss_release_buffer(&min_stat, &status_string);
235 }
ba4fe07c 236 if (debug)
3e5d7cdf 237 fprintf(stderr, "%s| %s: %s failed: %s\n", LogTime(), PROGRAM, function, buf);
ba4fe07c
AJ
238 fprintf(stdout, "BH %s failed: %s\n",function, buf);
239 if (log)
3e5d7cdf 240 fprintf(stderr, "%s| %s: User not authenticated\n", LogTime(), PROGRAM);
241 return(1);
242 }
243 return(0);
244}
245
ba4fe07c
AJ
246
247
3e5d7cdf 248int main(int argc, char * const argv[])
249{
94fd8c3a 250 char buf[MAX_AUTHTOKEN_LEN];
3e5d7cdf 251 char *c;
252 int length=0;
253 static int err=0;
ba4fe07c
AJ
254 int opt, debug=0, log=0;
255#ifndef HAVE_SPNEGO
256 int rc;
257#endif
3e5d7cdf 258 OM_uint32 ret_flags=0, spnego_flag=0;
259 char *service_name=(char *)"HTTP",*host_name=NULL;
260 char *token = NULL;
261 char *service_principal = NULL;
262 OM_uint32 major_status, minor_status;
263 gss_ctx_id_t gss_context = GSS_C_NO_CONTEXT;
264 gss_name_t client_name = GSS_C_NO_NAME;
265 gss_name_t server_name = GSS_C_NO_NAME;
266 gss_cred_id_t server_creds = GSS_C_NO_CREDENTIAL;
3e5d7cdf 267 gss_buffer_desc service = GSS_C_EMPTY_BUFFER;
268 gss_buffer_desc input_token = GSS_C_EMPTY_BUFFER;
269 gss_buffer_desc output_token = GSS_C_EMPTY_BUFFER;
270 const unsigned char *kerberosToken = NULL;
ba4fe07c 271#ifndef HAVE_SPNEGO
3e5d7cdf 272 size_t kerberosTokenLength = 0;
ba4fe07c 273#endif
3e5d7cdf 274 const unsigned char *spnegoToken = NULL ;
275 size_t spnegoTokenLength = 0;
276
277 setbuf(stdout,NULL);
278 setbuf(stdin,NULL);
279
280 while (-1 != (opt = getopt(argc, argv, "dis:h"))) {
281 switch (opt) {
282 case 'd':
283 debug = 1;
284 break;
285 case 'i':
ba4fe07c 286 log = 1;
3e5d7cdf 287 break;
288 case 's':
ba4fe07c 289 service_principal = xstrdup(optarg);
3e5d7cdf 290 break;
291 case 'h':
ba4fe07c
AJ
292 fprintf(stderr, "Usage: \n");
293 fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n");
294 fprintf(stderr, "-d full debug\n");
295 fprintf(stderr, "-i informational messages\n");
296 fprintf(stderr, "-s service principal name\n");
297 fprintf(stderr, "-h help\n");
298 fprintf(stderr, "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
299 fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
300 exit(0);
3e5d7cdf 301 default:
302 fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
303 }
304 }
305
ba4fe07c
AJ
306 if (debug)
307 fprintf(stderr, "%s| %s: Starting version %s\n", LogTime(), PROGRAM, VERSION);
3e5d7cdf 308 if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
309 service.value = service_principal;
310 service.length = strlen((char *)service.value);
311 } else {
312 host_name=gethost_name();
313 if ( !host_name ) {
314 fprintf(stderr, "%s| %s: Local hostname could not be determined. Please specify the service principal\n", LogTime(), PROGRAM);
ba4fe07c 315 fprintf(stdout, "BH hostname error\n");
3e5d7cdf 316 exit(-1);
317 }
ba4fe07c 318 service.value = xmalloc(strlen(service_name)+strlen(host_name)+2);
3e5d7cdf 319 snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name);
320 service.length = strlen((char *)service.value);
321 }
322
323 while (1) {
324 if (fgets(buf, sizeof(buf)-1, stdin) == NULL) {
325 if (ferror(stdin)) {
326 if (debug)
327 fprintf(stderr, "%s| %s: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
328 strerror(ferror(stdin)));
329
ba4fe07c 330 fprintf(stdout, "BH input error\n");
3e5d7cdf 331 exit(1); /* BIIG buffer */
332 }
ba4fe07c 333 fprintf(stdout, "BH input error\n");
3e5d7cdf 334 exit(0);
335 }
336
337 c=memchr(buf,'\n',sizeof(buf)-1);
338 if (c) {
339 *c = '\0';
340 length = c-buf;
341 } else {
342 err = 1;
343 }
344 if (err) {
345 if (debug)
346 fprintf(stderr, "%s| %s: Oversized message\n", LogTime(), PROGRAM);
ba4fe07c 347 fprintf(stdout, "BH Oversized message\n");
3e5d7cdf 348 err = 0;
349 continue;
350 }
351
352 if (debug)
ba4fe07c 353 fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf,length);
3e5d7cdf 354
355 if (buf[0] == '\0') {
356 if (debug)
357 fprintf(stderr, "%s| %s: Invalid request\n", LogTime(), PROGRAM);
ba4fe07c 358 fprintf(stdout, "BH Invalid request\n");
3e5d7cdf 359 continue;
360 }
361
362 if (strlen(buf) < 2) {
363 if (debug)
364 fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
ba4fe07c 365 fprintf(stdout, "BH Invalid request\n");
3e5d7cdf 366 continue;
367 }
368
369 if ( !strncmp(buf, "QQ", 2) ) {
370 gss_release_buffer(&minor_status, &input_token);
371 gss_release_buffer(&minor_status, &output_token);
372 gss_release_buffer(&minor_status, &service);
373 gss_release_cred(&minor_status, &server_creds);
ba4fe07c
AJ
374 if (server_name)
375 gss_release_name(&minor_status, &server_name);
376 if (client_name)
377 gss_release_name(&minor_status, &client_name);
378 if (gss_context != GSS_C_NO_CONTEXT )
379 gss_delete_sec_context(&minor_status, &gss_context, NULL);
3e5d7cdf 380 if (kerberosToken) {
381 /* Allocated by parseNegTokenInit, but no matching free function exists.. */
382 if (!spnego_flag)
ba4fe07c 383 xfree((char *)kerberosToken);
3e5d7cdf 384 kerberosToken=NULL;
385 }
386 if (spnego_flag) {
387 /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
388 if (spnegoToken)
ba4fe07c 389 xfree((char *)spnegoToken);
3e5d7cdf 390 spnegoToken=NULL;
391 }
392 if (token) {
ba4fe07c 393 xfree(token);
3e5d7cdf 394 token=NULL;
395 }
396 if (host_name) {
ba4fe07c 397 xfree(host_name);
3e5d7cdf 398 host_name=NULL;
399 }
ba4fe07c 400 fprintf(stdout, "BH quit command\n");
3e5d7cdf 401 exit(0);
402 }
403
ba4fe07c 404 if ( strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2) ) {
3e5d7cdf 405 if (debug)
406 fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
ba4fe07c 407 fprintf(stdout, "BH Invalid request\n");
3e5d7cdf 408 continue;
409 }
410 if ( !strncmp(buf, "YR", 2) ){
411 if (gss_context != GSS_C_NO_CONTEXT )
412 gss_delete_sec_context(&minor_status, &gss_context, NULL);
413 gss_context = GSS_C_NO_CONTEXT;
414 }
415
416 if (strlen(buf) <= 3) {
417 if (debug)
418 fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
ba4fe07c 419 fprintf(stdout, "BH Invalid negotiate request\n");
3e5d7cdf 420 continue;
421 }
422
ba4fe07c
AJ
423 input_token.length = ska_base64_decode_len(buf+3);
424 if (debug)
425 fprintf(stderr, "%s| %s: Decode '%s' (decoded length: %d).\n", LogTime(), PROGRAM, buf+3,(int)input_token.length);
426 input_token.value = xmalloc(input_token.length);
3e5d7cdf 427
ba4fe07c 428 ska_base64_decode(input_token.value,buf+3,input_token.length);
3e5d7cdf 429
430
431#ifndef HAVE_SPNEGO
432 if (( rc=parseNegTokenInit (input_token.value,
433 input_token.length,
434 &kerberosToken,
435 &kerberosTokenLength))!=0 ){
436 if (debug)
437 fprintf(stderr, "%s| %s: parseNegTokenInit failed with rc=%d\n", LogTime(), PROGRAM, rc);
438
439 /* if between 100 and 200 it might be a GSSAPI token and not a SPNEGO token */
440 if ( rc < 100 || rc > 199 ) {
441 if (debug)
442 fprintf(stderr, "%s| %s: Invalid GSS-SPNEGO query [%s]\n", LogTime(), PROGRAM, buf);
ba4fe07c 443 fprintf(stdout, "BH Invalid GSS-SPNEGO query\n");
3e5d7cdf 444 goto cleanup;
445 }
446 if ((input_token.length >= sizeof ntlmProtocol + 1) &&
447 (!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
448 if (debug)
449 fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
ba4fe07c 450 fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
3e5d7cdf 451 goto cleanup;
452 }
ba4fe07c
AJ
453 if (debug)
454 fprintf(stderr, "%s| %s: Token is possibly a GSSAPI token\n", LogTime(), PROGRAM);
3e5d7cdf 455 spnego_flag=0;
456 } else {
457 gss_release_buffer(&minor_status, &input_token);
458 input_token.length=kerberosTokenLength;
459 input_token.value=(void *)kerberosToken;
460 spnego_flag=1;
461 }
462#else
463 if ((input_token.length >= sizeof ntlmProtocol + 1) &&
464 (!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
465 if (debug)
466 fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
ba4fe07c 467 fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
3e5d7cdf 468 goto cleanup;
469 }
470#endif
471
472 if ( service_principal ) {
473 if ( strcasecmp(service_principal,"GSS_C_NO_NAME") ){
474 major_status = gss_import_name(&minor_status, &service,
475 (gss_OID) GSS_C_NULL_OID, &server_name);
476
477 } else {
478 server_name = GSS_C_NO_NAME;
479 major_status = GSS_S_COMPLETE;
480 }
481 } else {
482 major_status = gss_import_name(&minor_status, &service,
483 gss_nt_service_name, &server_name);
484 }
485
ba4fe07c 486 if ( check_gss_err(major_status,minor_status,"gss_import_name()",debug,log) )
3e5d7cdf 487 goto cleanup;
488
489 major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
490 GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds,
491 NULL, NULL);
ba4fe07c 492 if (check_gss_err(major_status,minor_status,"gss_acquire_cred()",debug,log) )
3e5d7cdf 493 goto cleanup;
494
495 major_status = gss_accept_sec_context(&minor_status,
496 &gss_context,
497 server_creds,
498 &input_token,
499 GSS_C_NO_CHANNEL_BINDINGS,
500 &client_name,
501 NULL,
502 &output_token,
503 &ret_flags,
504 NULL,
ba4fe07c 505 NULL);
3e5d7cdf 506
507
508 if (output_token.length) {
509#ifndef HAVE_SPNEGO
510 if (spnego_flag) {
511 if ((rc=makeNegTokenTarg (output_token.value,
512 output_token.length,
513 &spnegoToken,
514 &spnegoTokenLength))!=0 ) {
515 if (debug)
516 fprintf(stderr, "%s| %s: makeNegTokenTarg failed with rc=%d\n", LogTime(), PROGRAM, rc);
ba4fe07c 517 fprintf(stdout, "BH makeNegTokenTarg failed with rc=%d\n",rc);
3e5d7cdf 518 goto cleanup;
519 }
520 } else {
521 spnegoToken = output_token.value;
522 spnegoTokenLength = output_token.length;
523 }
524#else
525 spnegoToken = output_token.value;
526 spnegoTokenLength = output_token.length;
527#endif
ba4fe07c 528 token = xmalloc(ska_base64_encode_len(spnegoTokenLength));
3e5d7cdf 529 if (token == NULL) {
530 if (debug)
531 fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM);
ba4fe07c 532 fprintf(stdout, "BH Not enough memory\n");
3e5d7cdf 533 goto cleanup;
534 }
535
ba4fe07c 536 ska_base64_encode(token,(const char *)spnegoToken,ska_base64_encode_len(spnegoTokenLength),spnegoTokenLength);
3e5d7cdf 537
ba4fe07c 538 if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) )
3e5d7cdf 539 goto cleanup;
540 if (major_status & GSS_S_CONTINUE_NEEDED) {
541 if (debug)
542 fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM);
543 fprintf(stdout, "TT %s\n",token);
544 goto cleanup;
545 }
546 gss_release_buffer(&minor_status, &output_token);
547 major_status = gss_display_name(&minor_status, client_name, &output_token,
548 NULL);
549
ba4fe07c 550 if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) )
3e5d7cdf 551 goto cleanup;
552 fprintf(stdout, "AF %s %s\n",token,(char *)output_token.value);
553 if (debug)
554 fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, token,(char *)output_token.value);
ba4fe07c 555 if (log)
3e5d7cdf 556 fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value);
557 goto cleanup;
558 } else {
ba4fe07c 559 if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) )
3e5d7cdf 560 goto cleanup;
561 if (major_status & GSS_S_CONTINUE_NEEDED) {
562 if (debug)
563 fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM);
ba4fe07c 564 fprintf(stdout, "NA %s\n",token);
3e5d7cdf 565 goto cleanup;
566 }
567 gss_release_buffer(&minor_status, &output_token);
568 major_status = gss_display_name(&minor_status, client_name, &output_token,
569 NULL);
570
ba4fe07c 571 if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) )
3e5d7cdf 572 goto cleanup;
573 /*
574 * Return dummy token AA. May need an extra return tag then AF
575 */
576 fprintf(stdout, "AF %s %s\n","AA==",(char *)output_token.value);
577 if (debug)
578 fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, "AA==", (char *)output_token.value);
ba4fe07c 579 if (log)
3e5d7cdf 580 fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, (char *)output_token.value);
581
582cleanup:
583 gss_release_buffer(&minor_status, &input_token);
584 gss_release_buffer(&minor_status, &output_token);
585 gss_release_cred(&minor_status, &server_creds);
ba4fe07c
AJ
586 if (server_name)
587 gss_release_name(&minor_status, &server_name);
588 if (client_name)
589 gss_release_name(&minor_status, &client_name);
3e5d7cdf 590 if (kerberosToken) {
591 /* Allocated by parseNegTokenInit, but no matching free function exists.. */
592 if (!spnego_flag)
ba4fe07c 593 xfree((char *)kerberosToken);
3e5d7cdf 594 kerberosToken=NULL;
595 }
596 if (spnego_flag) {
597 /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
598 if (spnegoToken)
ba4fe07c 599 xfree((char *)spnegoToken);
3e5d7cdf 600 spnegoToken=NULL;
601 }
602 if (token) {
ba4fe07c 603 xfree(token);
3e5d7cdf 604 token=NULL;
605 }
606 continue;
607 }
608 }
609}