Exemple #1
0
static void
test_misc(krb5_context context)
{
    /* Tests for certain error returns */
    krb5_error_code       kret;
    krb5_keytab ktid;
    char defname[BUFSIZ];
    char *name;

    fprintf(stderr, "Testing miscellaneous error conditions\n");

    kret = krb5_kt_resolve(context, "unknown_method_ep:/tmp/name", &ktid);
    if (kret != KRB5_KT_UNKNOWN_TYPE) {
        CHECK(kret, "resolve unknown type");
    }

    /* Test length limits on krb5_kt_default_name */
    kret = krb5_kt_default_name(context, defname, sizeof(defname));
    CHECK(kret, "krb5_kt_default_name error");

    /* Now allocate space - without the null... */
    name = malloc(strlen(defname));
    if(!name) {
        fprintf(stderr, "Out of memory in testing\n");
        exit(1);
    }
    kret = krb5_kt_default_name(context, name, strlen(defname));
    free(name);
    if (kret != KRB5_CONFIG_NOTENUFSPACE) {
        CHECK(kret, "krb5_kt_default_name limited");
    }
}
std::string Krb5Keytab::getDefaultKeytabName(krb5_context context) {
  char name[kKeytabNameMaxLength];
  krb5_error_code code = krb5_kt_default_name(context,
                                              name,
                                              sizeof(name));
  raiseIf(context, code, "getting default keytab name");
  return name;
}
Exemple #3
0
static void
get_creds(krb5_context context, const char *keytab_str,
	  krb5_ccache *cache, const char *serverhost)
{
    krb5_keytab keytab;
    krb5_principal client;
    krb5_error_code ret;
    krb5_get_init_creds_opt *init_opts;
    krb5_creds creds;
    char *server;
    char keytab_buf[256];
    int aret;

    if (keytab_str == NULL) {
	ret = krb5_kt_default_name (context, keytab_buf, sizeof(keytab_buf));
	if (ret)
	    krb5_err (context, 1, ret, "krb5_kt_default_name");
	keytab_str = keytab_buf;
    }

    ret = krb5_kt_resolve(context, keytab_str, &keytab);
    if(ret)
	krb5_err(context, 1, ret, "%s", keytab_str);


    ret = krb5_sname_to_principal (context, slave_str, IPROP_NAME,
				   KRB5_NT_SRV_HST, &client);
    if (ret) krb5_err(context, 1, ret, "krb5_sname_to_principal");

    ret = krb5_get_init_creds_opt_alloc(context, &init_opts);
    if (ret) krb5_err(context, 1, ret, "krb5_get_init_creds_opt_alloc");

    aret = asprintf (&server, "%s/%s", IPROP_NAME, serverhost);
    if (aret == -1 || server == NULL)
	krb5_errx (context, 1, "malloc: no memory");

    ret = krb5_get_init_creds_keytab(context, &creds, client, keytab,
				     0, server, init_opts);
    free (server);
    krb5_get_init_creds_opt_free(context, init_opts);
    if(ret) krb5_err(context, 1, ret, "krb5_get_init_creds");

    ret = krb5_kt_close(context, keytab);
    if(ret) krb5_err(context, 1, ret, "krb5_kt_close");

    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, cache);
    if(ret) krb5_err(context, 1, ret, "krb5_cc_new_unique");

    ret = krb5_cc_initialize(context, *cache, client);
    if(ret) krb5_err(context, 1, ret, "krb5_cc_initialize");

    ret = krb5_cc_store_cred(context, *cache, &creds);
    if(ret) krb5_err(context, 1, ret, "krb5_cc_store_cred");

    krb5_free_cred_contents(context, &creds);
    krb5_free_principal(context, client);
}
Exemple #4
0
krb5_error_code KRB5_CALLCONV
krb5_kt_default(krb5_context context, krb5_keytab *id)
{
    char defname[BUFSIZ];
    krb5_error_code retval;

    if ((retval = krb5_kt_default_name(context, defname, sizeof(defname))))
	return retval;
    return krb5_kt_resolve(context, defname, id);
}
Exemple #5
0
int
kt_list(struct list_options *opt, int argc, char **argv)
{
    krb5_error_code ret;
    char kt[1024];

    if(verbose_flag)
	opt->timestamp_flag = 1;

    if (keytab_string == NULL) {
	if((ret = krb5_kt_default_name(context, kt, sizeof(kt))) != 0) {
	    krb5_warn(context, ret, "getting default keytab name");
	    return 1;
	}
	keytab_string = kt;
    }
    return do_list(opt, keytab_string) != 0;
}
Exemple #6
0
/*
 * effects: If keyprocarg is not NULL, it is taken to be the name of a 
 *	keytab.  Otherwise, the default keytab will be used.  This 
 *	routine opens the keytab and finds the principal associated with
 *	principal, vno, and enctype and returns the resulting key in *key 
 *	or returning an error code if it is not	found. 
 * returns: Either KSUCCESS or error code.
 * errors: error code if not found or keyprocarg is invalid.
 */
krb5_error_code KRB5_CALLCONV
krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg, krb5_principal principal, krb5_kvno vno, krb5_enctype enctype, krb5_keyblock **key)
{
    krb5_error_code kerror = KSUCCESS;
    char keytabname[MAX_KEYTAB_NAME_LEN + 1]; /* + 1 for NULL termination */
    krb5_keytab id;
    krb5_keytab_entry entry;
        
    /*
     * Get the name of the file that we should use. 
     */
    if (!keyprocarg) {
	if ((kerror = krb5_kt_default_name(context, (char *)keytabname, 
					   sizeof(keytabname) - 1))!= KSUCCESS)
	    return (kerror);
    } else {
	memset(keytabname, 0, sizeof(keytabname));
	(void) strncpy(keytabname, (char *)keyprocarg, 
		       sizeof(keytabname) - 1);
    }

    if ((kerror = krb5_kt_resolve(context, (char *)keytabname, &id)))
	return (kerror);

    kerror = krb5_kt_get_entry(context, id, principal, vno, enctype, &entry);
    krb5_kt_close(context, id);

    if (kerror)
	return(kerror);

    krb5_copy_keyblock(context, &entry.key, key);

    krb5_kt_free_entry(context, &entry);

    return (KSUCCESS);
}
Exemple #7
0
/* call-seq:
 *   krb5.get_init_creds_keytab(principal = nil, keytab = nil, service = nil, ccache = nil)
 *
 * Acquire credentials for +principal+ from +keytab+ using +service+. If
 * no principal is specified, then a principal is derived from the service
 * name. If no service name is specified, kerberos defaults to "host".
 *
 * If no keytab file is provided, the default keytab file is used. This is
 * typically /etc/krb5.keytab.
 *
 * If +ccache+ is supplied and is a Kerberos::Krb5::CredentialsCache, the
 * resulting credentials will be stored in the credential cache.
 */
static VALUE rkrb5_get_init_creds_keytab(int argc, VALUE* argv, VALUE self){
  RUBY_KRB5* ptr;
  VALUE v_user, v_keytab_name, v_service, v_ccache;
  char* user;
  char* service;
  char keytab_name[MAX_KEYTAB_NAME_LEN];

  krb5_error_code kerror;
  krb5_get_init_creds_opt* opt;
  krb5_creds cred;

  Data_Get_Struct(self, RUBY_KRB5, ptr); 

  if(!ptr->ctx)
    rb_raise(cKrb5Exception, "no context has been established");

  kerror = krb5_get_init_creds_opt_alloc(ptr->ctx, &opt);
  if(kerror)
    rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_alloc: %s", error_message(kerror));

  rb_scan_args(argc, argv, "04", &v_user, &v_keytab_name, &v_service, &v_ccache);

  // We need the service information for later.
  if(NIL_P(v_service)){
    service = NULL;
  }
  else{
    Check_Type(v_service, T_STRING);
    service = StringValueCStr(v_service);
  }

  // Convert the name (or service name) to a kerberos principal.
  if(NIL_P(v_user)){
    kerror = krb5_sname_to_principal(
      ptr->ctx,
      NULL,
      service,
      KRB5_NT_SRV_HST,
      &ptr->princ
    );

    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_sname_to_principal: %s", error_message(kerror));
    }
  }
  else{
    Check_Type(v_user, T_STRING);
    user = StringValueCStr(v_user);

    kerror = krb5_parse_name(ptr->ctx, user, &ptr->princ); 

    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_parse_name: %s", error_message(kerror));
    }
  }

  // Use the default keytab if none is specified.
  if(NIL_P(v_keytab_name)){
    kerror = krb5_kt_default_name(ptr->ctx, keytab_name, MAX_KEYTAB_NAME_LEN);

    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_kt_default_name: %s", error_message(kerror));
    }
  }
  else{
    Check_Type(v_keytab_name, T_STRING);
    strncpy(keytab_name, StringValueCStr(v_keytab_name), MAX_KEYTAB_NAME_LEN);
  }

  kerror = krb5_kt_resolve(
    ptr->ctx,
    keytab_name,
    &ptr->keytab
  );

  if(kerror) {
    krb5_get_init_creds_opt_free(ptr->ctx, opt);
    rb_raise(cKrb5Exception, "krb5_kt_resolve: %s", error_message(kerror));
  }

  // Set the credential cache from the supplied Kerberos::Krb5::CredentialsCache
  if(!NIL_P(v_ccache)){
    RUBY_KRB5_CCACHE* ccptr;
    Data_Get_Struct(v_ccache, RUBY_KRB5_CCACHE, ccptr);

    kerror = krb5_get_init_creds_opt_set_out_ccache(ptr->ctx, opt, ccptr->ccache);
    if(kerror) {
      krb5_get_init_creds_opt_free(ptr->ctx, opt);
      rb_raise(cKrb5Exception, "krb5_get_init_creds_opt_set_out_ccache: %s", error_message(kerror));
    }
  }

  kerror = krb5_get_init_creds_keytab(
    ptr->ctx,
    &cred,
    ptr->princ,
    ptr->keytab,
    0,
    service,
    opt
  );

  if(kerror) {
    krb5_get_init_creds_opt_free(ptr->ctx, opt);
    rb_raise(cKrb5Exception, "krb5_get_init_creds_keytab: %s", error_message(kerror));
  }

  krb5_get_init_creds_opt_free(ptr->ctx, opt);

  return self; 
}
//----------------------------------------------------------------------
// Authenticate to server as a daemon (i.e. using the keytab)
//----------------------------------------------------------------------
int Condor_Auth_Kerberos :: init_daemon()
{
    int            code, rc = TRUE;
    priv_state     priv;

    char *         daemonPrincipal = 0;

    krb5_keytab    keytab = 0;

	// init some member vars
    creds_ = (krb5_creds *) malloc(sizeof(krb5_creds));
    keytabName_ = param(STR_KERBEROS_SERVER_KEYTAB);

	// needed for extracting service name
	char * tmpsname = 0;
	MyString sname;

    memset(creds_, 0, sizeof(krb5_creds));

    //------------------------------------------
    // Initialize the principal for daemon (properly :-)
    //------------------------------------------
	// this means using a keytab to obtain a tgt.
	//
	// in krb5-1.2 and earlier this was done with krb5_get_in_tkt_keytab()
	//
	// in krb5-1.3 and
	// later this should be done with krb5_get_init_creds_keytab

	// select a server principal
    daemonPrincipal = param(STR_KERBEROS_SERVER_PRINCIPAL);

	if (daemonPrincipal) {
		// it was defined explicitly in the config file
		if ((code = krb5_parse_name(krb_context_, daemonPrincipal, &krb_principal_))) {
			free(daemonPrincipal);
			goto error;
		}
	} else {
		// not defined in config, let's construct one from a service name
		daemonPrincipal = param(STR_KERBEROS_SERVER_SERVICE);
		if (!daemonPrincipal) {
			// use the host credential if no service was specified
			daemonPrincipal = strdup(STR_DEFAULT_CONDOR_SERVICE);
		}

    	if ((code = krb5_sname_to_principal(krb_context_, 
                                        	NULL, 
                                        	daemonPrincipal,
                                        	KRB5_NT_SRV_HST, 
                                        	&krb_principal_))) {
			free(daemonPrincipal);
			goto error;
		}
	}
	free(daemonPrincipal);
	daemonPrincipal = 0;

   
	dprintf_krb5_principal( D_SECURITY, "init_daemon: client principal is '%s'\n", krb_principal_);

    if (keytabName_) {
    	dprintf(D_SECURITY, "init_daemon: Using keytab %s\n", keytabName_);
        code = krb5_kt_resolve(krb_context_, keytabName_, &keytab);
    } else {
		char defktname[_POSIX_PATH_MAX];
		krb5_kt_default_name(krb_context_, defktname, _POSIX_PATH_MAX);
    	dprintf(D_SECURITY, "init_daemon: Using default keytab %s\n", defktname);
        code = krb5_kt_default(krb_context_, &keytab);
    }
	if (code) {
		goto error;
	}

	// get the service name out of the member variable server_
	tmpsname = 0;
	code = krb5_unparse_name(krb_context_, server_, &tmpsname);
	if (code) {
		goto error;
	}

	// copy it into a mystring for stack cleanup purposes
	sname = tmpsname;
	free (tmpsname);

	dprintf(D_SECURITY, "init_daemon: Trying to get tgt credential for service %s\n", sname.Value());

	priv = set_root_priv();   // Get the old privilige
	code = krb5_get_init_creds_keytab(krb_context_, creds_, krb_principal_, keytab, 0, const_cast<char*>(sname.Value()), 0);
	set_priv(priv);
	if(code) {
		goto error;
	}

	dprintf_krb5_principal( D_SECURITY, "init_daemon: gic_kt creds_->client is '%s'\n", creds_->client );
	dprintf_krb5_principal( D_SECURITY, "init_daemon: gic_kt creds_->server is '%s'\n", creds_->server );

    dprintf(D_SECURITY, "Success..........................\n");
    
    rc = TRUE;

    goto cleanup;
    
 error:
    
    dprintf(D_ALWAYS, "AUTH_ERROR: %s\n", error_message(code));

    rc = FALSE;
    
 cleanup:
    
    if (keytab) {
        krb5_kt_close(krb_context_, keytab);   
    }
    
    return rc;
}
Exemple #9
0
/*
 * Print a krb5 ticket in our service key, for the supplied client principal.
 * The path to a keytab is mandatory, but the service principal may be
 * guessed from the keytab contents if desired.  The keytab entry must be
 * one of the allowed_enctypes (a zero-terminated list) if a non-NULL
 * parameter is passed.
 */
krb5_error_code
get_credv5_akimpersonate(krb5_context context, char* keytab,
			 krb5_principal service_principal,
			 krb5_principal client_principal, time_t starttime,
			 time_t endtime, const int *allowed_enctypes,
			 krb5_creds** out_creds /* out */ )
{
    char *tmpkt = NULL;
    struct stat tstat;
    char *ktname = NULL;
    krb5_error_code code;
    krb5_keytab kt = 0;
    krb5_keytab_entry entry[1];
    krb5_creds *creds = 0;
    krb5_enctype enctype;
    krb5_keyblock session_key[1];
#if USING_HEIMDAL
    Ticket *ticket_reply;
    EncTicketPart *enc_tkt_reply;
#else
    krb5_ticket *ticket_reply;
    krb5_enc_tkt_part *enc_tkt_reply;
#endif
    *out_creds = NULL;
    enctype = 0; /* AKIMPERSONATE_IGNORE_ENCTYPE */
    memset(entry, 0, sizeof *entry);
    memset(session_key, 0, sizeof *session_key);
    ticket_reply = NULL;
    enc_tkt_reply = NULL;

    creds = calloc(1, sizeof(*creds));
    if (creds == NULL) {
        code = ENOMEM;
        goto cleanup;
    }
    code = alloc_ticket(&ticket_reply);
    if (code != 0)
	goto cleanup;
    code = alloc_enc_tkt_part(&enc_tkt_reply);
    if (code != 0)
	goto cleanup;
    /* Empty list of allowed etypes must fail.  Do it here to avoid issues. */
    if (allowed_enctypes != NULL && *allowed_enctypes == 0) {
	code = KRB5_BAD_ENCTYPE;
	goto cleanup;
    }
    if (allowed_enctypes == NULL)
        allowed_enctypes = any_enctype;

    if (keytab != NULL) {
	tmpkt = strdup(keytab);
	if (!tmpkt)
	    code = ENOMEM;
    } else {
	tmpkt = malloc(256);
	if (!tmpkt)
	    code = ENOMEM;
	else
	    code = krb5_kt_default_name(context, tmpkt, 256);
    }
    if (code)
	goto cleanup;

    if (strncmp(tmpkt, "WRFILE:", 7) == 0)
	ktname = &(tmpkt[7]);
    else if (strncmp(tmpkt, "FILE:", 5) == 0)
	ktname = &(tmpkt[5]);

    if (ktname && (stat(ktname, &tstat) != 0)) {
	code = KRB5_KT_NOTFOUND;
	goto cleanup;
    }

    code = krb5_kt_resolve(context, tmpkt, &kt);
    if (code != 0)
        goto cleanup;

    code = pick_enctype_and_principal(context, kt, allowed_enctypes,
				      &enctype, &service_principal, entry);
    if (code != 0)
	goto cleanup;

    /* Conjure up a random session key */
    deref_keyblock_enctype(session_key) = enctype;
#if USING_HEIMDAL
    code = krb5_generate_random_keyblock(context, enctype, session_key);
#else
    code = krb5_c_make_random_key(context, enctype, session_key);
#endif
    if (code != 0)
        goto cleanup;

    populate_enc_tkt(session_key, client_principal, starttime, endtime,
		     enc_tkt_reply);

    code = encrypt_enc_tkt(context, service_principal, entry, ticket_reply,
			   enc_tkt_reply);
    if (code != 0)
	goto cleanup;

    code = populate_creds(context, service_principal, client_principal,
			  session_key, ticket_reply, enc_tkt_reply, creds);
    if (code != 0)
	goto cleanup;

    /* return creds */
    *out_creds = creds;
    creds = NULL;
cleanup:
    if (tmpkt)
	free(tmpkt);
    if (deref_enc_data(&ticket_reply->enc_part) != NULL)
        free(deref_enc_data(&ticket_reply->enc_part));
    krb5_free_keytab_entry_contents(context, entry);
    if (client_principal != NULL)
        krb5_free_principal(context, client_principal);
    if (service_principal != NULL)
        krb5_free_principal(context, service_principal);
    if (kt != NULL)
        krb5_kt_close(context, kt);
    if (creds != NULL)
	krb5_free_creds(context, creds);
    krb5_free_keyblock_contents(context, session_key);
    free_ticket(ticket_reply);
    free_enc_tkt_part(enc_tkt_reply);
    return code;
}
/*
 * create Kerberos memory cache
 */
int krb5_create_cache(struct main_args *margs,char *domain) {

    krb5_keytab	    keytab = 0;
    krb5_keytab_entry entry;
    krb5_kt_cursor cursor;
    krb5_creds	    *creds=NULL;
    krb5_creds	    *tgt_creds=NULL;
    krb5_principal  *principal_list = NULL;
    krb5_principal  principal = NULL;
    char  *service;
    char  *keytab_name=NULL,*principal_name=NULL,*mem_cache=NULL;
    char  buf[KT_PATH_MAX], *p;
    int nprinc=0;
    int i;
    int	retval=0; 
    int	found=0; 
    krb5_error_code 		code = 0;

    kparam.context=NULL;

    if (!domain || !strcmp(domain,"")) 
	return(1);

    /*
     * Initialise Kerberos
     */

    code = krb5_init_context(&kparam.context);
    if (code)
    {
	fprintf(stderr, "%s| %s: Error while initialising Kerberos library : %s\n",LogTime(), PROGRAM, error_message(code));
	retval=1;
	goto cleanup;
    }

    /*
     * getting default keytab name
     */

    if (margs->debug)
	fprintf(stderr, "%s| %s: Get default keytab file name\n",LogTime(), PROGRAM);
    krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX);
    p = strchr(buf, ':');             /* Find the end if "FILE:" */
    if (p) p++;                       /* step past : */
    keytab_name = strdup(p ? p : buf);
    if (margs->debug)
	fprintf(stderr, "%s| %s: Got default keytab file name %s\n",LogTime(), PROGRAM, keytab_name);

    code = krb5_kt_resolve(kparam.context, keytab_name, &keytab);
    if (code)
    {
	fprintf(stderr, "%s| %s: Error while resolving keytab %s : %s\n", LogTime(), PROGRAM, keytab_name,error_message(code));
	retval=1;
	goto cleanup;
    }

    code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor);
    if (code)
    {
	fprintf(stderr, "%s| %s: Error while starting keytab scan : %s\n", LogTime(), PROGRAM, error_message(code));
	retval=1;
	goto cleanup;
    }
    if (margs->debug)
	fprintf(stderr, "%s| %s: Get principal name from keytab %s\n",LogTime(), PROGRAM, keytab_name);

    nprinc=0;
    while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) 
    {

        principal_list=realloc(principal_list,sizeof(krb5_principal)*(nprinc+1));
        krb5_copy_principal(kparam.context,entry.principal,&principal_list[nprinc++]);
	if (margs->debug)
#ifdef HAVE_HEIMDAL_KERBEROS
	    fprintf(stderr, "%s| %s: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, entry.principal->realm);
#else
	    fprintf(stderr, "%s| %s: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data);
#endif
#ifdef HAVE_HEIMDAL_KERBEROS
	    if (!strcasecmp(domain, entry.principal->realm))
#else
	    if (!strcasecmp(domain,krb5_princ_realm(kparam.context, entry.principal)->data))
#endif
	    {
		code = krb5_unparse_name(kparam.context, entry.principal, &principal_name);
		if (code)
		{
		    fprintf(stderr, "%s| %s: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code));
		} else {
		    if (margs->debug)
			fprintf(stderr, "%s| %s: Found principal name: %s\n", LogTime(), PROGRAM, principal_name);
		    found=1;
                }
	    }
#if defined(HAVE_HEIMDAL_KERBEROS) || ( defined(HAVE_KRB5_KT_FREE_ENTRY) && HAVE_DECL_KRB5_KT_FREE_ENTRY==1)
	code = krb5_kt_free_entry(kparam.context,&entry);
#else
	code = krb5_free_keytab_entry_contents(kparam.context,&entry);
#endif
	if (code)
        {
	    fprintf(stderr, "%s| %s: Error while freeing keytab entry : %s\n", LogTime(), PROGRAM, error_message(code));
	    retval=1;
	    break;
        }
        if (found) 
            break;
    }

    if (code && code != KRB5_KT_END) 
    {
	fprintf(stderr, "%s| %s: Error while scanning keytab : %s\n", LogTime(), PROGRAM, error_message(code));
	retval=1;
	goto cleanup;
    }

    code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor);
    if (code)
    {
	fprintf(stderr, "%s| %s: Error while ending keytab scan : %s\n", LogTime(), PROGRAM, error_message(code));
	retval=1;
	goto cleanup;
    }

    /*
     * prepare memory credential cache
     */
#ifndef HAVE_KRB5_MEMORY_CACHE
    mem_cache=malloc(strlen("FILE:/tmp/squid_ldap_")+16);
    snprintf(mem_cache,strlen("FILE:/tmp/squid_ldap_")+16,"FILE:/tmp/squid_ldap_%d",(int)getpid());
#else    
    mem_cache=malloc(strlen("MEMORY:squid_ldap_")+16);
    snprintf(mem_cache,strlen("MEMORY:squid_ldap_")+16,"MEMORY:squid_ldap_%d",(int)getpid());
#endif    
    
    setenv("KRB5CCNAME",mem_cache,1);
    if (margs->debug)
	fprintf(stderr, "%s| %s: Set credential cache to %s\n",LogTime(), PROGRAM,mem_cache);
    code = krb5_cc_resolve(kparam.context, mem_cache , &kparam.cc);
    if (code) 
    {
	fprintf(stderr, "%s| %s: Error while resolving memory ccache : %s\n",LogTime(), PROGRAM, error_message(code));
	retval=1;
	goto cleanup;
    }

    /*
     * if no principal name found in keytab for domain use the prinipal name which can get a TGT
     */
    if (!principal_name)
    {
	if (margs->debug) {
	    fprintf(stderr, "%s| %s: Did not find a principal in keytab for domain %s.\n",LogTime(), PROGRAM,domain);
	    fprintf(stderr, "%s| %s: Try to get principal of trusted domain.\n",LogTime(), PROGRAM);
	}
	creds = malloc(sizeof(*creds));
	memset(creds, 0, sizeof(*creds));

        for (i=0;i<nprinc;i++) {	
            /*
             * get credentials
             */
            code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name);
            if (code)
            {
                if (margs->debug)
                    fprintf(stderr, "%s| %s: Error while unparsing principal name : %s\n", LogTime(), PROGRAM, error_message(code));
		goto loop_end;
            }
	    if (margs->debug)
	        fprintf(stderr, "%s| %s: Keytab entry has principal: %s\n", LogTime(), PROGRAM, principal_name);

#if HAVE_GET_INIT_CREDS_KEYTAB
            code = krb5_get_init_creds_keytab(kparam.context, creds, principal_list[i], keytab, 0, NULL, NULL);
#else
            service=malloc(strlen("krbtgt")+2*strlen(domain)+3);
            snprintf(service,strlen("krbtgt")+2*strlen(domain)+3,"krbtgt/%s@%s",domain,domain);
            creds->client=principal_list[i];
            code = krb5_parse_name(kparam.context,service,&creds->server);
            if (service)
               free(service);
            code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
#endif
            if (code)
            {
		if (margs->debug)
		    fprintf(stderr, "%s| %s: Error while initialising credentials from keytab : %s\n",LogTime(), PROGRAM, error_message(code));
		goto loop_end;
            }

            code = krb5_cc_initialize(kparam.context, kparam.cc, principal_list[i]);
            if (code)
            {
                fprintf(stderr, "%s| %s: Error while initializing memory caches : %s\n",LogTime(), PROGRAM, error_message(code));
		goto loop_end;
            }

	    code = krb5_cc_store_cred(kparam.context, kparam.cc, creds);
	    if (code)
	    {
	        if (margs->debug)
		    fprintf(stderr, "%s| %s: Error while storing credentials : %s\n",LogTime(), PROGRAM, error_message(code));
		goto loop_end;
    	    }

            if (creds->server)
               krb5_free_principal(kparam.context,creds->server);
#ifdef HAVE_HEIMDAL_KERBEROS
            service=malloc(strlen("krbtgt")+strlen(domain)+strlen(principal_list[i]->realm)+3);
            snprintf(service,strlen("krbtgt")+strlen(domain)+strlen(principal_list[i]->realm)+3,"krbtgt/%s@%s",domain,principal_list[i]->realm);
#else
            service=malloc(strlen("krbtgt")+strlen(domain)+strlen(krb5_princ_realm(kparam.context, principal_list[i])->data)+3);
            snprintf(service,strlen("krbtgt")+strlen(domain)+strlen(krb5_princ_realm(kparam.context, principal_list[i])->data)+3,"krbtgt/%s@%s",domain,krb5_princ_realm(kparam.context, principal_list[i])->data);
#endif
            code = krb5_parse_name(kparam.context,service,&creds->server);
            if (service)
               free(service);
	    if (code)
	    {
		fprintf(stderr, "%s| %s: Error while initialising TGT credentials : %s\n",LogTime(), PROGRAM, error_message(code));
		goto loop_end;
	    }

	    code = krb5_get_credentials(kparam.context, 0, kparam.cc, creds, &tgt_creds);
	    if (code) {
		if (margs->debug)
		    fprintf(stderr, "%s| %s: Error while getting tgt : %s\n",LogTime(), PROGRAM, error_message(code));
		goto loop_end;
	    } else {
		if (margs->debug)
		    fprintf(stderr, "%s| %s: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name);
		break;
	    }

loop_end:
            if (principal_name) 
	        free(principal_name);
            principal_name=NULL;
	}
            
	if (tgt_creds)
	    krb5_free_creds(kparam.context,tgt_creds);
        tgt_creds=NULL;
	if (creds)
	    krb5_free_creds(kparam.context,creds);
        creds=NULL;
    }


    if (principal_name) {

	if (margs->debug)
	    fprintf(stderr, "%s| %s: Got principal name %s\n",LogTime(), PROGRAM, principal_name);
	/*
	 * build principal
	 */
	code = krb5_parse_name(kparam.context, principal_name, &principal);
	if (code)
	{
	    fprintf(stderr, "%s| %s: Error while parsing name %s : %s\n", LogTime(), PROGRAM, principal_name,error_message(code));
	    retval=1;
	    goto cleanup;
	}
  
	creds = malloc(sizeof(*creds));
	memset(creds, 0, sizeof(*creds));

	/*
	 * get credentials
	 */
#if HAVE_GET_INIT_CREDS_KEYTAB
        code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, NULL, NULL);
#else
        service=malloc(strlen("krbtgt")+2*strlen(domain)+3);
        snprintf(service,strlen("krbtgt")+2*strlen(domain)+3,"krbtgt/%s@%s",domain,domain);
        creds->client=principal;
        code = krb5_parse_name(kparam.context,service,&creds->server);
        if (service)
           free(service);
        code = krb5_get_in_tkt_with_keytab(kparam.context, 0, NULL, NULL, NULL, keytab, NULL, creds, 0);
#endif
	if (code)
	{
	    fprintf(stderr, "%s| %s: Error while initialising credentials from keytab : %s\n",LogTime(), PROGRAM, error_message(code));
	    retval=1;
	    goto cleanup;
	}

        code = krb5_cc_initialize(kparam.context, kparam.cc, principal);
        if (code)
        {
            fprintf(stderr, "%s| %s: Error while initializing memory caches : %s\n",LogTime(), PROGRAM, error_message(code));
            retval=1;
            goto cleanup;
        }

	code = krb5_cc_store_cred(kparam.context, kparam.cc, creds);
	if (code) 
	{
	    fprintf(stderr, "%s| %s: Error while storing credentials : %s\n",LogTime(), PROGRAM, error_message(code));
	    retval=1;
	    goto cleanup;
	}
	if (margs->debug)
	    fprintf(stderr, "%s| %s: Stored credentials\n",LogTime(), PROGRAM);
    } else {
	if (margs->debug)
	    fprintf(stderr, "%s| %s: Got no principal name\n",LogTime(), PROGRAM);
	retval=1;
    }
 cleanup:
    if (keytab)
        krb5_kt_close(kparam.context, keytab);
    if (keytab_name)
	free(keytab_name);
    if (principal_name)
	free(principal_name);
    if (mem_cache)
	free(mem_cache);
    if (principal)
	krb5_free_principal(kparam.context,principal);
    for (i=0;i<nprinc;i++) {
        if (principal_list[i])
	    krb5_free_principal(kparam.context,principal_list[i]);
    }
    if (principal_list)
        free(principal_list);
    if (creds)
	krb5_free_creds(kparam.context,creds);

    return(retval);
}