Line data Source code
1 : /*
2 : * Copyright (c) 2021, 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 <krb5_locl.h>
34 : #include <mech_locl.h>
35 :
36 : #include "gss-preauth-protos.h"
37 : #include "gss-preauth-private.h"
38 :
39 : static krb5_error_code
40 0 : pa_gss_acquire_initiator_cred(krb5_context context,
41 : krb5_gss_init_ctx gssic,
42 : const krb5_creds *kcred,
43 : gss_cred_id_t *cred)
44 : {
45 0 : krb5_error_code ret;
46 :
47 0 : OM_uint32 major, minor;
48 0 : gss_const_OID mech;
49 0 : gss_OID_set_desc mechs;
50 0 : gss_name_t initiator_name = GSS_C_NO_NAME;
51 0 : OM_uint32 time_req;
52 0 : krb5_timestamp now;
53 :
54 0 : *cred = GSS_C_NO_CREDENTIAL;
55 :
56 0 : mech = _krb5_init_creds_get_gss_mechanism(context, gssic);
57 :
58 0 : mechs.count = 1;
59 0 : mechs.elements = (gss_OID)mech;
60 :
61 0 : ret = _krb5_gss_pa_unparse_name(context, kcred->client, &initiator_name);
62 0 : if (ret)
63 0 : return ret;
64 :
65 0 : krb5_timeofday(context, &now);
66 0 : if (kcred->times.endtime && kcred->times.endtime > now)
67 0 : time_req = kcred->times.endtime - now;
68 : else
69 0 : time_req = GSS_C_INDEFINITE;
70 :
71 0 : major = gss_acquire_cred(&minor, initiator_name, time_req, &mechs,
72 : GSS_C_INITIATE, cred, NULL, NULL);
73 0 : ret = _krb5_gss_map_error(major, minor);
74 :
75 0 : gss_release_name(&major, &initiator_name);
76 :
77 0 : return ret;
78 : }
79 :
80 : static krb5_error_code KRB5_LIB_CALL
81 0 : pa_gss_step(krb5_context context,
82 : krb5_gss_init_ctx gssic,
83 : const krb5_creds *kcred,
84 : gss_ctx_id_t *ctx,
85 : KDCOptions flags,
86 : krb5_data *enc_as_req,
87 : krb5_data *in,
88 : krb5_data *out)
89 : {
90 0 : krb5_error_code ret;
91 0 : krb5_principal tgs_name = NULL;
92 :
93 0 : OM_uint32 major, minor;
94 0 : gss_cred_id_t cred;
95 0 : gss_name_t target_name = GSS_C_NO_NAME;
96 0 : OM_uint32 req_flags = GSS_C_MUTUAL_FLAG;
97 0 : OM_uint32 ret_flags;
98 0 : struct gss_channel_bindings_struct cb;
99 0 : gss_buffer_desc input_token, output_token = GSS_C_EMPTY_BUFFER;
100 :
101 0 : memset(&cb, 0, sizeof(cb));
102 0 : krb5_data_zero(out);
103 :
104 0 : if (flags.request_anonymous)
105 0 : req_flags |= GSS_C_ANON_FLAG;
106 :
107 0 : cred = (gss_cred_id_t)_krb5_init_creds_get_gss_cred(context, gssic);
108 :
109 0 : if (cred == GSS_C_NO_CREDENTIAL) {
110 0 : ret = pa_gss_acquire_initiator_cred(context, gssic, kcred, &cred);
111 0 : if (ret)
112 0 : goto out;
113 :
114 0 : _krb5_init_creds_set_gss_cred(context, gssic, cred);
115 : }
116 :
117 0 : ret = krb5_make_principal(context, &tgs_name, kcred->server->realm,
118 0 : KRB5_TGS_NAME, kcred->server->realm, NULL);
119 0 : if (ret)
120 0 : goto out;
121 :
122 0 : ret = _krb5_gss_pa_unparse_name(context, tgs_name, &target_name);
123 0 : if (ret)
124 0 : goto out;
125 :
126 0 : _krb5_gss_data_to_buffer(enc_as_req, &cb.application_data);
127 0 : _krb5_gss_data_to_buffer(in, &input_token);
128 :
129 0 : major = gss_init_sec_context(&minor,
130 : cred,
131 : ctx,
132 : target_name,
133 0 : (gss_OID)_krb5_init_creds_get_gss_mechanism(context, gssic),
134 : req_flags,
135 : GSS_C_INDEFINITE,
136 : &cb,
137 : &input_token,
138 : NULL,
139 : &output_token,
140 : &ret_flags,
141 : NULL);
142 :
143 0 : _krb5_gss_buffer_to_data(&output_token, out);
144 :
145 0 : if (major == GSS_S_COMPLETE) {
146 0 : if ((ret_flags & GSS_C_MUTUAL_FLAG) == 0)
147 0 : ret = KRB5_MUTUAL_FAILED;
148 0 : else if ((ret_flags & req_flags) != req_flags)
149 0 : ret = KRB5KDC_ERR_BADOPTION;
150 : else
151 0 : ret = 0;
152 : } else
153 0 : ret = _krb5_gss_map_error(major, minor);
154 :
155 0 : out:
156 0 : gss_release_name(&minor, &target_name);
157 0 : krb5_free_principal(context, tgs_name);
158 :
159 0 : return ret;
160 : }
161 :
162 : static krb5_error_code KRB5_LIB_CALL
163 0 : pa_gss_finish(krb5_context context,
164 : krb5_gss_init_ctx gssic,
165 : const krb5_creds *kcred,
166 : gss_ctx_id_t ctx,
167 : krb5int32 nonce,
168 : krb5_enctype enctype,
169 : krb5_principal *client_p,
170 : krb5_keyblock **reply_key_p)
171 : {
172 0 : krb5_error_code ret;
173 0 : krb5_principal client = NULL;
174 0 : krb5_keyblock *reply_key = NULL;
175 :
176 0 : OM_uint32 major, minor;
177 0 : gss_name_t initiator_name = GSS_C_NO_NAME;
178 :
179 0 : *client_p = NULL;
180 0 : *reply_key_p = NULL;
181 :
182 0 : major = gss_inquire_context(&minor,
183 : ctx,
184 : &initiator_name,
185 : NULL, /* target_name */
186 : NULL, /* lifetime_req */
187 : NULL, /* mech_type */
188 : NULL, /* ctx_flags */
189 : NULL, /* locally_initiated */
190 : NULL); /* open */
191 :
192 0 : if (GSS_ERROR(major))
193 0 : return _krb5_gss_map_error(major, minor);
194 :
195 0 : ret = _krb5_gss_pa_parse_name(context, initiator_name, 0, &client);
196 0 : if (ret)
197 0 : goto out;
198 :
199 0 : ret = _krb5_gss_pa_derive_key(context, ctx, nonce, enctype, &reply_key);
200 0 : if (ret)
201 0 : goto out;
202 :
203 0 : *client_p = client;
204 0 : client = NULL;
205 :
206 0 : *reply_key_p = reply_key;
207 0 : reply_key = NULL;
208 :
209 0 : out:
210 0 : krb5_free_principal(context, client);
211 0 : if (reply_key)
212 0 : krb5_free_keyblock(context, reply_key);
213 0 : gss_release_name(&minor, &initiator_name);
214 :
215 0 : return ret;
216 : }
217 :
218 : static void KRB5_LIB_CALL
219 0 : pa_gss_delete_sec_context(krb5_context context,
220 : krb5_gss_init_ctx gssic,
221 : gss_ctx_id_t ctx)
222 : {
223 0 : OM_uint32 minor;
224 :
225 0 : gss_delete_sec_context(&minor, &ctx, GSS_C_NO_BUFFER);
226 0 : }
227 :
228 : static void KRB5_LIB_CALL
229 0 : pa_gss_release_cred(krb5_context context,
230 : krb5_gss_init_ctx gssic,
231 : gss_cred_id_t cred)
232 : {
233 0 : OM_uint32 minor;
234 :
235 0 : gss_release_cred(&minor, &cred);
236 0 : }
237 :
238 : krb5_error_code
239 0 : krb5_gss_set_init_creds(krb5_context context,
240 : krb5_init_creds_context ctx,
241 : gss_const_cred_id_t gss_cred,
242 : gss_const_OID gss_mech)
243 : {
244 0 : return _krb5_init_creds_init_gss(context,ctx,
245 : pa_gss_step,
246 : pa_gss_finish,
247 : pa_gss_release_cred,
248 : pa_gss_delete_sec_context,
249 : gss_cred,
250 : gss_mech,
251 : 0);
252 : }
|