krb5_error_code KRB5_LIB_FUNCTION
krb5_get_in_tkt_with_skey (krb5_context context,
			   krb5_flags options,
			   krb5_addresses *addrs,
			   const krb5_enctype *etypes,
			   const krb5_preauthtype *pre_auth_types,
			   const krb5_keyblock *key,
			   krb5_ccache ccache,
			   krb5_creds *creds,
			   krb5_kdc_rep *ret_as_reply)
{
    if(key == NULL)
	return krb5_get_in_tkt_with_keytab (context,
					    options,
					    addrs,
					    etypes,
					    pre_auth_types,
					    NULL,
					    ccache,
					    creds,
					    ret_as_reply);
    else
	return krb5_get_in_tkt (context,
				options,
				addrs,
				etypes,
				pre_auth_types,
				krb5_skey_key_proc,
				key,
				NULL,
				NULL,
				creds,
				ccache,
				ret_as_reply);
}
Esempio n. 2
0
/*
  Similar to krb5_get_in_tkt_with_password.

  Attempts to get an initial ticket for creds->client to use server
  creds->server, (realm is taken from creds->client), with options
  options, and using creds->times.starttime, creds->times.endtime,
  creds->times.renew_till as from, till, and rtime.
  creds->times.renew_till is ignored unless the RENEWABLE option is requested.

  If addrs is non-NULL, it is used for the addresses requested.  If it is
  null, the system standard addresses are used.

  If keyblock is NULL, an appropriate key for creds->client is retrieved
  from the system key store (e.g. /etc/srvtab).  If keyblock is non-NULL,
  it is used as the decryption key.

  A succesful call will place the ticket in the credentials cache ccache.

  returns system errors, encryption errors

*/
krb5_error_code KRB5_CALLCONV
krb5_get_in_tkt_with_skey(krb5_context context, krb5_flags options,
                          krb5_address *const *addrs, krb5_enctype *ktypes,
                          krb5_preauthtype *pre_auth_types,
                          const krb5_keyblock *key, krb5_ccache ccache,
                          krb5_creds *creds, krb5_kdc_rep **ret_as_reply)
{
    krb5_error_code retval;
    char *server;
    krb5_principal server_princ, client_princ;
    int use_master = 0;
    krb5_get_init_creds_opt *opts = NULL;

#ifndef LEAN_CLIENT
    if (key == NULL) {
        return krb5_get_in_tkt_with_keytab(context, options, addrs, ktypes,
                                           pre_auth_types, NULL, ccache,
                                           creds, ret_as_reply);
    }
#endif /* LEAN_CLIENT */

    retval = krb5int_populate_gic_opt(context, &opts, options, addrs, ktypes,
                                      pre_auth_types, creds);
    if (retval)
        return retval;
    retval = krb5_unparse_name(context, creds->server, &server);
    if (retval) {
        krb5_get_init_creds_opt_free(context, opts);
        return retval;
    }
    server_princ = creds->server;
    client_princ = creds->client;
    retval = krb5int_get_init_creds(context, creds, creds->client,
                                    krb5_prompter_posix, NULL, 0, server, opts,
                                    get_as_key_skey, (void *) key, &use_master,
                                    ret_as_reply);
    krb5_free_unparsed_name(context, server);
    krb5_get_init_creds_opt_free(context, opts);
    if (retval)
        return retval;
    krb5_free_principal( context, creds->server);
    krb5_free_principal( context, creds->client);
    creds->client = client_princ;
    creds->server = server_princ;
    /* store it in the ccache! */
    if (ccache)
        retval = krb5_cc_store_cred(context, ccache, creds);
    return retval;
}
Esempio n. 3
0
/*
 * Get a ticket granting ticket and stuff it in the cache
 */
static const char *
get_tgt(
    char *	keytab_name,
    char *	principal_name)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_principal client = NULL, server = NULL;
    krb5_creds creds;
    krb5_keytab keytab;
    krb5_ccache ccache;
    krb5_timestamp now;
#ifdef KRB5_HEIMDAL_INCLUDES
    krb5_data tgtname = { KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME };
#else
    krb5_data tgtname = { 0, KRB5_TGS_NAME_SIZE, KRB5_TGS_NAME };
#endif
    static char *error = NULL;

    if (error != NULL) {
	amfree(error);
	error = NULL;
    }
    if ((ret = krb5_init_context(&context)) != 0) {
	error = vstrallocf(_("error initializing krb5 context: %s"),
	    error_message(ret));
	return (error);
    }

    /*krb5_init_ets(context);*/

    if(!keytab_name) {
        error = vstrallocf(_("error  -- no krb5 keytab defined"));
        return(error);
    }

    if(!principal_name) {
        error = vstrallocf(_("error  -- no krb5 principal defined"));
        return(error);
    }

    /*
     * Resolve keytab file into a keytab object
     */
    if ((ret = krb5_kt_resolve(context, keytab_name, &keytab)) != 0) {
	error = vstrallocf(_("error resolving keytab %s: %s"), keytab_name, 
	    error_message(ret));
	return (error);
    }

    /*
     * Resolve the amanda service held in the keytab into a principal
     * object
     */
    ret = krb5_parse_name(context, principal_name, &client);
    if (ret != 0) {
	error = vstrallocf(_("error parsing %s: %s"), principal_name,
	    error_message(ret));
	return (error);
    }

#ifdef KRB5_HEIMDAL_INCLUDES
    ret = krb5_build_principal_ext(context, &server,
        krb5_realm_length(*krb5_princ_realm(context, client)),
        krb5_realm_data(*krb5_princ_realm(context, client)),
        tgtname.length, tgtname.data,
        krb5_realm_length(*krb5_princ_realm(context, client)),
        krb5_realm_data(*krb5_princ_realm(context, client)),
        0);
#else
    ret = krb5_build_principal_ext(context, &server,
	krb5_princ_realm(context, client)->length,
	krb5_princ_realm(context, client)->data,
	tgtname.length, tgtname.data,
	krb5_princ_realm(context, client)->length,
	krb5_princ_realm(context, client)->data,
	0);
#endif
    if (ret != 0) {
	error = vstrallocf(_("error while building server name: %s"),
	    error_message(ret));
	return (error);
    }

    ret = krb5_timeofday(context, &now);
    if (ret != 0) {
	error = vstrallocf(_("error getting time of day: %s"), error_message(ret));
	return (error);
    }

    memset(&creds, 0, SIZEOF(creds));
    creds.times.starttime = 0;
    creds.times.endtime = now + AMANDA_TKT_LIFETIME;

    creds.client = client;
    creds.server = server;

    /*
     * Get a ticket for the service, using the keytab
     */
    ret = krb5_get_in_tkt_with_keytab(context, 0, NULL, NULL, NULL,
	keytab, 0, &creds, 0);

    if (ret != 0) {
	error = vstrallocf(_("error getting ticket for %s: %s"),
	    principal_name, error_message(ret));
	goto cleanup2;
    }

    if ((ret = krb5_cc_default(context, &ccache)) != 0) {
	error = vstrallocf(_("error initializing ccache: %s"), error_message(ret));
	goto cleanup;
    }
    if ((ret = krb5_cc_initialize(context, ccache, client)) != 0) {
	error = vstrallocf(_("error initializing ccache: %s"), error_message(ret));
	goto cleanup;
    }
    if ((ret = krb5_cc_store_cred(context, ccache, &creds)) != 0) {
	error = vstrallocf(_("error storing creds in ccache: %s"), 
	    error_message(ret));
	/* FALLTHROUGH */
    }
    krb5_cc_close(context, ccache);
cleanup:
    krb5_free_cred_contents(context, &creds);
cleanup2:
#if 0
    krb5_free_principal(context, client);
    krb5_free_principal(context, server);
#endif
    krb5_free_context(context);
    return (error);
}
Esempio n. 4
0
/*
 * 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);
}