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