1/*
2 * Copyright (c) 2005, PADL Software Pty Ltd.
3 * All rights reserved.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 *    notice, this list of conditions and the following disclaimer.
11 *
12 * 2. Redistributions in binary form must reproduce the above copyright
13 *    notice, this list of conditions and the following disclaimer in the
14 *    documentation and/or other materials provided with the distribution.
15 *
16 * 3. Neither the name of PADL Software nor the names of its contributors
17 *    may be used to endorse or promote products derived from this software
18 *    without specific prior written permission.
19 *
20 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23 * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * SUCH DAMAGE.
31 */
32
33#include "kcm_locl.h"
34
35RCSID("$Id$");
36
37krb5_error_code
38kcm_ccache_refresh(krb5_context context,
39		   kcm_ccache ccache,
40		   krb5_creds **credp)
41{
42    krb5_error_code ret;
43    krb5_creds in, *out;
44    krb5_kdc_flags flags;
45    krb5_const_realm realm;
46    krb5_ccache_data ccdata;
47
48    memset(&in, 0, sizeof(in));
49
50    KCM_ASSERT_VALID(ccache);
51
52    if (ccache->client == NULL) {
53	/* no primary principal */
54	kcm_log(0, "Refresh credentials requested but no client principal");
55	return KRB5_CC_NOTFOUND;
56    }
57
58    HEIMDAL_MUTEX_lock(&ccache->mutex);
59
60    /* Fake up an internal ccache */
61    kcm_internal_ccache(context, ccache, &ccdata);
62
63    /* Find principal */
64    in.client = ccache->client;
65
66    if (ccache->server != NULL) {
67	ret = krb5_copy_principal(context, ccache->server, &in.server);
68	if (ret) {
69	    kcm_log(0, "Failed to copy service principal: %s",
70		    krb5_get_err_text(context, ret));
71	    goto out;
72	}
73    } else {
74	realm = krb5_principal_get_realm(context, in.client);
75	ret = krb5_make_principal(context, &in.server, realm,
76				  KRB5_TGS_NAME, realm, NULL);
77	if (ret) {
78	    kcm_log(0, "Failed to make TGS principal for realm %s: %s",
79		    realm, krb5_get_err_text(context, ret));
80	    goto out;
81	}
82    }
83
84    if (ccache->tkt_life)
85	in.times.endtime = time(NULL) + ccache->tkt_life;
86    if (ccache->renew_life)
87	in.times.renew_till = time(NULL) + ccache->renew_life;
88
89    flags.i = 0;
90    flags.b.renewable = TRUE;
91    flags.b.renew = TRUE;
92
93    ret = krb5_get_kdc_cred(context,
94			    &ccdata,
95			    flags,
96			    NULL,
97			    NULL,
98			    &in,
99			    &out);
100    if (ret) {
101	kcm_log(0, "Failed to renew credentials for cache %s: %s",
102		ccache->name, krb5_get_err_text(context, ret));
103	goto out;
104    }
105
106    /* Swap them in */
107    kcm_ccache_remove_creds_internal(context, ccache);
108
109    ret = kcm_ccache_store_cred_internal(context, ccache, out, 0, credp);
110    if (ret) {
111	kcm_log(0, "Failed to store credentials for cache %s: %s",
112		ccache->name, krb5_get_err_text(context, ret));
113	krb5_free_creds(context, out);
114	goto out;
115    }
116
117    free(out); /* but not contents */
118
119out:
120    HEIMDAL_MUTEX_unlock(&ccache->mutex);
121
122    return ret;
123}
124
125