111497Sphk/*
211497Sphk * Copyright (c) 2005, PADL Software Pty Ltd.
311497Sphk * All rights reserved.
411497Sphk *
593151Sphk * Redistribution and use in source and binary forms, with or without
611497Sphk * modification, are permitted provided that the following conditions
711497Sphk * are met:
811497Sphk *
911497Sphk * 1. Redistributions of source code must retain the above copyright
10108605Sphk *    notice, this list of conditions and the following disclaimer.
11108605Sphk *
1250477Speter * 2. Redistributions in binary form must reproduce the above copyright
1311497Sphk *    notice, this list of conditions and the following disclaimer in the
14108605Sphk *    documentation and/or other materials provided with the distribution.
15108605Sphk *
1611497Sphk * 3. Neither the name of PADL Software nor the names of its contributors
17103392Sphk *    may be used to endorse or promote products derived from this software
1841594Sarchie *    without specific prior written permission.
19108605Sphk *
2041594Sarchie * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21108605Sphk * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22108605Sphk * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23108605Sphk * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24108605Sphk * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25103392Sphk * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26108605Sphk * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27108605Sphk * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28108605Sphk * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29108605Sphk * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30108605Sphk * SUCH DAMAGE.
31108605Sphk */
32108605Sphk
33108605Sphk#include "kcm_locl.h"
34108605Sphk
35108605SphkRCSID("$Id$");
36108605Sphk
37108605Sphkkrb5_error_code
38108605Sphkkcm_ccache_refresh(krb5_context context,
39108605Sphk		   kcm_ccache ccache,
40108605Sphk		   krb5_creds **credp)
41108605Sphk{
42108605Sphk    krb5_error_code ret;
43108605Sphk    krb5_creds in, *out;
44108605Sphk    krb5_kdc_flags flags;
45108605Sphk    krb5_const_realm realm;
46108605Sphk    krb5_ccache_data ccdata;
47108605Sphk
48108605Sphk    memset(&in, 0, sizeof(in));
49108605Sphk
50108605Sphk    KCM_ASSERT_VALID(ccache);
51108605Sphk
52108605Sphk    if (ccache->client == NULL) {
53108605Sphk	/* no primary principal */
54108605Sphk	kcm_log(0, "Refresh credentials requested but no client principal");
55108605Sphk	return KRB5_CC_NOTFOUND;
56108605Sphk    }
57108605Sphk
58108605Sphk    HEIMDAL_MUTEX_lock(&ccache->mutex);
59108605Sphk
60108605Sphk    /* Fake up an internal ccache */
61108605Sphk    kcm_internal_ccache(context, ccache, &ccdata);
62108605Sphk
63108605Sphk    /* Find principal */
64108605Sphk    in.client = ccache->client;
65108605Sphk
66108605Sphk    if (ccache->server != NULL) {
67103392Sphk	ret = krb5_copy_principal(context, ccache->server, &in.server);
6841594Sarchie	if (ret) {
6941594Sarchie	    kcm_log(0, "Failed to copy service principal: %s",
70141640Sphk		    krb5_get_err_text(context, ret));
71103392Sphk	    goto out;
72141640Sphk	}
73141640Sphk    } else {
74141640Sphk	realm = krb5_principal_get_realm(context, in.client);
75141640Sphk	ret = krb5_make_principal(context, &in.server, realm,
76141640Sphk				  KRB5_TGS_NAME, realm, NULL);
77141640Sphk	if (ret) {
78141640Sphk	    kcm_log(0, "Failed to make TGS principal for realm %s: %s",
79141640Sphk		    realm, krb5_get_err_text(context, ret));
80141640Sphk	    goto out;
8111497Sphk	}
8211497Sphk    }
8311497Sphk
8411497Sphk    if (ccache->tkt_life)
8511497Sphk	in.times.endtime = time(NULL) + ccache->tkt_life;
8611497Sphk    if (ccache->renew_life)
8711497Sphk	in.times.renew_till = time(NULL) + ccache->renew_life;
88141640Sphk
89141640Sphk    flags.i = 0;
90141640Sphk    flags.b.renewable = TRUE;
91141640Sphk    flags.b.renew = TRUE;
9211497Sphk
93141640Sphk    ret = krb5_get_kdc_cred(context,
94141640Sphk			    &ccdata,
9511497Sphk			    flags,
9611497Sphk			    NULL,
9711497Sphk			    NULL,
9811497Sphk			    &in,
9911497Sphk			    &out);
10011497Sphk    if (ret) {
10111497Sphk	kcm_log(0, "Failed to renew credentials for cache %s: %s",
10211497Sphk		ccache->name, krb5_get_err_text(context, ret));
103141640Sphk	goto out;
10411497Sphk    }
10511497Sphk
10611497Sphk    /* Swap them in */
10712814Sphk    kcm_ccache_remove_creds_internal(context, ccache);
10812814Sphk
10911497Sphk    ret = kcm_ccache_store_cred_internal(context, ccache, out, 0, credp);
11012814Sphk    if (ret) {
111141640Sphk	kcm_log(0, "Failed to store credentials for cache %s: %s",
11211497Sphk		ccache->name, krb5_get_err_text(context, ret));
11311497Sphk	krb5_free_creds(context, out);
11411497Sphk	goto out;
11511497Sphk    }
11611497Sphk
11711497Sphk    free(out); /* but not contents */
11811497Sphk
11911497Sphkout:
12011497Sphk    HEIMDAL_MUTEX_unlock(&ccache->mutex);
121108605Sphk
12211497Sphk    return ret;
12311497Sphk}
12411497Sphk
12511497Sphk