Example #1
0
File: ccfns.c Project: OPSF/uClinux
krb5_error_code KRB5_CALLCONV
krb5_cc_store_cred (krb5_context context, krb5_ccache cache,
		    krb5_creds *creds)
{
    krb5_error_code ret;
    krb5_ticket *tkt;
    krb5_principal s1, s2;

    /* remove any dups */
    krb5_cc_remove_cred(context, cache, 0, creds);

    ret = cache->ops->store(context, cache, creds);
    if (ret) return ret;

    /*
     * If creds->server and the server in the decoded ticket differ,
     * store both principals.
     */
    s1 = creds->server;
    ret = decode_krb5_ticket(&creds->ticket, &tkt);
    /* Bail out on errors in case someone is storing a non-ticket. */
    if (ret) return 0;
    s2 = tkt->server;
    if (!krb5_principal_compare(context, s1, s2)) {
        creds->server = s2;
        /* remove any dups */
        krb5_cc_remove_cred(context, cache, 0, creds);
        ret = cache->ops->store(context, cache, creds);
        creds->server = s1;
    }
    krb5_free_ticket(context, tkt);
    return ret;
}
Example #2
0
krb5_error_code KRB5_CALLCONV
krb5_cc_set_config(krb5_context context, krb5_ccache id,
                   krb5_const_principal principal,
                   const char *key, krb5_data *data)
{
    krb5_error_code ret;
    krb5_creds cred;
    memset(&cred, 0, sizeof(cred));

    TRACE_CC_SET_CONFIG(context, id, principal, key, data);

    ret = k5_build_conf_principals(context, id, principal, key, &cred);
    if (ret)
        goto out;

    if (data == NULL) {
        ret = krb5_cc_remove_cred(context, id, 0, &cred);
    } else {
        ret = krb5int_copy_data_contents(context, data, &cred.ticket);
        if (ret)
            goto out;
        ret = krb5_cc_store_cred(context, id, &cred);
    }
out:
    krb5_free_cred_contents(context, &cred);
    return ret;
}
Example #3
0
/*
 * The krb5_cc_remove_cred() function is defined in the MIT API documentation,
 * however it is not implemented.  So we don't bother trying to call it...
 */
krb5_error_code clear_old_certs(krb5_context k5_context,
								krb5_ccache cc,
								krb5_creds *creds)
{
	if (krb5_cc_remove_cred(k5_context, cc, XXX, creds))
	{
		log_printf("clear_old_certs: unable to initialize K5 context (%d)\n", k5_rc);
		return -1;
	}
	return 0;
}
Example #4
0
/*
 * Indicate the we failed to log in to this service/host with these
 * credentials.  The caller passes an unsigned int which they
 * initialise to the number of times they would like to retry.
 *
 * This method is used to support re-trying with freshly fetched
 * credentials in case a server is rebuilt while clients have
 * non-expired tickets. When the client code gets a logon failure they
 * throw away the existing credentials for the server and retry.
 */
_PUBLIC_ bool cli_credentials_failed_kerberos_login(struct cli_credentials *cred,
						    const char *principal,
						    unsigned int *count)
{
	struct ccache_container *ccc;
	krb5_creds creds, creds2;
	int ret;

	if (principal == NULL) {
		/* no way to delete if we don't know the principal */
		return false;
	}

	ccc = cred->ccache;
	if (ccc == NULL) {
		/* not a kerberos connection */
		return false;
	}

	if (*count > 0) {
		/* We have already tried discarding the credentials */
		return false;
	}
	(*count)++;

	ZERO_STRUCT(creds);
	ret = krb5_parse_name(ccc->smb_krb5_context->krb5_context, principal, &creds.server);
	if (ret != 0) {
		return false;
	}

	ret = krb5_cc_retrieve_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds, &creds2);
	if (ret != 0) {
		/* don't retry - we didn't find these credentials to remove */
		krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds);
		return false;
	}

	ret = krb5_cc_remove_cred(ccc->smb_krb5_context->krb5_context, ccc->ccache, KRB5_TC_MATCH_SRV_NAMEONLY, &creds);
	krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds);
	krb5_free_cred_contents(ccc->smb_krb5_context->krb5_context, &creds2);
	if (ret != 0) {
		/* don't retry - we didn't find these credentials to
		 * remove. Note that with the current backend this
		 * never happens, as it always returns 0 even if the
		 * creds don't exist, which is why we do a separate
		 * krb5_cc_retrieve_cred() above.
		 */
		return false;
	}
	return true;
}
Example #5
0
static void
test_fcache_remove(krb5_context context)
{
    krb5_error_code ret;
    krb5_ccache id;
    krb5_principal p;
    krb5_creds cred;

    ret = krb5_parse_name(context, "*****@*****.**", &p);
    if (ret)
	krb5_err(context, 1, ret, "krb5_parse_name");

    ret = krb5_cc_gen_new(context, &krb5_fcc_ops, &id);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_gen_new");

    ret = krb5_cc_initialize(context, id, p);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_initialize");

    /* */
    memset(&cred, 0, sizeof(cred));
    ret = krb5_parse_name(context, "krbtgt/[email protected]", &cred.server);
    if (ret)
	krb5_err(context, 1, ret, "krb5_parse_name");
    ret = krb5_parse_name(context, "*****@*****.**", &cred.client);
    if (ret)
	krb5_err(context, 1, ret, "krb5_parse_name");

    ret = krb5_cc_store_cred(context, id, &cred);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_store_cred");

    ret = krb5_cc_remove_cred(context, id, 0, &cred);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_remove_cred");

    ret = krb5_cc_destroy(context, id);
    if (ret)
	krb5_err(context, 1, ret, "krb5_cc_destroy");

    krb5_free_principal(context, p);
    krb5_free_principal(context, cred.server);
    krb5_free_principal(context, cred.client);
}
Example #6
0
static krb5_error_code
check_cc(krb5_context context, krb5_flags options, krb5_ccache ccache,
	 krb5_creds *in_creds, krb5_creds *out_creds)
{
    krb5_error_code ret;
    krb5_timestamp timeret;

    /*
     * If we got a credential, check if credential is expired before
     * returning it.
     */
    ret = krb5_cc_retrieve_cred(context, ccache,
				options & KRB5_TC_MATCH_KEYTYPE,
                                in_creds, out_creds);
    if (ret != 0)
	return ret; /* Caller will check for KRB5_CC_END */

    /*
     * If we got a credential, check if credential is expired before
     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
     */

    /* If expired ok, don't bother checking */
    if (options & KRB5_GC_EXPIRED_OK)
	return 0;

    krb5_timeofday(context, &timeret);
    if (out_creds->times.endtime > timeret)
	return 0;

    /* Expired and not ok; remove and pretend we didn't find it */
    if (options & KRB5_GC_CACHED)
	krb5_cc_remove_cred(context, ccache, 0, out_creds);

    krb5_free_cred_contents(context, out_creds);
    memset(out_creds, 0, sizeof (*out_creds));
    return KRB5_CC_END;
}
Example #7
0
static BOOL ads_cleanup_expired_creds(krb5_context context, 
				      krb5_ccache  ccache,
				      krb5_creds  *credsp)
{
	krb5_error_code retval;
	const char *cc_type = krb5_cc_get_type(context, ccache);

	DEBUG(3, ("ads_cleanup_expired_creds: Ticket in ccache[%s:%s] expiration %s\n",
		  cc_type, krb5_cc_get_name(context, ccache),
		  http_timestring(credsp->times.endtime)));

	/* we will probably need new tickets if the current ones
	   will expire within 10 seconds.
	*/
	if (credsp->times.endtime >= (time(NULL) + 10))
		return False;

	/* heimdal won't remove creds from a file ccache, and 
	   perhaps we shouldn't anyway, since internally we 
	   use memory ccaches, and a FILE one probably means that
	   we're using creds obtained outside of our exectuable
	*/
	if (strequal(cc_type, "FILE")) {
		DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a %s ccache\n", cc_type));
		return False;
	}

	retval = krb5_cc_remove_cred(context, ccache, 0, credsp);
	if (retval) {
		DEBUG(1, ("ads_cleanup_expired_creds: krb5_cc_remove_cred failed, err %s\n",
			  error_message(retval)));
		/* If we have an error in this, we want to display it,
		   but continue as though we deleted it */
	}
	return True;
}
Example #8
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_creds(krb5_context context,
	       krb5_get_creds_opt opt,
	       krb5_ccache ccache,
	       krb5_const_principal inprinc,
	       krb5_creds **out_creds)
{
    krb5_kdc_flags flags;
    krb5_flags options;
    krb5_creds in_creds;
    krb5_error_code ret;
    krb5_creds **tgts;
    krb5_creds *res_creds;
    int i;

    if (opt && opt->enctype) {
	ret = krb5_enctype_valid(context, opt->enctype);
	if (ret)
	    return ret;
    }

    memset(&in_creds, 0, sizeof(in_creds));
    in_creds.server = rk_UNCONST(inprinc);

    ret = krb5_cc_get_principal(context, ccache, &in_creds.client);
    if (ret)
	return ret;

    if (opt)
	options = opt->options;
    else
	options = 0;
    flags.i = 0;

    *out_creds = NULL;
    res_creds = calloc(1, sizeof(*res_creds));
    if (res_creds == NULL) {
	krb5_free_principal(context, in_creds.client);
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    if (opt && opt->enctype) {
	in_creds.session.keytype = opt->enctype;
	options |= KRB5_TC_MATCH_KEYTYPE;
    }

    /*
     * If we got a credential, check if credential is expired before
     * returning it.
     */
    ret = krb5_cc_retrieve_cred(context,
                                ccache,
				options & KRB5_TC_MATCH_KEYTYPE,
                                &in_creds, res_creds);
    /*
     * If we got a credential, check if credential is expired before
     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
     */
    if (ret == 0) {
	krb5_timestamp timeret;

	/* If expired ok, don't bother checking */
        if(options & KRB5_GC_EXPIRED_OK) {
            *out_creds = res_creds;
	    krb5_free_principal(context, in_creds.client);
            goto out;
        }
	
	krb5_timeofday(context, &timeret);
	if(res_creds->times.endtime > timeret) {
	    *out_creds = res_creds;
	    krb5_free_principal(context, in_creds.client);
            goto out;
	}
	if(options & KRB5_GC_CACHED)
	    krb5_cc_remove_cred(context, ccache, 0, res_creds);

    } else if(ret != KRB5_CC_END) {
        free(res_creds);
	krb5_free_principal(context, in_creds.client);
	goto out;
    }
    free(res_creds);
    if(options & KRB5_GC_CACHED) {
	krb5_free_principal(context, in_creds.client);
	ret = not_found(context, in_creds.server, KRB5_CC_NOTFOUND);
	goto out;
    }
    if(options & KRB5_GC_USER_USER) {
	flags.b.enc_tkt_in_skey = 1;
	options |= KRB5_GC_NO_STORE;
    }
    if (options & KRB5_GC_FORWARDABLE)
	flags.b.forwardable = 1;
    if (options & KRB5_GC_NO_TRANSIT_CHECK)
	flags.b.disable_transited_check = 1;
    if (options & KRB5_GC_CONSTRAINED_DELEGATION) {
	flags.b.request_anonymous = 1; /* XXX ARGH confusion */
	flags.b.constrained_delegation = 1;
    }
    if (options & KRB5_GC_CANONICALIZE)
	flags.b.canonicalize = 1;

    tgts = NULL;
    ret = _krb5_get_cred_kdc_any(context, flags, ccache,
				 &in_creds, opt->self, opt->ticket,
				 out_creds, &tgts);
    krb5_free_principal(context, in_creds.client);
    for(i = 0; tgts && tgts[i]; i++) {
	krb5_cc_store_cred(context, ccache, tgts[i]);
	krb5_free_creds(context, tgts[i]);
    }
    free(tgts);
    if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0)
	krb5_cc_store_cred(context, ccache, *out_creds);

 out:
    _krb5_debug(context, 5, "krb5_get_creds: ret = %d", ret);

    return ret;
}
Example #9
0
KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_get_credentials_with_flags(krb5_context context,
				krb5_flags options,
				krb5_kdc_flags flags,
				krb5_ccache ccache,
				krb5_creds *in_creds,
				krb5_creds **out_creds)
{
    krb5_error_code ret;
    krb5_creds **tgts;
    krb5_creds *res_creds;
    int i;

    if (in_creds->session.keytype) {
	ret = krb5_enctype_valid(context, in_creds->session.keytype);
	if (ret)
	    return ret;
    }

    *out_creds = NULL;
    res_creds = calloc(1, sizeof(*res_creds));
    if (res_creds == NULL) {
	krb5_set_error_message(context, ENOMEM,
			       N_("malloc: out of memory", ""));
	return ENOMEM;
    }

    if (in_creds->session.keytype)
	options |= KRB5_TC_MATCH_KEYTYPE;

    /*
     * If we got a credential, check if credential is expired before
     * returning it.
     */
    ret = krb5_cc_retrieve_cred(context,
                                ccache,
                                in_creds->session.keytype ?
                                KRB5_TC_MATCH_KEYTYPE : 0,
                                in_creds, res_creds);
    /*
     * If we got a credential, check if credential is expired before
     * returning it, but only if KRB5_GC_EXPIRED_OK is not set.
     */
    if (ret == 0) {
	krb5_timestamp timeret;

	/* If expired ok, don't bother checking */
        if(options & KRB5_GC_EXPIRED_OK) {
            *out_creds = res_creds;
            return 0;
        }
	
	krb5_timeofday(context, &timeret);
	if(res_creds->times.endtime > timeret) {
	    *out_creds = res_creds;
	    return 0;
	}
	if(options & KRB5_GC_CACHED)
	    krb5_cc_remove_cred(context, ccache, 0, res_creds);

    } else if(ret != KRB5_CC_END) {
        free(res_creds);
        return ret;
    }
    free(res_creds);
    if(options & KRB5_GC_CACHED)
	return not_found(context, in_creds->server, KRB5_CC_NOTFOUND);

    if(options & KRB5_GC_USER_USER)
	flags.b.enc_tkt_in_skey = 1;
    if (flags.b.enc_tkt_in_skey)
	options |= KRB5_GC_NO_STORE;

    tgts = NULL;
    ret = _krb5_get_cred_kdc_any(context, flags, ccache,
				 in_creds, NULL, NULL, out_creds, &tgts);
    for(i = 0; tgts && tgts[i]; i++) {
	krb5_cc_store_cred(context, ccache, tgts[i]);
	krb5_free_creds(context, tgts[i]);
    }
    free(tgts);
    if(ret == 0 && (options & KRB5_GC_NO_STORE) == 0)
	krb5_cc_store_cred(context, ccache, *out_creds);
    return ret;
}
Example #10
0
static krb5_error_code
fcc_remove_cred(krb5_context context,
		 krb5_ccache id,
		 krb5_flags which,
		 krb5_creds *cred)
{
    krb5_error_code ret;
    krb5_ccache copy, newfile;
    char *newname;
    int fd;

    ret = krb5_cc_new_unique(context, krb5_cc_type_memory, NULL, &copy);
    if (ret)
	return ret;

    ret = krb5_cc_copy_cache(context, id, copy);
    if (ret) {
	krb5_cc_destroy(context, copy);
	return ret;
    }

    ret = krb5_cc_remove_cred(context, copy, which, cred);
    if (ret) {
	krb5_cc_destroy(context, copy);
	return ret;
    }

    asprintf(&newname, "FILE:%s.XXXXXX", FILENAME(id));
    if (newname == NULL) {
	krb5_cc_destroy(context, copy);
	return ret;
    }

    fd = mkstemp(&newname[5]);
    if (fd < 0) {
	ret = errno;
	krb5_cc_destroy(context, copy);
	return ret;
    }
    close(fd);

    ret = krb5_cc_resolve(context, newname, &newfile);
    if (ret) {
	unlink(&newname[5]);
	free(newname);
	krb5_cc_destroy(context, copy);
	return ret;
    }

    ret = krb5_cc_copy_cache(context, copy, newfile);
    krb5_cc_destroy(context, copy);
    if (ret) {
	free(newname);
	krb5_cc_destroy(context, newfile);
	return ret;
    }

    ret = rename(&newname[5], FILENAME(id));
    if (ret)
	ret = errno;
    free(newname);
    krb5_cc_close(context, newfile);

    return ret;
}
Example #11
0
int
main (int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache  ccache;
    int optidx = 0;
    int exit_val = 0;

    setprogname (argv[0]);

    if(getarg(args, num_args, argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

    if(version_flag){
	print_version(NULL);
	exit(0);
    }

    argc -= optidx;
    argv += optidx;

    if (argc != 0)
	usage (1);

    ret = krb5_init_context (&context);
    if (ret)
	errx (1, "krb5_init_context failed: %d", ret);

    if (all_flag) {
	krb5_cccol_cursor cursor;

	ret = krb5_cccol_cursor_new (context, &cursor);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cccol_cursor_new");

	while (krb5_cccol_cursor_next (context, cursor, &ccache) == 0 && ccache != NULL) {

	    ret = krb5_cc_destroy (context, ccache);
	    if (ret) {
		krb5_warn(context, ret, "krb5_cc_destroy");
		exit_val = 1;
	    }
	}
	krb5_cccol_cursor_free(context, &cursor);

    } else {
	if(cache == NULL) {
	    ret = krb5_cc_default(context, &ccache);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_cc_default");
	} else {
	    ret =  krb5_cc_resolve(context,
				   cache,
				   &ccache);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_cc_resolve");
	}

	if (ret == 0) {
	    if (credential) {
		krb5_creds mcred;

		krb5_cc_clear_mcred(&mcred);

		ret = krb5_parse_name(context, credential, &mcred.server);
		if (ret)
		    krb5_err(context, 1, ret,
			     "Can't parse principal %s", credential);

		ret = krb5_cc_remove_cred(context, ccache, 0, &mcred);
		if (ret)
		    krb5_err(context, 1, ret,
			     "Failed to remove principal %s", credential);

		krb5_cc_close(context, ccache);
		krb5_free_principal(context, mcred.server);
		krb5_free_context(context);
		return 0;
	    }

	    ret = krb5_cc_destroy (context, ccache);
	    if (ret) {
		krb5_warn(context, ret, "krb5_cc_destroy");
		exit_val = 1;
	    }
	}
    }

    krb5_free_context (context);

#ifndef NO_AFS
    if (unlog_flag && k_hasafs ()) {
	if (k_unlog ())
	    exit_val = 1;
    }
#endif

    return exit_val;
}