Пример #1
0
int main(int argc, char * const argv[])
{
  char buf[MAX_AUTHTOKEN_LEN];
  char *c;
  char *user=NULL;
  int length=0;
  static int err=0;
  int opt, rc, debug=0, loging=0;
  OM_uint32 ret_flags=0, spnego_flag=0;
  char *service_name=(char *)"HTTP",*host_name=NULL;
  char *token = NULL;
  char *service_principal = NULL;
  OM_uint32 major_status, minor_status;
  gss_ctx_id_t 		gss_context = GSS_C_NO_CONTEXT;
  gss_name_t 		client_name = GSS_C_NO_NAME;
  gss_name_t 		server_name = GSS_C_NO_NAME;
  gss_cred_id_t 	server_creds = GSS_C_NO_CREDENTIAL;
  gss_cred_id_t 	delegated_cred = GSS_C_NO_CREDENTIAL;
  gss_buffer_desc 	service = GSS_C_EMPTY_BUFFER;
  gss_buffer_desc 	input_token = GSS_C_EMPTY_BUFFER;
  gss_buffer_desc 	output_token = GSS_C_EMPTY_BUFFER;
  const unsigned char	*kerberosToken       = NULL;
  size_t		kerberosTokenLength = 0;
  const unsigned char	*spnegoToken         = NULL ;
  size_t		spnegoTokenLength   = 0;

  setbuf(stdout,NULL);
  setbuf(stdin,NULL);

  while (-1 != (opt = getopt(argc, argv, "dis:h"))) {
    switch (opt) {
    case 'd':
      debug = 1;
      break;              
    case 'i':
      loging = 1;
      break;              
    case 's':
      service_principal = strdup(optarg);
      break;
    case 'h':
      fprintf(stdout, "Usage: \n");
      fprintf(stdout, "squid_kerb_auth -d [-s SPN]\n");
      fprintf(stdout, "SPN = service principal name\n");
      fprintf(stdout, "Can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
      fprintf(stdout, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
      break;
    default:
      fprintf(stderr, "%s| %s: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
    }
  }

  if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
    service.value = service_principal;
    service.length = strlen((char *)service.value);
  } else {
    host_name=gethost_name();
    if ( !host_name ) {
      fprintf(stderr, "%s| %s: Local hostname could not be determined. Please specify the service principal\n", LogTime(), PROGRAM);
      exit(-1);
    }
    service.value = malloc(strlen(service_name)+strlen(host_name)+2);
    snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name);
    service.length = strlen((char *)service.value);
  }

  while (1) {
    if (fgets(buf, sizeof(buf)-1, stdin) == NULL) {
      if (ferror(stdin)) {
	if (debug)
	  fprintf(stderr, "%s| %s: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
		 strerror(ferror(stdin)));

	exit(1);    /* BIIG buffer */
      }
      exit(0);
    }

    c=memchr(buf,'\n',sizeof(buf)-1);
    if (c) {
      *c = '\0';
      length = c-buf;
    } else {
      err = 1;
    }
    if (err) {
      if (debug)
	fprintf(stderr, "%s| %s: Oversized message\n", LogTime(), PROGRAM);
      fprintf(stdout, "NA Oversized message\n");
      err = 0;
      continue;
    }

    if (debug)
      fprintf(stderr, "%s| %s: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf ,length);

    if (buf[0] == '\0') {
      if (debug)
	fprintf(stderr, "%s| %s: Invalid request\n", LogTime(), PROGRAM);
      fprintf(stdout, "NA Invalid request\n");
      continue;
    }

    if (strlen(buf) < 2) {
      if (debug)
	fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
      fprintf(stdout, "NA Invalid request\n");
      continue;
    }

    if ( !strncmp(buf, "QQ", 2) ) {
      gss_release_buffer(&minor_status, &input_token);
      gss_release_buffer(&minor_status, &output_token);
      gss_release_buffer(&minor_status, &service);
      gss_release_cred(&minor_status, &server_creds);
      gss_release_cred(&minor_status, &delegated_cred);
      gss_release_name(&minor_status, &server_name);
      gss_release_name(&minor_status, &client_name);
      gss_delete_sec_context(&minor_status, &gss_context, NULL);
      if (kerberosToken) {
	/* Allocated by parseNegTokenInit, but no matching free function exists.. */
        if (!spnego_flag)
          free((char *)kerberosToken);
        kerberosToken=NULL;
      }
      if (spnego_flag) {
	/* Allocated by makeNegTokenTarg, but no matching free function exists.. */
        if (spnegoToken) 
	  free((char *)spnegoToken);
      	spnegoToken=NULL;
      }
      if (token) {
        free(token);
        token=NULL;
      }
      if (host_name) {
        free(host_name);
        host_name=NULL;
      }
      exit(0);
    }

    if ( !strncmp(buf, "YR", 2) && !strncmp(buf, "KK", 2) ) {
      if (debug)
	fprintf(stderr, "%s| %s: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
      fprintf(stdout, "NA Invalid request\n");
      continue;
    }
    if ( !strncmp(buf, "YR", 2) ){
      if (gss_context != GSS_C_NO_CONTEXT )
        gss_delete_sec_context(&minor_status, &gss_context, NULL);
      gss_context = GSS_C_NO_CONTEXT;
    }

    if (strlen(buf) <= 3) {
      if (debug)
	fprintf(stderr, "%s| %s: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
      fprintf(stdout, "NA Invalid negotiate request\n");
      continue;
    }
        
    input_token.length = base64_decode_len(buf+3);
    input_token.value = malloc(input_token.length);

    base64_decode(input_token.value,buf+3,input_token.length);

 
#ifndef HAVE_SPNEGO
    if (( rc=parseNegTokenInit (input_token.value,
				input_token.length,
				&kerberosToken,
				&kerberosTokenLength))!=0 ){
      if (debug)
	fprintf(stderr, "%s| %s: parseNegTokenInit failed with rc=%d\n", LogTime(), PROGRAM, rc);
        
      /* if between 100 and 200 it might be a GSSAPI token and not a SPNEGO token */    
      if ( rc < 100 || rc > 199 ) {
	if (debug)
	  fprintf(stderr, "%s| %s: Invalid GSS-SPNEGO query [%s]\n", LogTime(), PROGRAM, buf);
	fprintf(stdout, "NA Invalid GSS-SPNEGO query\n");
	goto cleanup;
      } 
      if ((input_token.length >= sizeof ntlmProtocol + 1) &&
	  (!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
	if (debug)
	  fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
	fprintf(stdout, "NA received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
	goto cleanup;
      } 
      spnego_flag=0;
    } else {
      gss_release_buffer(&minor_status, &input_token);
      input_token.length=kerberosTokenLength;
      input_token.value=(void *)kerberosToken;
      spnego_flag=1;
    }
#else
    if ((input_token.length >= sizeof ntlmProtocol + 1) &&
	(!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
      if (debug)
	fprintf(stderr, "%s| %s: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
      fprintf(stdout, "NA received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
      goto cleanup;
    } 
#endif
     
    if ( service_principal ) {
      if ( strcasecmp(service_principal,"GSS_C_NO_NAME") ){
        major_status = gss_import_name(&minor_status, &service,
  				       (gss_OID) GSS_C_NULL_OID, &server_name);
       
      } else {
        server_name = GSS_C_NO_NAME;
        major_status = GSS_S_COMPLETE;
      }
    } else {
      major_status = gss_import_name(&minor_status, &service,
  				     gss_nt_service_name, &server_name);
    }

    if ( check_gss_err(major_status,minor_status,"gss_import_name()",debug,loging) )
      goto cleanup;

    major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
				    GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds,
				    NULL, NULL);
    if (check_gss_err(major_status,minor_status,"gss_acquire_cred()",debug,loging) )
      goto cleanup;

    major_status = gss_accept_sec_context(&minor_status,
					  &gss_context,
					  server_creds,
					  &input_token,
					  GSS_C_NO_CHANNEL_BINDINGS,
					  &client_name,
					  NULL,
					  &output_token,
					  &ret_flags,
					  NULL,
					  &delegated_cred);


    if (output_token.length) {
#ifndef HAVE_SPNEGO
      if (spnego_flag) {
	if ((rc=makeNegTokenTarg (output_token.value,
				  output_token.length,
				  &spnegoToken,
				  &spnegoTokenLength))!=0 ) {
	  if (debug)
	    fprintf(stderr, "%s| %s: makeNegTokenTarg failed with rc=%d\n", LogTime(), PROGRAM, rc);
	  fprintf(stdout, "NA makeNegTokenTarg failed with rc=%d\n",rc);
	  goto cleanup;
	}
      } else {
	spnegoToken = output_token.value;
	spnegoTokenLength = output_token.length;
      }
#else
      spnegoToken = output_token.value;
      spnegoTokenLength = output_token.length;
#endif
      token = malloc(base64_encode_len(spnegoTokenLength));
      if (token == NULL) {
	if (debug)
	  fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM);
	fprintf(stdout, "NA Not enough memory\n");
        goto cleanup;
      }

      base64_encode(token,(const char *)spnegoToken,base64_encode_len(spnegoTokenLength),spnegoTokenLength);

      if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,loging) )
	goto cleanup;
      if (major_status & GSS_S_CONTINUE_NEEDED) {
	if (debug)
	  fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM);
	fprintf(stdout, "TT %s\n",token);
        goto cleanup;
      }
      gss_release_buffer(&minor_status, &output_token);
      major_status = gss_display_name(&minor_status, client_name, &output_token,
				      NULL);

      if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,loging) )
	goto cleanup;
      
      user=malloc(output_token.length+1);
      if (user == NULL) {
        if (debug)
          fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM);
        fprintf(stdout, "BH Not enough memory\n");
        goto cleanup;
      }
      memcpy(user,output_token.value,output_token.length);
      user[output_token.length]='\0';
      fprintf(stdout, "AF %s %s\n",token,user);
      if (debug)
	fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, token,user); 
      if (loging)
	fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, user);
      goto cleanup;
    } else {
      if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,loging) )
	goto cleanup;
      if (major_status & GSS_S_CONTINUE_NEEDED) {
	if (debug)
	  fprintf(stderr, "%s| %s: continuation needed\n", LogTime(), PROGRAM);
	fprintf(stdout, "NA No token to return to continue\n");
	goto cleanup;
      }
      gss_release_buffer(&minor_status, &output_token);
      major_status = gss_display_name(&minor_status, client_name, &output_token,
				      NULL);

      if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,loging) )
	goto cleanup;
      /* 
       *  Return dummy token AA. May need an extra return tag then AF
       */
      user=malloc(output_token.length+1);
      if (user == NULL) { 
        if (debug)
          fprintf(stderr, "%s| %s: Not enough memory\n", LogTime(), PROGRAM);
        fprintf(stdout, "BH Not enough memory\n");
        goto cleanup; 
      }
      memcpy(user,output_token.value,output_token.length);
      user[output_token.length]='\0';      
      fprintf(stdout, "AF %s %s\n","AA==",user);
      if (debug)
	fprintf(stderr, "%s| %s: AF %s %s\n", LogTime(), PROGRAM, "AA==", user);
      if (loging)
	fprintf(stderr, "%s| %s: User %s authenticated\n", LogTime(), PROGRAM, user);

cleanup:
      gss_release_buffer(&minor_status, &input_token);
      gss_release_buffer(&minor_status, &output_token);
      gss_release_cred(&minor_status, &server_creds);
      gss_release_cred(&minor_status, &delegated_cred);
      gss_release_name(&minor_status, &server_name);
      gss_release_name(&minor_status, &client_name);
      if (kerberosToken) {
	/* Allocated by parseNegTokenInit, but no matching free function exists.. */
	if (!spnego_flag)
           free((char *)kerberosToken);
      	kerberosToken=NULL;
      }
      if (spnego_flag) {
	/* Allocated by makeNegTokenTarg, but no matching free function exists.. */
        if (spnegoToken)
	  free((char *)spnegoToken);
      	spnegoToken=NULL;
      }
      if (token) {
        free(token);
      	token=NULL;
      }
      if( user) {
         free(user);
         user=NULL;
      }
      continue;            
    }
  }
}
Пример #2
0
int main(int argc, char * const argv[])
{
    char buf[MAX_AUTHTOKEN_LEN];
    char *c;
    char *user=NULL;
    int length=0;
    static int err=0;
    int opt, debug=0, log=0;
    OM_uint32 ret_flags=0, spnego_flag=0;
    char *service_name=(char *)"HTTP",*host_name=NULL;
    char *token = NULL;
    char *service_principal = NULL;
    OM_uint32 major_status, minor_status;
    gss_ctx_id_t 		gss_context = GSS_C_NO_CONTEXT;
    gss_name_t 		client_name = GSS_C_NO_NAME;
    gss_name_t 		server_name = GSS_C_NO_NAME;
    gss_cred_id_t 	server_creds = GSS_C_NO_CREDENTIAL;
    gss_buffer_desc 	service = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc 	input_token = GSS_C_EMPTY_BUFFER;
    gss_buffer_desc 	output_token = GSS_C_EMPTY_BUFFER;
    const unsigned char	*kerberosToken       = NULL;
    const unsigned char	*spnegoToken         = NULL ;
    size_t		spnegoTokenLength   = 0;

    setbuf(stdout,NULL);
    setbuf(stdin,NULL);

    while (-1 != (opt = getopt(argc, argv, "dis:h"))) {
        switch (opt) {
        case 'd':
            debug = 1;
            break;
        case 'i':
            log = 1;
            break;
        case 's':
            service_principal = xstrdup(optarg);
            break;
        case 'h':
            fprintf(stderr, "Usage: \n");
            fprintf(stderr, "squid_kerb_auth [-d] [-i] [-s SPN] [-h]\n");
            fprintf(stderr, "-d full debug\n");
            fprintf(stderr, "-i informational messages\n");
            fprintf(stderr, "-s service principal name\n");
            fprintf(stderr, "-h help\n");
            fprintf(stderr, "The SPN can be set to GSS_C_NO_NAME to allow any entry from keytab\n");
            fprintf(stderr, "default SPN is HTTP/fqdn@DEFAULT_REALM\n");
            exit(0);
        default:
            fprintf(stderr, "%s| %s: WARNING: unknown option: -%c.\n", LogTime(), PROGRAM, opt);
        }
    }

    if (debug)
        fprintf(stderr, "%s| %s: INFO: Starting version %s\n", LogTime(), PROGRAM, VERSION);
    if (service_principal && strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
        service.value = service_principal;
        service.length = strlen((char *)service.value);
    } else {
        host_name=gethost_name();
        if ( !host_name ) {
            fprintf(stderr, "%s| %s: FATAL: Local hostname could not be determined. Please specify the service principal\n", LogTime(), PROGRAM);
            fprintf(stdout, "BH hostname error\n");
            exit(-1);
        }
        service.value = xmalloc(strlen(service_name)+strlen(host_name)+2);
        snprintf(service.value,strlen(service_name)+strlen(host_name)+2,"%s@%s",service_name,host_name);
        service.length = strlen((char *)service.value);
    }

    while (1) {
        if (fgets(buf, sizeof(buf)-1, stdin) == NULL) {
            if (ferror(stdin)) {
                if (debug)
                    fprintf(stderr, "%s| %s: FATAL: fgets() failed! dying..... errno=%d (%s)\n", LogTime(), PROGRAM, ferror(stdin),
                            strerror(ferror(stdin)));

                fprintf(stdout, "BH input error\n");
                exit(1);    /* BIIG buffer */
            }
            fprintf(stdout, "BH input error\n");
            exit(0);
        }

        c=memchr(buf,'\n',sizeof(buf)-1);
        if (c) {
            *c = '\0';
            length = c-buf;
        } else {
            err = 1;
        }
        if (err) {
            if (debug)
                fprintf(stderr, "%s| %s: ERROR: Oversized message\n", LogTime(), PROGRAM);
            fprintf(stdout, "BH Oversized message\n");
            err = 0;
            continue;
        }

        if (debug)
            fprintf(stderr, "%s| %s: DEBUG: Got '%s' from squid (length: %d).\n", LogTime(), PROGRAM, buf,length);

        if (buf[0] == '\0') {
            if (debug)
                fprintf(stderr, "%s| %s: ERROR: Invalid request\n", LogTime(), PROGRAM);
            fprintf(stdout, "BH Invalid request\n");
            continue;
        }

        if (strlen(buf) < 2) {
            if (debug)
                fprintf(stderr, "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
            fprintf(stdout, "BH Invalid request\n");
            continue;
        }

        if ( !strncmp(buf, "QQ", 2) ) {
            gss_release_buffer(&minor_status, &input_token);
            gss_release_buffer(&minor_status, &output_token);
            gss_release_buffer(&minor_status, &service);
            gss_release_cred(&minor_status, &server_creds);
            if (server_name)
                gss_release_name(&minor_status, &server_name);
            if (client_name)
                gss_release_name(&minor_status, &client_name);
            if (gss_context != GSS_C_NO_CONTEXT )
                gss_delete_sec_context(&minor_status, &gss_context, NULL);
            if (kerberosToken) {
                /* Allocated by parseNegTokenInit, but no matching free function exists.. */
                if (!spnego_flag)
                    xfree((char *)kerberosToken);
                kerberosToken=NULL;
            }
            if (spnego_flag) {
                /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
                if (spnegoToken)
                    xfree((char *)spnegoToken);
                spnegoToken=NULL;
            }
            if (token) {
                xfree(token);
                token=NULL;
            }
            if (host_name) {
                xfree(host_name);
                host_name=NULL;
            }
            fprintf(stdout, "BH quit command\n");
            exit(0);
        }

        if ( strncmp(buf, "YR", 2) && strncmp(buf, "KK", 2) ) {
            if (debug)
                fprintf(stderr, "%s| %s: ERROR: Invalid request [%s]\n", LogTime(), PROGRAM, buf);
            fprintf(stdout, "BH Invalid request\n");
            continue;
        }
        if ( !strncmp(buf, "YR", 2) ) {
            if (gss_context != GSS_C_NO_CONTEXT )
                gss_delete_sec_context(&minor_status, &gss_context, NULL);
            gss_context = GSS_C_NO_CONTEXT;
        }

        if (strlen(buf) <= 3) {
            if (debug)
                fprintf(stderr, "%s| %s: ERROR: Invalid negotiate request [%s]\n", LogTime(), PROGRAM, buf);
            fprintf(stdout, "BH Invalid negotiate request\n");
            continue;
        }

        input_token.length = ska_base64_decode_len(buf+3);
        if (debug)
            fprintf(stderr, "%s| %s: DEBUG: Decode '%s' (decoded length: %d).\n", LogTime(), PROGRAM, buf+3,(int)input_token.length);
        input_token.value = xmalloc(input_token.length);

        ska_base64_decode(input_token.value,buf+3,input_token.length);


        if ((input_token.length >= sizeof ntlmProtocol + 1) &&
                (!memcmp (input_token.value, ntlmProtocol, sizeof ntlmProtocol))) {
            if (debug)
                fprintf(stderr, "%s| %s: WARNING: received type %d NTLM token\n", LogTime(), PROGRAM, (int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
            fprintf(stdout, "BH received type %d NTLM token\n",(int) *((unsigned char *)input_token.value + sizeof ntlmProtocol));
            goto cleanup;
        }

        if ( service_principal ) {
            if ( strcasecmp(service_principal,"GSS_C_NO_NAME") ) {
                major_status = gss_import_name(&minor_status, &service,
                                               (gss_OID) GSS_C_NULL_OID, &server_name);

            } else {
                server_name = GSS_C_NO_NAME;
                major_status = GSS_S_COMPLETE;
            }
        } else {
            major_status = gss_import_name(&minor_status, &service,
                                           gss_nt_service_name, &server_name);
        }

        if ( check_gss_err(major_status,minor_status,"gss_import_name()",debug,log) )
            goto cleanup;

        major_status = gss_acquire_cred(&minor_status, server_name, GSS_C_INDEFINITE,
                                        GSS_C_NO_OID_SET, GSS_C_ACCEPT, &server_creds,
                                        NULL, NULL);
        if (check_gss_err(major_status,minor_status,"gss_acquire_cred()",debug,log) )
            goto cleanup;

        major_status = gss_accept_sec_context(&minor_status,
                                              &gss_context,
                                              server_creds,
                                              &input_token,
                                              GSS_C_NO_CHANNEL_BINDINGS,
                                              &client_name,
                                              NULL,
                                              &output_token,
                                              &ret_flags,
                                              NULL,
                                              NULL);


        if (output_token.length) {
            spnegoToken = output_token.value;
            spnegoTokenLength = output_token.length;
            token = xmalloc(ska_base64_encode_len(spnegoTokenLength));
            if (token == NULL) {
                if (debug)
                    fprintf(stderr, "%s| %s: ERROT: Not enough memory\n", LogTime(), PROGRAM);
                fprintf(stdout, "BH Not enough memory\n");
                goto cleanup;
            }

            ska_base64_encode(token,(const char *)spnegoToken,ska_base64_encode_len(spnegoTokenLength),spnegoTokenLength);

            if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) )
                goto cleanup;
            if (major_status & GSS_S_CONTINUE_NEEDED) {
                if (debug)
                    fprintf(stderr, "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
                fprintf(stdout, "TT %s\n",token);
                goto cleanup;
            }
            gss_release_buffer(&minor_status, &output_token);
            major_status = gss_display_name(&minor_status, client_name, &output_token,
                                            NULL);

            if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) )
                goto cleanup;
            user=xmalloc(output_token.length+1);
            if (user == NULL) {
                if (debug)
                    fprintf(stderr, "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                fprintf(stdout, "BH Not enough memory\n");
                goto cleanup;
            }
            memcpy(user,output_token.value,output_token.length);
            user[output_token.length]='\0';
            fprintf(stdout, "AF %s %s\n",token,user);
            if (debug)
                fprintf(stderr, "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, token,user);
            if (log)
                fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(), PROGRAM, user);
            goto cleanup;
        } else {
            if (check_gss_err(major_status,minor_status,"gss_accept_sec_context()",debug,log) )
                goto cleanup;
            if (major_status & GSS_S_CONTINUE_NEEDED) {
                if (debug)
                    fprintf(stderr, "%s| %s: INFO: continuation needed\n", LogTime(), PROGRAM);
                fprintf(stdout, "NA %s\n",token);
                goto cleanup;
            }
            gss_release_buffer(&minor_status, &output_token);
            major_status = gss_display_name(&minor_status, client_name, &output_token,
                                            NULL);

            if (check_gss_err(major_status,minor_status,"gss_display_name()",debug,log) )
                goto cleanup;
            /*
             *  Return dummy token AA. May need an extra return tag then AF
             */
            user=xmalloc(output_token.length+1);
            if (user == NULL) {
                if (debug)
                    fprintf(stderr, "%s| %s: ERROR: Not enough memory\n", LogTime(), PROGRAM);
                fprintf(stdout, "BH Not enough memory\n");
                goto cleanup;
            }
            memcpy(user,output_token.value,output_token.length);
            user[output_token.length]='\0';
            fprintf(stdout, "AF %s %s\n","AA==",user);
            if (debug)
                fprintf(stderr, "%s| %s: DEBUG: AF %s %s\n", LogTime(), PROGRAM, "AA==", user);
            if (log)
                fprintf(stderr, "%s| %s: INFO: User %s authenticated\n", LogTime(), PROGRAM, user);

cleanup:
            gss_release_buffer(&minor_status, &input_token);
            gss_release_buffer(&minor_status, &output_token);
            gss_release_cred(&minor_status, &server_creds);
            if (server_name)
                gss_release_name(&minor_status, &server_name);
            if (client_name)
                gss_release_name(&minor_status, &client_name);
            if (kerberosToken) {
                /* Allocated by parseNegTokenInit, but no matching free function exists.. */
                if (!spnego_flag)
                    xfree((char *)kerberosToken);
                kerberosToken=NULL;
            }
            if (spnego_flag) {
                /* Allocated by makeNegTokenTarg, but no matching free function exists.. */
                if (spnegoToken)
                    xfree((char *)spnegoToken);
                spnegoToken=NULL;
            }
            if (token) {
                xfree(token);
                token=NULL;
            }
            if (user) {
                xfree(user);
                user=NULL;
            }
            continue;
        }
    }
}