Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/sys/kgssapi/gss_accept_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
37
#include <kgssapi/gssapi.h>
38
#include <kgssapi/gssapi_impl.h>
39
#include <rpc/rpc.h>
40
41
#include "gssd.h"
42
#include "kgss_if.h"
43
44
/*
45
* This function should only be called when the gssd
46
* daemon running on the system is an old one that
47
* does not use gss_krb5_export_lucid_sec_context().
48
*/
49
OM_uint32 gss_accept_sec_context(OM_uint32 *minor_status,
50
gss_ctx_id_t *context_handle,
51
const gss_cred_id_t acceptor_cred_handle,
52
const gss_buffer_t input_token,
53
const gss_channel_bindings_t input_chan_bindings,
54
gss_name_t *src_name,
55
gss_OID *mech_type,
56
gss_buffer_t output_token,
57
OM_uint32 *ret_flags,
58
OM_uint32 *time_rec,
59
gss_cred_id_t *delegated_cred_handle)
60
{
61
struct accept_sec_context_res res;
62
struct accept_sec_context_args args;
63
enum clnt_stat stat;
64
gss_ctx_id_t ctx = *context_handle;
65
gss_name_t name;
66
gss_cred_id_t cred;
67
CLIENT *cl;
68
69
cl = kgss_gssd_client();
70
if (cl == NULL) {
71
*minor_status = 0;
72
return (GSS_S_FAILURE);
73
}
74
75
if (ctx)
76
args.ctx = ctx->handle;
77
else
78
args.ctx = 0;
79
if (acceptor_cred_handle)
80
args.cred = acceptor_cred_handle->handle;
81
else
82
args.cred = 0;
83
args.input_token = *input_token;
84
args.input_chan_bindings = input_chan_bindings;
85
86
bzero(&res, sizeof(res));
87
stat = gssd_accept_sec_context_1(&args, &res, cl);
88
CLNT_RELEASE(cl);
89
if (stat != RPC_SUCCESS) {
90
*minor_status = stat;
91
return (GSS_S_FAILURE);
92
}
93
94
if (res.major_status != GSS_S_COMPLETE
95
&& res.major_status != GSS_S_CONTINUE_NEEDED) {
96
*minor_status = res.minor_status;
97
xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res);
98
return (res.major_status);
99
}
100
101
*minor_status = res.minor_status;
102
103
if (!ctx) {
104
ctx = kgss_create_context(res.mech_type);
105
if (!ctx) {
106
xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res);
107
*minor_status = 0;
108
return (GSS_S_BAD_MECH);
109
}
110
}
111
*context_handle = ctx;
112
113
ctx->handle = res.ctx;
114
name = malloc(sizeof(struct _gss_name_t), M_GSSAPI, M_WAITOK);
115
name->handle = res.src_name;
116
if (src_name) {
117
*src_name = name;
118
} else {
119
OM_uint32 junk;
120
gss_release_name(&junk, &name);
121
}
122
if (mech_type)
123
*mech_type = KGSS_MECH_TYPE(ctx);
124
kgss_copy_buffer(&res.output_token, output_token);
125
if (ret_flags)
126
*ret_flags = res.ret_flags;
127
if (time_rec)
128
*time_rec = res.time_rec;
129
cred = malloc(sizeof(struct _gss_cred_id_t), M_GSSAPI, M_WAITOK);
130
cred->handle = res.delegated_cred_handle;
131
if (delegated_cred_handle) {
132
*delegated_cred_handle = cred;
133
} else {
134
OM_uint32 junk;
135
gss_release_cred(&junk, &cred);
136
}
137
138
xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res);
139
140
/*
141
* If the context establishment is complete, export it from
142
* userland and hand the result (which includes key material
143
* etc.) to the kernel implementation.
144
*/
145
if (res.major_status == GSS_S_COMPLETE)
146
res.major_status = kgss_transfer_context(ctx, NULL);
147
148
return (res.major_status);
149
}
150
151
/*
152
* This function should be called when the gssd daemon is
153
* one that uses gss_krb5_export_lucid_sec_context().
154
* There is a lot of code common with
155
* gss_accept_sec_context(). However, the structures used
156
* are not the same and future changes may be needed for
157
* this one. As such, I have not factored out the common
158
* code.
159
* gss_supports_lucid() may be used to check to see if the
160
* gssd daemon uses gss_krb5_export_lucid_sec_context().
161
*/
162
OM_uint32 gss_accept_sec_context_lucid_v1(OM_uint32 *minor_status,
163
gss_ctx_id_t *context_handle,
164
const gss_cred_id_t acceptor_cred_handle,
165
const gss_buffer_t input_token,
166
const gss_channel_bindings_t input_chan_bindings,
167
gss_name_t *src_name,
168
gss_OID *mech_type,
169
gss_buffer_t output_token,
170
OM_uint32 *ret_flags,
171
OM_uint32 *time_rec,
172
gss_cred_id_t *delegated_cred_handle,
173
gss_buffer_t exported_name,
174
uid_t *uidp,
175
gid_t *gidp,
176
int *numgroups,
177
gid_t *groups)
178
{
179
struct accept_sec_context_lucid_v1_res res;
180
struct accept_sec_context_lucid_v1_args args;
181
enum clnt_stat stat;
182
gss_ctx_id_t ctx = *context_handle;
183
gss_name_t name;
184
gss_cred_id_t cred;
185
CLIENT *cl;
186
187
cl = kgss_gssd_client();
188
if (cl == NULL) {
189
*minor_status = 0;
190
return (GSS_S_FAILURE);
191
}
192
193
if (ctx)
194
args.ctx = ctx->handle;
195
else
196
args.ctx = 0;
197
if (acceptor_cred_handle)
198
args.cred = acceptor_cred_handle->handle;
199
else
200
args.cred = 0;
201
args.input_token = *input_token;
202
args.input_chan_bindings = input_chan_bindings;
203
204
bzero(&res, sizeof(res));
205
stat = gssd_accept_sec_context_lucid_v1_1(&args, &res, cl);
206
CLNT_RELEASE(cl);
207
if (stat != RPC_SUCCESS) {
208
*minor_status = stat;
209
return (GSS_S_FAILURE);
210
}
211
212
if (res.major_status != GSS_S_COMPLETE
213
&& res.major_status != GSS_S_CONTINUE_NEEDED) {
214
*minor_status = res.minor_status;
215
xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res);
216
return (res.major_status);
217
}
218
219
*minor_status = res.minor_status;
220
221
if (!ctx) {
222
ctx = kgss_create_context(res.mech_type);
223
if (!ctx) {
224
xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res);
225
*minor_status = 0;
226
return (GSS_S_BAD_MECH);
227
}
228
}
229
*context_handle = ctx;
230
231
ctx->handle = res.ctx;
232
name = malloc(sizeof(struct _gss_name_t), M_GSSAPI, M_WAITOK);
233
name->handle = res.src_name;
234
if (src_name) {
235
*src_name = name;
236
} else {
237
OM_uint32 junk;
238
gss_release_name(&junk, &name);
239
}
240
if (mech_type)
241
*mech_type = KGSS_MECH_TYPE(ctx);
242
kgss_copy_buffer(&res.output_token, output_token);
243
if (ret_flags)
244
*ret_flags = res.ret_flags;
245
if (time_rec)
246
*time_rec = res.time_rec;
247
cred = malloc(sizeof(struct _gss_cred_id_t), M_GSSAPI, M_WAITOK);
248
cred->handle = res.delegated_cred_handle;
249
if (delegated_cred_handle) {
250
*delegated_cred_handle = cred;
251
} else {
252
OM_uint32 junk;
253
gss_release_cred(&junk, &cred);
254
}
255
256
/*
257
* If the context establishment is complete, export it from
258
* userland and hand the result (which includes key material
259
* etc.) to the kernel implementation.
260
*/
261
if (res.major_status == GSS_S_COMPLETE) {
262
int i, n;
263
264
/* First, get the unix credentials. */
265
*uidp = res.uid;
266
*gidp = res.gid;
267
n = res.gidlist.gidlist_len;
268
if (n > *numgroups)
269
n = *numgroups;
270
for (i = 0; i < n; i++)
271
groups[i] = res.gidlist.gidlist_val[i];
272
*numgroups = n;
273
274
/* Next, get the exported_name. */
275
kgss_copy_buffer(&res.exported_name, exported_name);
276
277
/* Now, handle the lucid credential setup. */
278
res.major_status = kgss_transfer_context(ctx, &res.lucid);
279
if (res.major_status != GSS_S_COMPLETE)
280
printf("gss_accept_sec_context_lucid_v1: "
281
"transfer failed\n");
282
}
283
284
xdr_free((xdrproc_t) xdr_accept_sec_context_res, &res);
285
286
return (res.major_status);
287
}
288
289