Exemplo n.º 1
0
static krb5_error_code
find_cred(krb5_context context,
	  krb5_ccache id,
	  krb5_principal server,
	  krb5_creds **tgts,
	  krb5_creds *out_creds)
{
    krb5_error_code ret;
    krb5_creds mcreds;

    krb5_cc_clear_mcred(&mcreds);
    mcreds.server = server;
    ret = krb5_cc_retrieve_cred(context, id, KRB5_TC_DONT_MATCH_REALM,
				&mcreds, out_creds);
    if(ret == 0)
	return 0;
    while(tgts && *tgts){
	if(krb5_compare_creds(context, KRB5_TC_DONT_MATCH_REALM,
			      &mcreds, *tgts)){
	    ret = krb5_copy_creds_contents(context, *tgts, out_creds);
	    return ret;
	}
	tgts++;
    }
    return not_found(context, server, KRB5_CC_NOTFOUND);
}
Exemplo n.º 2
0
static void
ka_krb5_cc_clear_mcred (krb5_creds *mcred)
{
#if defined HAVE_KRB5_CC_CLEAR_MCRED
    krb5_cc_clear_mcred (mcred);
#else
    memset (mcred, 0, sizeof (krb5_creds));
#endif
}
Exemplo n.º 3
0
static int
check_for_tgt (krb5_context context,
	       krb5_ccache ccache,
	       krb5_principal principal,
	       time_t *expiration)
{
    krb5_error_code ret;
    krb5_creds pattern;
    krb5_creds creds;
    krb5_const_realm client_realm;
    int expired;

    krb5_cc_clear_mcred(&pattern);

    client_realm = krb5_principal_get_realm(context, principal);

    ret = krb5_make_principal (context, &pattern.server,
			       client_realm, KRB5_TGS_NAME, client_realm, NULL);
    if (ret)
	krb5_err (context, 1, ret, "krb5_make_principal");
    pattern.client = principal;

    ret = krb5_cc_retrieve_cred (context, ccache, 0, &pattern, &creds);
    krb5_free_principal (context, pattern.server);
    if (ret) {
	if (ret == KRB5_CC_END)
	    return 1;
	krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");
    }

    expired = time(NULL) > creds.times.endtime;

    if (expiration)
	*expiration = creds.times.endtime;

    krb5_free_cred_contents (context, &creds);

    return expired;
}
Exemplo n.º 4
0
static krb5_error_code
get_cred_kdc_referral(krb5_context context,
		      krb5_kdc_flags flags,
		      krb5_ccache ccache,
		      krb5_creds *in_creds,
		      krb5_principal impersonate_principal,
		      Ticket *second_ticket,			
		      krb5_creds **out_creds,
		      krb5_creds ***ret_tgts)
{
    krb5_const_realm client_realm;
    krb5_error_code ret;
    krb5_creds tgt, referral, ticket;
    int loop = 0;
    int ok_as_delegate = 1;

    if (in_creds->server->name.name_string.len < 2 && !flags.b.canonicalize) {
	krb5_set_error_message(context, KRB5KDC_ERR_PATH_NOT_ACCEPTED,
			       N_("Name too short to do referals, skipping", ""));
	return KRB5KDC_ERR_PATH_NOT_ACCEPTED;
    }

    memset(&tgt, 0, sizeof(tgt));
    memset(&ticket, 0, sizeof(ticket));

    flags.b.canonicalize = 1;

    *out_creds = NULL;

    client_realm = krb5_principal_get_realm(context, in_creds->client);

    /* find tgt for the clients base realm */
    {
	krb5_principal tgtname;
	
	ret = krb5_make_principal(context, &tgtname,
				  client_realm,
				  KRB5_TGS_NAME,
				  client_realm,
				  NULL);
	if(ret)
	    return ret;
	
	ret = find_cred(context, ccache, tgtname, *ret_tgts, &tgt);
	krb5_free_principal(context, tgtname);
	if (ret)
	    return ret;
    }

    referral = *in_creds;
    ret = krb5_copy_principal(context, in_creds->server, &referral.server);
    if (ret) {
	krb5_free_cred_contents(context, &tgt);
	return ret;
    }
    ret = krb5_principal_set_realm(context, referral.server, client_realm);
    if (ret) {
	krb5_free_cred_contents(context, &tgt);
	krb5_free_principal(context, referral.server);
	return ret;
    }

    while (loop++ < 17) {
	krb5_creds **tickets;
	krb5_creds mcreds;
	char *referral_realm;

	/* Use cache if we are not doing impersonation or contrainte deleg */
	if (impersonate_principal == NULL || flags.b.constrained_delegation) {
	    krb5_cc_clear_mcred(&mcreds);
	    mcreds.server = referral.server;
	    ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcreds, &ticket);
	} else
	    ret = EINVAL;

	if (ret) {
	    ret = get_cred_kdc_address(context, ccache, flags, NULL,
				       &referral, &tgt, impersonate_principal,
				       second_ticket, &ticket);
	    if (ret)
		goto out;
	}

	/* Did we get the right ticket ? */
	if (krb5_principal_compare_any_realm(context,
					     referral.server,
					     ticket.server))
	    break;

	if (!krb5_principal_is_krbtgt(context, ticket.server)) {
	    krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US,
				   N_("Got back an non krbtgt "
				      "ticket referrals", ""));
	    ret = KRB5KRB_AP_ERR_NOT_US;
	    goto out;
	}

	referral_realm = ticket.server->name.name_string.val[1];

	/* check that there are no referrals loops */
	tickets = *ret_tgts;

	krb5_cc_clear_mcred(&mcreds);
	mcreds.server = ticket.server;

	while(tickets && *tickets){
	    if(krb5_compare_creds(context,
				  KRB5_TC_DONT_MATCH_REALM,
				  &mcreds,
				  *tickets))
	    {
		krb5_set_error_message(context, KRB5_GET_IN_TKT_LOOP,
				       N_("Referral from %s "
					  "loops back to realm %s", ""),
				       tgt.server->realm,
				       referral_realm);
		ret = KRB5_GET_IN_TKT_LOOP;
                goto out;
	    }
	    tickets++;
	}	

	/* 
	 * if either of the chain or the ok_as_delegate was stripped
	 * by the kdc, make sure we strip it too.
	 */

	if (ok_as_delegate == 0 || ticket.flags.b.ok_as_delegate == 0) {
	    ok_as_delegate = 0;
	    ticket.flags.b.ok_as_delegate = 0;
	}

	ret = add_cred(context, &ticket, ret_tgts);
	if (ret)
	    goto out;

	/* try realm in the referral */
	ret = krb5_principal_set_realm(context,
				       referral.server,
				       referral_realm);
	krb5_free_cred_contents(context, &tgt);
	tgt = ticket;
	memset(&ticket, 0, sizeof(ticket));
	if (ret)
	    goto out;
    }

    ret = krb5_copy_creds(context, &ticket, out_creds);

out:
    krb5_free_principal(context, referral.server);
    krb5_free_cred_contents(context, &tgt);
    krb5_free_cred_contents(context, &ticket);
    return ret;
}
Exemplo n.º 5
0
static int
proto (int sock, const char *hostname, const char *service)
{
    struct sockaddr_in remote, local;
    socklen_t addrlen;
    krb5_address remote_addr, local_addr;
    krb5_context context;
    krb5_ccache ccache;
    krb5_auth_context auth_context;
    krb5_error_code status;
    krb5_principal client;
    krb5_data data;
    krb5_data packet;
    krb5_creds mcred, cred;
    krb5_ticket *ticket;

    addrlen = sizeof(local);
    if (getsockname (sock, (struct sockaddr *)&local, &addrlen) < 0
	|| addrlen != sizeof(local))
	err (1, "getsockname(%s)", hostname);

    addrlen = sizeof(remote);
    if (getpeername (sock, (struct sockaddr *)&remote, &addrlen) < 0
	|| addrlen != sizeof(remote))
	err (1, "getpeername(%s)", hostname);

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

    status = krb5_cc_default (context, &ccache);
    if (status)
	krb5_err(context, 1, status, "krb5_cc_default");

    status = krb5_auth_con_init (context, &auth_context);
    if (status)
	krb5_err(context, 1, status, "krb5_auth_con_init");

    local_addr.addr_type = AF_INET;
    local_addr.address.length = sizeof(local.sin_addr);
    local_addr.address.data   = &local.sin_addr;

    remote_addr.addr_type = AF_INET;
    remote_addr.address.length = sizeof(remote.sin_addr);
    remote_addr.address.data   = &remote.sin_addr;

    status = krb5_auth_con_setaddrs (context,
				     auth_context,
				     &local_addr,
				     &remote_addr);
    if (status)
	krb5_err(context, 1, status, "krb5_auth_con_setaddr");

    krb5_cc_clear_mcred(&mcred);

    status = krb5_cc_get_principal(context, ccache, &client);
    if(status)
	krb5_err(context, 1, status, "krb5_cc_get_principal");
    status = krb5_make_principal(context, &mcred.server,
				 krb5_principal_get_realm(context, client),
				 "krbtgt",
				 krb5_principal_get_realm(context, client),
				 NULL);
    if(status)
	krb5_err(context, 1, status, "krb5_make_principal");
    mcred.client = client;

    status = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
    if(status)
	krb5_err(context, 1, status, "krb5_cc_retrieve_cred");

    {
	char *client_name;
	krb5_data data;
	status = krb5_unparse_name(context, cred.client, &client_name);
	if(status)
	    krb5_err(context, 1, status, "krb5_unparse_name");
	data.data = client_name;
	data.length = strlen(client_name) + 1;
	status = krb5_write_message(context, &sock, &data);
	if(status)
	    krb5_err(context, 1, status, "krb5_write_message");
	free(client_name);
    }

    status = krb5_write_message(context, &sock, &cred.ticket);
    if(status)
	krb5_err(context, 1, status, "krb5_write_message");

    status = krb5_auth_con_setuserkey(context, auth_context, &cred.session);
    if(status)
	krb5_err(context, 1, status, "krb5_auth_con_setuserkey");

    status = krb5_recvauth(context, &auth_context, &sock,
			   VERSION, client, 0, NULL, &ticket);

    if (status)
	krb5_err(context, 1, status, "krb5_recvauth");

    if (ticket->ticket.authorization_data) {
	AuthorizationData *authz;
	int i;

	printf("Authorization data:\n");

	authz = ticket->ticket.authorization_data;
	for (i = 0; i < authz->len; i++) {
	    printf("\ttype %d, length %lu\n",
		   authz->val[i].ad_type,
		   (unsigned long)authz->val[i].ad_data.length);
	}
    }

    data.data   = "hej";
    data.length = 3;

    krb5_data_zero (&packet);

    status = krb5_mk_safe (context,
			   auth_context,
			   &data,
			   &packet,
			   NULL);
    if (status)
	krb5_err(context, 1, status, "krb5_mk_safe");

    status = krb5_write_message(context, &sock, &packet);
    if(status)
	krb5_err(context, 1, status, "krb5_write_message");

    data.data   = "hemligt";
    data.length = 7;

    krb5_data_free (&packet);

    status = krb5_mk_priv (context,
			   auth_context,
			   &data,
			   &packet,
			   NULL);
    if (status)
	krb5_err(context, 1, status, "krb5_mk_priv");

    status = krb5_write_message(context, &sock, &packet);
    if(status)
	krb5_err(context, 1, status, "krb5_write_message");
    return 0;
}
Exemplo n.º 6
0
static krb5_error_code
tkt_referral_recv(krb5_context context,
		  krb5_tkt_creds_context ctx,
		  krb5_data *in,
		  krb5_data *out,
		  krb5_realm *realm,
		  unsigned int *flags)
{
    krb5_error_code ret;
    krb5_creds outcred, mcred;
    unsigned long n;

    _krb5_debugx(context, 10, "tkt_referral_recv: %s", ctx->server_name);
    
    memset(&outcred, 0, sizeof(outcred));

    ret = parse_tgs_rep(context, ctx, in, &outcred);
    if (ret) {
	_krb5_debugx(context, 10, "tkt_referral_recv: parse_tgs_rep %d", ret);
	tkt_reset(context, ctx);
	ctx->state = tkt_capath_init;
	return 0;
    }
    
    /*
     * Check if we found the right ticket
     */
    
    if (krb5_principal_compare_any_realm(context, ctx->next.server, outcred.server)) {
	ret = krb5_copy_creds(context, &outcred, &ctx->cred);
	if (ret)
	    return (ctx->error = ret);
	krb5_free_cred_contents(context, &outcred);
	ctx->state = tkt_store;
	return 0;
    }

    if (!krb5_principal_is_krbtgt(context, outcred.server)) {
	krb5_set_error_message(context, KRB5KRB_AP_ERR_NOT_US,
			       N_("Got back an non krbtgt "
				      "ticket referrals", ""));
	krb5_free_cred_contents(context, &outcred);
	ctx->state = tkt_capath_init;
	return 0;
    }
    
    _krb5_debugx(context, 10, "KDC for realm %s sends a referrals to %s",
		ctx->tgt.server->realm, outcred.server->name.name_string.val[1]);

    /*
     * check if there is a loop
     */
    krb5_cc_clear_mcred(&mcred);
    mcred.server = outcred.server;

    for (n = 0; ctx->tickets && ctx->tickets[n]; n++) {
	if(krb5_compare_creds(context,
			      KRB5_TC_DONT_MATCH_REALM,
			      &mcred,
			      ctx->tickets[n]))
	{
	    _krb5_debugx(context, 5, "Referral from %s loops back to realm %s",
				    ctx->tgt.server->realm,
				    outcred.server->realm);
	    ctx->state = tkt_capath_init;
	    return 0;
	}
    }
#define MAX_KDC_REFERRALS_LOOPS 15
    if (n > MAX_KDC_REFERRALS_LOOPS) {
	ctx->state = tkt_capath_init;
	return 0;
    }

    /*
     * filter out ok-as-delegate if needed
     */
    
    if (ctx->ok_as_delegate == 0 || outcred.flags.b.ok_as_delegate == 0) {
	ctx->ok_as_delegate = 0;
	outcred.flags.b.ok_as_delegate = 0;
    }

    /* add to iteration cache */
    ret = add_cred(context, &outcred, &ctx->tickets);
    if (ret) {
	ctx->state = tkt_capath_init;
	return 0;
    }

    /* set up next server to talk to */
    krb5_free_cred_contents(context, &ctx->tgt);
    ctx->tgt = outcred;
    
    /*
     * Setup next target principal to target
     */

    ret = krb5_principal_set_realm(context, ctx->next.server,
				   ctx->tgt.server->realm);
    if (ret) {
	ctx->state = tkt_capath_init;
	return 0;
    }
    
    ctx->state = tkt_referral_send;
    
    return 0;
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    krb5_get_creds_opt opt;
    krb5_principal server;
    krb5_principal impersonate = NULL;

    setprogname (argv[0]);

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

    if(getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

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

    argc -= optidx;
    argv += optidx;

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

    if(cache_str) {
	ret = krb5_cc_resolve(context, cache_str, &cache);
	if (ret)
	    krb5_err (context, 1, ret, "%s", cache_str);
    } else {
	ret = krb5_cc_default (context, &cache);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");
    }

    ret = krb5_get_creds_opt_alloc(context, &opt);
    if (ret)
	krb5_err (context, 1, ret, "krb5_get_creds_opt_alloc");

    if (etype_str) {
	krb5_enctype enctype;

	ret = krb5_string_to_enctype(context, etype_str, &enctype);
	if (ret)
	    krb5_errx (context, 1, N_("unrecognized enctype: %s", ""),
		       etype_str);
	krb5_get_creds_opt_set_enctype(context, opt, enctype);
    }

    if (impersonate_str) {
	ret = krb5_parse_name(context, impersonate_str, &impersonate);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_parse_name %s", impersonate_str);
	krb5_get_creds_opt_set_impersonate(context, opt, impersonate);
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
    }

    if (out_cache_str)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);

    if (forwardable_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE);
    if (!transit_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK);
    if (canonicalize_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE);

    if (delegation_cred_str) {
	krb5_ccache id;
	krb5_creds c, mc;
	Ticket ticket;

	krb5_cc_clear_mcred(&mc);
	ret = krb5_cc_get_principal(context, cache, &mc.server);
	if (ret)
	    krb5_err (context, 1, ret, "krb5_cc_get_principal");

	ret = krb5_cc_resolve(context, delegation_cred_str, &id);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_retrieve_cred");

	ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL);
	if (ret) {
	    krb5_clear_error_message(context);
	    krb5_err (context, 1, ret, "decode_Ticket");
	}
	krb5_free_cred_contents(context, &c);

	ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_get_creds_opt_set_ticket");
	free_Ticket(&ticket);

	krb5_cc_close (context, id);
	krb5_free_principal(context, mc.server);

	krb5_get_creds_opt_add_options(context, opt,
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

    ret = krb5_parse_name(context, argv[0], &server);
    if (ret)
	krb5_err (context, 1, ret, "krb5_parse_name %s", argv[0]);

    if (nametype_str) {
	int32_t nametype;

	ret = krb5_parse_nametype(context, nametype_str, &nametype);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_nametype");

	server->name.name_type = (NAME_TYPE)nametype;
    }

    ret = krb5_get_creds(context, opt, cache, server, &out);
    if (ret)
	krb5_err (context, 1, ret, "krb5_get_creds");

    if (out_cache_str) {
	krb5_ccache id;

	ret = krb5_cc_resolve(context, out_cache_str, &id);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_initialize(context, id, out->client);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, out);
	if(ret)
	    krb5_err (context, 1, ret, "krb5_cc_store_cred");
	krb5_cc_close (context, id);
    }

    krb5_free_creds(context, out);
    krb5_free_principal(context, server);
    krb5_get_creds_opt_free(context, opt);
    krb5_cc_close (context, cache);
    krb5_free_context (context);

    return 0;
}
Exemplo n.º 9
0
int
main(int argc, char **argv)
{
    krb5_error_code ret;
    krb5_context context;
    krb5_ccache cache;
    krb5_creds *out;
    int optidx = 0;
    int32_t nametype = KRB5_NT_UNKNOWN;
    krb5_get_creds_opt opt;
    krb5_principal server = NULL;
    krb5_principal impersonate;

    setprogname(argv[0]);

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

    if (getarg(args, sizeof(args) / sizeof(args[0]), argc, argv, &optidx))
	usage(1);

    if (help_flag)
	usage (0);

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

    argc -= optidx;
    argv += optidx;

    if (debug_flag) {
        ret = krb5_set_debug_dest(context, getprogname(), "STDERR");
        if (ret)
            krb5_warn(context, ret, "krb5_set_debug_dest");
    }

    if (cache_str) {
	ret = krb5_cc_resolve(context, cache_str, &cache);
	if (ret)
	    krb5_err(context, 1, ret, "%s", cache_str);
    } else {
	ret = krb5_cc_default (context, &cache);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve");
    }

    ret = krb5_get_creds_opt_alloc(context, &opt);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_creds_opt_alloc");

    if (etype_str) {
	krb5_enctype enctype;

	ret = krb5_string_to_enctype(context, etype_str, &enctype);
	if (ret)
	    krb5_errx(context, 1, N_("unrecognized enctype: %s", ""),
		      etype_str);
	krb5_get_creds_opt_set_enctype(context, opt, enctype);
    }

    if (impersonate_str) {
	ret = krb5_parse_name(context, impersonate_str, &impersonate);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name %s", impersonate_str);
	krb5_get_creds_opt_set_impersonate(context, opt, impersonate);
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
        krb5_free_principal(context, impersonate);
    }

    if (out_cache_str)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);

    if (forwardable_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_FORWARDABLE);
    if (!transit_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_TRANSIT_CHECK);
    if (canonicalize_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CANONICALIZE);
    if (!store_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_NO_STORE);
    if (cached_only_flag)
	krb5_get_creds_opt_add_options(context, opt, KRB5_GC_CACHED);

    if (delegation_cred_str) {
	krb5_ccache id;
	krb5_creds c, mc;
	Ticket ticket;

	krb5_cc_clear_mcred(&mc);
	ret = krb5_cc_get_principal(context, cache, &mc.server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_cc_get_principal");

	ret = krb5_cc_resolve(context, delegation_cred_str, &id);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_retrieve_cred(context, id, 0, &mc, &c);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_retrieve_cred");

	ret = decode_Ticket(c.ticket.data, c.ticket.length, &ticket, NULL);
	if (ret) {
	    krb5_clear_error_message(context);
	    krb5_err(context, 1, ret, "decode_Ticket");
	}
	krb5_free_cred_contents(context, &c);

	ret = krb5_get_creds_opt_set_ticket(context, opt, &ticket);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_get_creds_opt_set_ticket");
	free_Ticket(&ticket);

	krb5_cc_close(context, id);
	krb5_free_principal(context, mc.server);

	krb5_get_creds_opt_add_options(context, opt,
				       KRB5_GC_CONSTRAINED_DELEGATION);
    }

    if (nametype_str != NULL) {
        ret = krb5_parse_nametype(context, nametype_str, &nametype);
        if (ret)
            krb5_err(context, 1, ret, "krb5_parse_nametype");
    }

    if (nametype == KRB5_NT_SRV_HST ||
        nametype == KRB5_NT_SRV_HST_NEEDS_CANON)
        is_hostbased_flag = 1;

    if (is_hostbased_flag) {
	const char *sname = NULL;
	const char *hname = NULL;

        if (nametype_str != NULL &&
            nametype != KRB5_NT_SRV_HST &&
            nametype != KRB5_NT_SRV_HST_NEEDS_CANON)
            krb5_errx(context, 1, "--hostbased not compatible with "
                      "non-hostbased --name-type");

        if (is_canonical_flag)
            nametype = KRB5_NT_SRV_HST;
        else
            nametype = KRB5_NT_SRV_HST_NEEDS_CANON;

        /*
         * Host-based service names can have more than one component.
         *
         * RFC5179 did not, but should have, assign a Kerberos name-type
         * corresponding to GSS_C_NT_DOMAINBASED.  But it's basically a
         * host-based service name type with one additional component.
         *
         * So that's how we're treating host-based service names here:
         * two or more components.
         */

        if (argc == 0) {
            usage(1);
        } else if (argc == 1) {
            krb5_principal server2;

            /*
             * In this case the one argument is a principal name, not the
             * service name.
             *
             * We parse the argument as a principal name, extract the service
             * and hostname components, use krb5_sname_to_principal(), then
             * extract the service and hostname components from that.
             */

            ret = krb5_parse_name(context, argv[0], &server);
            if (ret)
                krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]);
            sname = krb5_principal_get_comp_string(context, server, 0);

            /*
             * If a single-component principal name is given, then we'll
             * default the hostname, as krb5_principal_get_comp_string()
             * returns NULL in this case.
             */
            hname = krb5_principal_get_comp_string(context, server, 1);

	    ret = krb5_sname_to_principal(context, hname, sname,
					   KRB5_NT_SRV_HST, &server2);
            sname = krb5_principal_get_comp_string(context, server2, 0);
            hname = krb5_principal_get_comp_string(context, server2, 1);

            /*
             * Modify the original with the new sname/hname.  This way we
             * retain any additional principal name components from the given
             * principal name.
             *
             * The name-type is set further below.
             */
            ret = krb5_principal_set_comp_string(context, server, 0, sname);
            if (ret)
                krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]);
            ret = krb5_principal_set_comp_string(context, server, 1, hname);
            if (ret)
                krb5_err(context, 1, ret, "krb5_principal_set_comp_string %s", argv[0]);
            krb5_free_principal(context, server2);
        } else {
            size_t i;

            /*
             * In this case the arguments are principal name components.
             *
             * The service and hostname components can be defaulted by passing
             * empty strings.
             */
	    sname = argv[0];
            if (*sname == '\0')
                sname = NULL;
	    hname = argv[1];
            if (hname == NULL || *hname == '\0')
                hname = NULL;
	    ret = krb5_sname_to_principal(context, hname, sname,
                                          KRB5_NT_SRV_HST, &server);
	    if (ret)
		krb5_err(context, 1, ret, "krb5_sname_to_principal");

            for (i = 2; i < argc; i++) {
                ret = krb5_principal_set_comp_string(context, server, i, argv[i]);
                if (ret)
                    krb5_err(context, 1, ret, "krb5_principal_set_comp_string");
            }
	}
    } else if (argc == 1) {
	ret = krb5_parse_name(context, argv[0], &server);
	if (ret)
	    krb5_err(context, 1, ret, "krb5_parse_name %s", argv[0]);
    } else {
	usage(1);
    }

    if (nametype != KRB5_NT_UNKNOWN)
        server->name.name_type = (NAME_TYPE)nametype;

    ret = krb5_get_creds(context, opt, cache, server, &out);
    if (ret)
	krb5_err(context, 1, ret, "krb5_get_creds");

    if (out_cache_str) {
	krb5_ccache id;

	ret = krb5_cc_resolve(context, out_cache_str, &id);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_resolve");

	ret = krb5_cc_initialize(context, id, out->client);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_initialize");

	ret = krb5_cc_store_cred(context, id, out);
	if(ret)
	    krb5_err(context, 1, ret, "krb5_cc_store_cred");
	krb5_cc_close(context, id);
    }

    krb5_free_creds(context, out);
    krb5_free_principal(context, server);
    krb5_get_creds_opt_free(context, opt);
    krb5_cc_close (context, cache);
    krb5_free_context (context);

    return 0;
}
Exemplo n.º 10
0
static int
verify_krb5(struct passwd *pwd,
	    char *password,
	    int32_t *exp,
	    int quiet)
{
    krb5_context context;
    krb5_error_code ret;
    krb5_ccache ccache;
    krb5_principal principal;
    
    ret = krb5_init_context(&context);
    if (ret) {
	syslog(LOG_AUTH|LOG_DEBUG, "krb5_init_context failed: %d", ret);
	goto out;
    }

    ret = krb5_parse_name (context, pwd->pw_name, &principal);
    if (ret) {
	syslog(LOG_AUTH|LOG_DEBUG, "krb5_parse_name: %s", 
	       krb5_get_err_text(context, ret));
	goto out;
    }

    set_krb5ccname(pwd->pw_uid);
    ret = krb5_cc_resolve(context, krb5ccname, &ccache);
    if(ret) {
	syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_resolve: %s", 
	       krb5_get_err_text(context, ret));
	goto out;
    }

    ret = krb5_verify_user_lrealm(context,
				  principal,
				  ccache,
				  password,
				  TRUE,
				  NULL);
    if(ret) {
	syslog(LOG_AUTH|LOG_DEBUG, "krb5_verify_user: %s", 
	       krb5_get_err_text(context, ret));
	goto out;
    }

    if(chown(krb5_cc_get_name(context, ccache), pwd->pw_uid, pwd->pw_gid)) {
	syslog(LOG_AUTH|LOG_DEBUG, "chown: %s", 
	       krb5_get_err_text(context, errno));
	goto out;
    }

#ifdef KRB4
    {
	krb5_realm realm = NULL;
	krb5_boolean get_v4_tgt;

	krb5_get_default_realm(context, &realm);
	krb5_appdefault_boolean(context, "afskauthlib", 
				realm,
				"krb4_get_tickets", FALSE, &get_v4_tgt);
	if (get_v4_tgt) {
	    CREDENTIALS c;
	    krb5_creds mcred, cred;

	    krb5_cc_clear_mcred(&mcred);

	    krb5_make_principal(context, &mcred.server, realm,
				"krbtgt",
				realm,
				NULL);
	    ret = krb5_cc_retrieve_cred(context, ccache, 0, &mcred, &cred);
	    if(ret == 0) {
		ret = krb524_convert_creds_kdc_ccache(context, ccache, &cred, &c);
		if(ret)
		    krb5_warn(context, ret, "converting creds");
		else {
		    set_krbtkfile(pwd->pw_uid);
		    tf_setup(&c, c.pname, c.pinst); 
		}
		memset(&c, 0, sizeof(c));
		krb5_free_cred_contents(context, &cred);
	    } else
		syslog(LOG_AUTH|LOG_DEBUG, "krb5_cc_retrieve_cred: %s", 
		       krb5_get_err_text(context, ret));
	    
	    krb5_free_principal(context, mcred.server);
	}
	free (realm);
	if (!pag_set && k_hasafs()) {
	    k_setpag();
	    pag_set = 1;
	}

	if (pag_set)
	    krb5_afslog_uid_home(context, ccache, NULL, NULL, 
				 pwd->pw_uid, pwd->pw_dir);
    }
#endif
 out:
    if(ret && !quiet)
	printf ("%s\n", krb5_get_err_text (context, ret));
    return ret;
}