Coverage Report

Created: 2024-07-23 07:27

/src/krb5/src/lib/gssapi/krb5/store_cred.c
Line
Count
Source (jump to first uncovered line)
1
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2
/* lib/gssapi/krb5/store_cred.c */
3
/*
4
 * Copyright 2009 by the Massachusetts Institute of Technology.
5
 * All Rights Reserved.
6
 *
7
 * Export of this software from the United States of America may
8
 *   require a specific license from the United States Government.
9
 *   It is the responsibility of any person or organization contemplating
10
 *   export to obtain such a license before exporting.
11
 *
12
 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13
 * distribute this software and its documentation for any purpose and
14
 * without fee is hereby granted, provided that the above copyright
15
 * notice appear in all copies and that both that copyright notice and
16
 * this permission notice appear in supporting documentation, and that
17
 * the name of M.I.T. not be used in advertising or publicity pertaining
18
 * to distribution of the software without specific, written prior
19
 * permission.  Furthermore if you modify this software you must label
20
 * your software as modified software and not distribute it in such a
21
 * fashion that it might be confused with the original M.I.T. software.
22
 * M.I.T. makes no representations about the suitability of
23
 * this software for any purpose.  It is provided "as is" without express
24
 * or implied warranty.
25
 */
26
27
#include "k5-int.h"
28
#include "gssapiP_krb5.h"
29
30
static OM_uint32
31
copy_initiator_creds(OM_uint32 *minor_status,
32
                     gss_cred_id_t input_cred_handle,
33
                     const gss_OID desired_mech,
34
                     OM_uint32 overwrite_cred,
35
                     OM_uint32 default_cred,
36
                     gss_const_key_value_set_t cred_store)
37
0
{
38
0
    OM_uint32 major_status;
39
0
    krb5_error_code ret;
40
0
    krb5_gss_cred_id_t kcred = NULL;
41
0
    krb5_context context = NULL;
42
0
    krb5_ccache cache = NULL, defcache = NULL, mcc = NULL;
43
0
    krb5_principal princ = NULL;
44
0
    krb5_boolean switch_to_cache = FALSE;
45
0
    const char *ccache_name, *deftype;
46
47
0
    *minor_status = 0;
48
49
0
    ret = krb5_gss_init_context(&context);
50
0
    if (ret)
51
0
        goto kerr_cleanup;
52
53
0
    major_status = krb5_gss_validate_cred_1(minor_status,
54
0
                                            input_cred_handle,
55
0
                                            context);
56
0
    if (GSS_ERROR(major_status))
57
0
        goto cleanup;
58
59
0
    kcred = (krb5_gss_cred_id_t)input_cred_handle;
60
61
0
    if (kcred->ccache == NULL) {
62
0
        *minor_status = KG_CCACHE_NOMATCH;
63
0
        major_status = GSS_S_DEFECTIVE_CREDENTIAL;
64
0
        goto cleanup;
65
0
    }
66
67
0
    major_status = kg_value_from_cred_store(cred_store,
68
0
                                            KRB5_CS_CCACHE_URN, &ccache_name);
69
0
    if (GSS_ERROR(major_status))
70
0
        goto cleanup;
71
72
0
    if (ccache_name != NULL) {
73
0
        ret = krb5_cc_set_default_name(context, ccache_name);
74
0
        if (ret)
75
0
            goto kerr_cleanup;
76
0
    } else {
77
0
        major_status = kg_sync_ccache_name(context, minor_status);
78
0
        if (major_status != GSS_S_COMPLETE)
79
0
            goto cleanup;
80
0
    }
81
82
    /* Resolve the default ccache and get its type. */
83
0
    ret = krb5_cc_default(context, &defcache);
84
0
    if (ret)
85
0
        goto kerr_cleanup;
86
0
    deftype = krb5_cc_get_type(context, defcache);
87
88
0
    if (krb5_cc_support_switch(context, deftype)) {
89
        /* Use an existing or new cache within the collection. */
90
0
        ret = krb5_cc_cache_match(context, kcred->name->princ, &cache);
91
0
        if (!ret && !overwrite_cred) {
92
0
            major_status = GSS_S_DUPLICATE_ELEMENT;
93
0
            goto cleanup;
94
0
        }
95
0
        if (ret == KRB5_CC_NOTFOUND)
96
0
            ret = krb5_cc_new_unique(context, deftype, NULL, &cache);
97
0
        if (ret)
98
0
            goto kerr_cleanup;
99
0
        switch_to_cache = default_cred;
100
0
    } else {
101
        /* Use the default cache. */
102
0
        cache = defcache;
103
0
        defcache = NULL;
104
0
        ret = krb5_cc_get_principal(context, cache, &princ);
105
0
        krb5_free_principal(context, princ);
106
0
        if (!ret && !overwrite_cred) {
107
0
            major_status = GSS_S_DUPLICATE_ELEMENT;
108
0
            goto cleanup;
109
0
        }
110
0
    }
111
112
0
    ret = krb5_cc_new_unique(context, "MEMORY", NULL, &mcc);
113
0
    if (ret)
114
0
        goto kerr_cleanup;
115
0
    ret = krb5_cc_initialize(context, mcc, kcred->name->princ);
116
0
    if (ret)
117
0
        goto kerr_cleanup;
118
0
    ret = krb5_cc_copy_creds(context, kcred->ccache, mcc);
119
0
    if (ret)
120
0
        goto kerr_cleanup;
121
0
    ret = krb5_cc_move(context, mcc, cache);
122
0
    if (ret)
123
0
        goto kerr_cleanup;
124
0
    mcc = NULL;
125
126
0
    if (switch_to_cache) {
127
0
        ret = krb5_cc_switch(context, cache);
128
0
        if (ret)
129
0
            goto kerr_cleanup;
130
0
    }
131
132
0
    *minor_status = 0;
133
0
    major_status = GSS_S_COMPLETE;
134
135
0
cleanup:
136
0
    if (kcred != NULL)
137
0
        k5_mutex_unlock(&kcred->lock);
138
0
    if (defcache != NULL)
139
0
        krb5_cc_close(context, defcache);
140
0
    if (cache != NULL)
141
0
        krb5_cc_close(context, cache);
142
0
    if (mcc != NULL)
143
0
        krb5_cc_destroy(context, mcc);
144
0
    krb5_free_context(context);
145
146
0
    return major_status;
147
148
0
kerr_cleanup:
149
0
    *minor_status = ret;
150
0
    major_status = GSS_S_FAILURE;
151
0
    goto cleanup;
152
0
}
153
154
OM_uint32 KRB5_CALLCONV
155
krb5_gss_store_cred(OM_uint32 *minor_status,
156
                    gss_cred_id_t input_cred_handle,
157
                    gss_cred_usage_t cred_usage,
158
                    const gss_OID desired_mech,
159
                    OM_uint32 overwrite_cred,
160
                    OM_uint32 default_cred,
161
                    gss_OID_set *elements_stored,
162
                    gss_cred_usage_t *cred_usage_stored)
163
0
{
164
0
    return krb5_gss_store_cred_into(minor_status, input_cred_handle,
165
0
                                    cred_usage, desired_mech,
166
0
                                    overwrite_cred, default_cred,
167
0
                                    GSS_C_NO_CRED_STORE,
168
0
                                    elements_stored, cred_usage_stored);
169
0
}
170
171
OM_uint32 KRB5_CALLCONV
172
krb5_gss_store_cred_into(OM_uint32 *minor_status,
173
                         gss_cred_id_t input_cred_handle,
174
                         gss_cred_usage_t cred_usage,
175
                         const gss_OID desired_mech,
176
                         OM_uint32 overwrite_cred,
177
                         OM_uint32 default_cred,
178
                         gss_const_key_value_set_t cred_store,
179
                         gss_OID_set *elements_stored,
180
                         gss_cred_usage_t *cred_usage_stored)
181
0
{
182
0
    OM_uint32 major_status;
183
0
    gss_cred_usage_t actual_usage;
184
0
    OM_uint32 lifetime;
185
186
0
    if (input_cred_handle == GSS_C_NO_CREDENTIAL)
187
0
        return GSS_S_NO_CRED;
188
189
0
    major_status = GSS_S_FAILURE;
190
191
0
    if (cred_usage == GSS_C_ACCEPT) {
192
0
        *minor_status = G_STORE_ACCEPTOR_CRED_NOSUPP;
193
0
        return GSS_S_FAILURE;
194
0
    } else if (cred_usage != GSS_C_INITIATE && cred_usage != GSS_C_BOTH) {
195
0
        *minor_status = G_BAD_USAGE;
196
0
        return GSS_S_FAILURE;
197
0
    }
198
199
0
    major_status = krb5_gss_inquire_cred(minor_status, input_cred_handle,
200
0
                                         NULL, &lifetime,
201
0
                                         &actual_usage, elements_stored);
202
0
    if (GSS_ERROR(major_status))
203
0
        return major_status;
204
205
0
    if (lifetime == 0)
206
0
        return GSS_S_CREDENTIALS_EXPIRED;
207
208
0
    if (actual_usage != GSS_C_INITIATE && actual_usage != GSS_C_BOTH) {
209
0
        *minor_status = G_STORE_ACCEPTOR_CRED_NOSUPP;
210
0
        return GSS_S_FAILURE;
211
0
    }
212
213
0
    major_status = copy_initiator_creds(minor_status, input_cred_handle,
214
0
                                        desired_mech, overwrite_cred,
215
0
                                        default_cred, cred_store);
216
0
    if (GSS_ERROR(major_status))
217
0
        return major_status;
218
219
0
    if (cred_usage_stored != NULL)
220
0
        *cred_usage_stored = GSS_C_INITIATE;
221
222
0
    return GSS_S_COMPLETE;
223
0
}