Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/kgssapi/gss_init_sec_context.c
39476 views
1
/*-
2
* SPDX-License-Identifier: BSD-2-Clause
3
*
4
* Copyright (c) 2008 Isilon Inc http://www.isilon.com/
5
* Authors: Doug Rabson <[email protected]>
6
* Developed with Red Inc: Alfred Perlstein <[email protected]>
7
*
8
* Redistribution and use in source and binary forms, with or without
9
* modification, are permitted provided that the following conditions
10
* are met:
11
* 1. Redistributions of source code must retain the above copyright
12
* notice, this list of conditions and the following disclaimer.
13
* 2. Redistributions in binary form must reproduce the above copyright
14
* notice, this list of conditions and the following disclaimer in the
15
* documentation and/or other materials provided with the distribution.
16
*
17
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27
* SUCH DAMAGE.
28
*/
29
30
#include <sys/param.h>
31
#include <sys/kernel.h>
32
#include <sys/kobj.h>
33
#include <sys/lock.h>
34
#include <sys/malloc.h>
35
#include <sys/mutex.h>
36
#include <sys/proc.h>
37
38
#include <kgssapi/gssapi.h>
39
#include <kgssapi/gssapi_impl.h>
40
#include <rpc/rpc.h>
41
42
#include "gssd.h"
43
#include "kgss_if.h"
44
45
/*
46
* This function should only be called when the gssd
47
* daemon running on the system is an old one that
48
* does not use gss_krb5_export_lucid_sec_context().
49
*/
50
OM_uint32
51
gss_init_sec_context(OM_uint32 * minor_status,
52
const gss_cred_id_t initiator_cred_handle,
53
gss_ctx_id_t * context_handle,
54
const gss_name_t target_name,
55
const gss_OID input_mech_type,
56
OM_uint32 req_flags,
57
OM_uint32 time_req,
58
const gss_channel_bindings_t input_chan_bindings,
59
const gss_buffer_t input_token,
60
gss_OID * actual_mech_type,
61
gss_buffer_t output_token,
62
OM_uint32 * ret_flags,
63
OM_uint32 * time_rec)
64
{
65
struct init_sec_context_res res;
66
struct init_sec_context_args args;
67
enum clnt_stat stat;
68
gss_ctx_id_t ctx = *context_handle;
69
CLIENT *cl;
70
71
*minor_status = 0;
72
73
cl = kgss_gssd_client();
74
if (cl == NULL)
75
return (GSS_S_FAILURE);
76
77
args.uid = curthread->td_ucred->cr_uid;
78
if (initiator_cred_handle)
79
args.cred = initiator_cred_handle->handle;
80
else
81
args.cred = 0;
82
if (ctx)
83
args.ctx = ctx->handle;
84
else
85
args.ctx = 0;
86
args.name = target_name->handle;
87
args.mech_type = input_mech_type;
88
args.req_flags = req_flags;
89
args.time_req = time_req;
90
args.input_chan_bindings = input_chan_bindings;
91
if (input_token)
92
args.input_token = *input_token;
93
else {
94
args.input_token.length = 0;
95
args.input_token.value = NULL;
96
}
97
98
bzero(&res, sizeof(res));
99
stat = gssd_init_sec_context_1(&args, &res, cl);
100
CLNT_RELEASE(cl);
101
if (stat != RPC_SUCCESS) {
102
*minor_status = stat;
103
return (GSS_S_FAILURE);
104
}
105
106
if (res.major_status != GSS_S_COMPLETE
107
&& res.major_status != GSS_S_CONTINUE_NEEDED) {
108
*minor_status = res.minor_status;
109
xdr_free((xdrproc_t) xdr_init_sec_context_res, &res);
110
return (res.major_status);
111
}
112
113
*minor_status = res.minor_status;
114
115
if (!ctx) {
116
ctx = kgss_create_context(res.actual_mech_type);
117
if (!ctx) {
118
xdr_free((xdrproc_t) xdr_init_sec_context_res, &res);
119
*minor_status = 0;
120
return (GSS_S_BAD_MECH);
121
}
122
}
123
*context_handle = ctx;
124
ctx->handle = res.ctx;
125
if (actual_mech_type)
126
*actual_mech_type = KGSS_MECH_TYPE(ctx);
127
kgss_copy_buffer(&res.output_token, output_token);
128
if (ret_flags)
129
*ret_flags = res.ret_flags;
130
if (time_rec)
131
*time_rec = res.time_rec;
132
133
xdr_free((xdrproc_t) xdr_init_sec_context_res, &res);
134
135
/*
136
* If the context establishment is complete, export it from
137
* userland and hand the result (which includes key material
138
* etc.) to the kernel implementation.
139
*/
140
if (res.major_status == GSS_S_COMPLETE)
141
res.major_status = kgss_transfer_context(ctx, NULL);
142
143
return (res.major_status);
144
}
145
146
OM_uint32
147
gss_supports_lucid(uint32_t *minor_status, uint32_t *vers)
148
{
149
struct supports_lucid_res res;
150
enum clnt_stat stat;
151
CLIENT *cl;
152
153
*minor_status = 0;
154
155
cl = kgss_gssd_client();
156
if (cl == NULL)
157
return (GSS_S_FAILURE);
158
159
bzero(&res, sizeof(res));
160
stat = gssd_supports_lucid_1(NULL, &res, cl);
161
CLNT_RELEASE(cl);
162
if (stat != RPC_SUCCESS) {
163
*minor_status = stat;
164
return (GSS_S_FAILURE);
165
}
166
167
if (vers)
168
*vers = res.vers;
169
170
return (res.major_status);
171
}
172
173
/*
174
* This function should be called when the gssd daemon is
175
* one that uses gss_krb5_export_lucid_sec_context().
176
* There is a lot of code common with
177
* gss_init_sec_context(). However, the structures used
178
* are not the same and future changes may be needed for
179
* this one. As such, I have not factored out the common
180
* code.
181
* gss_supports_lucid() may be used to check to see if the
182
* gssd daemon uses gss_krb5_export_lucid_sec_context().
183
*/
184
OM_uint32
185
gss_init_sec_context_lucid_v1(OM_uint32 * minor_status,
186
const gss_cred_id_t initiator_cred_handle,
187
gss_ctx_id_t * context_handle,
188
const gss_name_t target_name,
189
const gss_OID input_mech_type,
190
OM_uint32 req_flags,
191
OM_uint32 time_req,
192
const gss_channel_bindings_t input_chan_bindings,
193
const gss_buffer_t input_token,
194
gss_OID * actual_mech_type,
195
gss_buffer_t output_token,
196
OM_uint32 * ret_flags,
197
OM_uint32 * time_rec)
198
{
199
struct init_sec_context_lucid_v1_res res;
200
struct init_sec_context_lucid_v1_args args;
201
enum clnt_stat stat;
202
gss_ctx_id_t ctx = *context_handle;
203
CLIENT *cl;
204
205
*minor_status = 0;
206
207
cl = kgss_gssd_client();
208
if (cl == NULL)
209
return (GSS_S_FAILURE);
210
211
args.uid = curthread->td_ucred->cr_uid;
212
if (initiator_cred_handle)
213
args.cred = initiator_cred_handle->handle;
214
else
215
args.cred = 0;
216
if (ctx)
217
args.ctx = ctx->handle;
218
else
219
args.ctx = 0;
220
args.name = target_name->handle;
221
args.mech_type = input_mech_type;
222
args.req_flags = req_flags;
223
args.time_req = time_req;
224
args.input_chan_bindings = input_chan_bindings;
225
if (input_token)
226
args.input_token = *input_token;
227
else {
228
args.input_token.length = 0;
229
args.input_token.value = NULL;
230
}
231
232
bzero(&res, sizeof(res));
233
stat = gssd_init_sec_context_lucid_v1_1(&args, &res, cl);
234
CLNT_RELEASE(cl);
235
if (stat != RPC_SUCCESS) {
236
*minor_status = stat;
237
return (GSS_S_FAILURE);
238
}
239
240
if (res.major_status != GSS_S_COMPLETE
241
&& res.major_status != GSS_S_CONTINUE_NEEDED) {
242
*minor_status = res.minor_status;
243
xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res);
244
return (res.major_status);
245
}
246
247
*minor_status = res.minor_status;
248
249
if (!ctx) {
250
ctx = kgss_create_context(res.actual_mech_type);
251
if (!ctx) {
252
xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res);
253
*minor_status = 0;
254
return (GSS_S_BAD_MECH);
255
}
256
}
257
*context_handle = ctx;
258
ctx->handle = res.ctx;
259
if (actual_mech_type)
260
*actual_mech_type = KGSS_MECH_TYPE(ctx);
261
kgss_copy_buffer(&res.output_token, output_token);
262
if (ret_flags)
263
*ret_flags = res.ret_flags;
264
if (time_rec)
265
*time_rec = res.time_rec;
266
267
/*
268
* If the context establishment is complete, export it from
269
* userland and hand the result (which includes key material
270
* etc.) to the kernel implementation.
271
*/
272
if (res.major_status == GSS_S_COMPLETE) {
273
res.major_status = kgss_transfer_context(ctx, &res.lucid);
274
if (res.major_status != GSS_S_COMPLETE)
275
printf("gss_init_sec_context_lucid_v1: "
276
"transfer failed\n");
277
}
278
279
xdr_free((xdrproc_t) xdr_init_sec_context_lucid_v1_res, &res);
280
281
return (res.major_status);
282
}
283
284