s4:heimdal: import lorikeet-heimdal-202201172009 (commit 5a0b45cd723628b3690ea848548b...
[samba.git] / source4 / heimdal / kcm / renew.c
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
35 RCSID("$Id$");
36
37 krb5_error_code
38 kcm_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     const char *estr;
48
49     memset(&in, 0, sizeof(in));
50
51     KCM_ASSERT_VALID(ccache);
52
53     if (ccache->client == NULL) {
54         /* no primary principal */
55         kcm_log(0, "Refresh credentials requested but no client principal");
56         return KRB5_CC_NOTFOUND;
57     }
58
59     HEIMDAL_MUTEX_lock(&ccache->mutex);
60
61     /* Fake up an internal ccache */
62     kcm_internal_ccache(context, ccache, &ccdata);
63
64     /* Find principal */
65     in.client = ccache->client;
66
67     if (ccache->server != NULL) {
68         ret = krb5_copy_principal(context, ccache->server, &in.server);
69         if (ret) {
70             estr = krb5_get_error_message(context, ret);
71             kcm_log(0, "Failed to copy service principal: %s",
72                     estr);
73             krb5_free_error_message(context, estr);
74             goto out;
75         }
76     } else {
77         realm = krb5_principal_get_realm(context, in.client);
78         ret = krb5_make_principal(context, &in.server, realm,
79                                   KRB5_TGS_NAME, realm, NULL);
80         if (ret) {
81             estr = krb5_get_error_message(context, ret);
82             kcm_log(0, "Failed to make TGS principal for realm %s: %s",
83                     realm, estr);
84             krb5_free_error_message(context, estr);
85             goto out;
86         }
87     }
88
89     if (ccache->tkt_life)
90         in.times.endtime = time(NULL) + ccache->tkt_life;
91     if (ccache->renew_life)
92         in.times.renew_till = time(NULL) + ccache->renew_life;
93
94     flags.i = 0;
95     flags.b.renewable = TRUE;
96     flags.b.renew = TRUE;
97
98     ret = krb5_get_kdc_cred(context,
99                             &ccdata,
100                             flags,
101                             NULL,
102                             NULL,
103                             &in,
104                             &out);
105     if (ret) {
106         estr = krb5_get_error_message(context, ret);
107         kcm_log(0, "Failed to renew credentials for cache %s: %s",
108                 ccache->name, estr);
109         krb5_free_error_message(context, estr);
110         goto out;
111     }
112
113     /* Swap them in */
114     kcm_ccache_remove_creds_internal(context, ccache);
115
116     ret = kcm_ccache_store_cred_internal(context, ccache, out, 0, credp);
117     if (ret) {
118         estr = krb5_get_error_message(context, ret);
119         kcm_log(0, "Failed to store credentials for cache %s: %s",
120                 ccache->name, estr);
121         krb5_free_error_message(context, estr);
122         krb5_free_creds(context, out);
123         goto out;
124     }
125
126     free(out); /* but not contents */
127
128 out:
129     HEIMDAL_MUTEX_unlock(&ccache->mutex);
130
131     return ret;
132 }
133