1178825Sdfr/*
2178825Sdfr * Copyright (c) 2005, PADL Software Pty Ltd.
3178825Sdfr * All rights reserved.
4178825Sdfr *
5178825Sdfr * Redistribution and use in source and binary forms, with or without
6178825Sdfr * modification, are permitted provided that the following conditions
7178825Sdfr * are met:
8178825Sdfr *
9178825Sdfr * 1. Redistributions of source code must retain the above copyright
10178825Sdfr *    notice, this list of conditions and the following disclaimer.
11178825Sdfr *
12178825Sdfr * 2. Redistributions in binary form must reproduce the above copyright
13178825Sdfr *    notice, this list of conditions and the following disclaimer in the
14178825Sdfr *    documentation and/or other materials provided with the distribution.
15178825Sdfr *
16178825Sdfr * 3. Neither the name of PADL Software nor the names of its contributors
17178825Sdfr *    may be used to endorse or promote products derived from this software
18178825Sdfr *    without specific prior written permission.
19178825Sdfr *
20178825Sdfr * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND
21178825Sdfr * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22178825Sdfr * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23178825Sdfr * ARE DISCLAIMED.  IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE
24178825Sdfr * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
25178825Sdfr * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
26178825Sdfr * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
27178825Sdfr * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
28178825Sdfr * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
29178825Sdfr * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30178825Sdfr * SUCH DAMAGE.
31178825Sdfr */
32178825Sdfr
33178825Sdfr#include "kcm_locl.h"
34178825Sdfr
35233294SstasRCSID("$Id$");
36178825Sdfr
37178825Sdfrkrb5_error_code
38178825Sdfrkcm_ccache_refresh(krb5_context context,
39178825Sdfr		   kcm_ccache ccache,
40178825Sdfr		   krb5_creds **credp)
41178825Sdfr{
42178825Sdfr    krb5_error_code ret;
43178825Sdfr    krb5_creds in, *out;
44178825Sdfr    krb5_kdc_flags flags;
45178825Sdfr    krb5_const_realm realm;
46178825Sdfr    krb5_ccache_data ccdata;
47178825Sdfr
48178825Sdfr    memset(&in, 0, sizeof(in));
49178825Sdfr
50178825Sdfr    KCM_ASSERT_VALID(ccache);
51178825Sdfr
52178825Sdfr    if (ccache->client == NULL) {
53178825Sdfr	/* no primary principal */
54178825Sdfr	kcm_log(0, "Refresh credentials requested but no client principal");
55178825Sdfr	return KRB5_CC_NOTFOUND;
56178825Sdfr    }
57178825Sdfr
58178825Sdfr    HEIMDAL_MUTEX_lock(&ccache->mutex);
59178825Sdfr
60178825Sdfr    /* Fake up an internal ccache */
61178825Sdfr    kcm_internal_ccache(context, ccache, &ccdata);
62178825Sdfr
63178825Sdfr    /* Find principal */
64178825Sdfr    in.client = ccache->client;
65178825Sdfr
66178825Sdfr    if (ccache->server != NULL) {
67178825Sdfr	ret = krb5_copy_principal(context, ccache->server, &in.server);
68178825Sdfr	if (ret) {
69178825Sdfr	    kcm_log(0, "Failed to copy service principal: %s",
70178825Sdfr		    krb5_get_err_text(context, ret));
71178825Sdfr	    goto out;
72178825Sdfr	}
73178825Sdfr    } else {
74178825Sdfr	realm = krb5_principal_get_realm(context, in.client);
75178825Sdfr	ret = krb5_make_principal(context, &in.server, realm,
76178825Sdfr				  KRB5_TGS_NAME, realm, NULL);
77178825Sdfr	if (ret) {
78178825Sdfr	    kcm_log(0, "Failed to make TGS principal for realm %s: %s",
79178825Sdfr		    realm, krb5_get_err_text(context, ret));
80178825Sdfr	    goto out;
81178825Sdfr	}
82178825Sdfr    }
83178825Sdfr
84178825Sdfr    if (ccache->tkt_life)
85178825Sdfr	in.times.endtime = time(NULL) + ccache->tkt_life;
86178825Sdfr    if (ccache->renew_life)
87178825Sdfr	in.times.renew_till = time(NULL) + ccache->renew_life;
88178825Sdfr
89178825Sdfr    flags.i = 0;
90178825Sdfr    flags.b.renewable = TRUE;
91178825Sdfr    flags.b.renew = TRUE;
92178825Sdfr
93178825Sdfr    ret = krb5_get_kdc_cred(context,
94178825Sdfr			    &ccdata,
95178825Sdfr			    flags,
96178825Sdfr			    NULL,
97178825Sdfr			    NULL,
98178825Sdfr			    &in,
99178825Sdfr			    &out);
100178825Sdfr    if (ret) {
101178825Sdfr	kcm_log(0, "Failed to renew credentials for cache %s: %s",
102178825Sdfr		ccache->name, krb5_get_err_text(context, ret));
103178825Sdfr	goto out;
104178825Sdfr    }
105178825Sdfr
106178825Sdfr    /* Swap them in */
107178825Sdfr    kcm_ccache_remove_creds_internal(context, ccache);
108178825Sdfr
109178825Sdfr    ret = kcm_ccache_store_cred_internal(context, ccache, out, 0, credp);
110178825Sdfr    if (ret) {
111178825Sdfr	kcm_log(0, "Failed to store credentials for cache %s: %s",
112178825Sdfr		ccache->name, krb5_get_err_text(context, ret));
113178825Sdfr	krb5_free_creds(context, out);
114178825Sdfr	goto out;
115178825Sdfr    }
116178825Sdfr
117178825Sdfr    free(out); /* but not contents */
118178825Sdfr
119178825Sdfrout:
120178825Sdfr    HEIMDAL_MUTEX_unlock(&ccache->mutex);
121178825Sdfr
122178825Sdfr    return ret;
123178825Sdfr}
124178825Sdfr
125