Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/kafs/afskrb5.c
34878 views
1
/*
2
* Copyright (c) 1995-2003 Kungliga Tekniska Högskolan
3
* (Royal Institute of Technology, Stockholm, Sweden).
4
* All rights reserved.
5
*
6
* Redistribution and use in source and binary forms, with or without
7
* modification, are permitted provided that the following conditions
8
* are met:
9
*
10
* 1. Redistributions of source code must retain the above copyright
11
* notice, this list of conditions and the following disclaimer.
12
*
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
* 3. Neither the name of the Institute nor the names of its contributors
18
* may be used to endorse or promote products derived from this software
19
* without specific prior written permission.
20
*
21
* THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24
* ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31
* SUCH DAMAGE.
32
*/
33
34
#include "kafs_locl.h"
35
36
struct krb5_kafs_data {
37
krb5_context context;
38
krb5_ccache id;
39
krb5_const_realm realm;
40
};
41
42
enum {
43
KAFS_RXKAD_2B_KVNO = 213,
44
KAFS_RXKAD_K5_KVNO = 256
45
};
46
47
static int
48
v5_to_kt(krb5_creds *cred, uid_t uid, struct kafs_token *kt, int local524)
49
{
50
int kvno, ret;
51
52
kt->ticket = NULL;
53
54
/* check if des key */
55
if (cred->session.keyvalue.length != 8)
56
return EINVAL;
57
58
if (local524) {
59
Ticket t;
60
unsigned char *buf;
61
size_t buf_len;
62
size_t len;
63
64
kvno = KAFS_RXKAD_2B_KVNO;
65
66
ret = decode_Ticket(cred->ticket.data, cred->ticket.length, &t, &len);
67
if (ret)
68
return ret;
69
if (t.tkt_vno != 5)
70
return -1;
71
72
ASN1_MALLOC_ENCODE(EncryptedData, buf, buf_len, &t.enc_part,
73
&len, ret);
74
free_Ticket(&t);
75
if (ret)
76
return ret;
77
if(buf_len != len) {
78
free(buf);
79
return KRB5KRB_ERR_GENERIC;
80
}
81
82
kt->ticket = buf;
83
kt->ticket_len = buf_len;
84
85
} else {
86
kvno = KAFS_RXKAD_K5_KVNO;
87
kt->ticket = malloc(cred->ticket.length);
88
if (kt->ticket == NULL)
89
return ENOMEM;
90
kt->ticket_len = cred->ticket.length;
91
memcpy(kt->ticket, cred->ticket.data, kt->ticket_len);
92
}
93
94
95
/*
96
* Build a struct ClearToken
97
*/
98
99
kt->ct.AuthHandle = kvno;
100
memcpy(kt->ct.HandShakeKey, cred->session.keyvalue.data, 8);
101
kt->ct.ViceId = uid;
102
kt->ct.BeginTimestamp = cred->times.starttime;
103
kt->ct.EndTimestamp = cred->times.endtime;
104
105
_kafs_fixup_viceid(&kt->ct, uid);
106
107
return 0;
108
}
109
110
static krb5_error_code
111
v5_convert(krb5_context context, krb5_ccache id,
112
krb5_creds *cred, uid_t uid,
113
const char *cell,
114
struct kafs_token *kt)
115
{
116
krb5_error_code ret;
117
char *c, *val;
118
119
c = strdup(cell);
120
if (c == NULL)
121
return ENOMEM;
122
_kafs_foldup(c, c);
123
krb5_appdefault_string (context, "libkafs",
124
c,
125
"afs-use-524", "2b", &val);
126
free(c);
127
128
if (strcasecmp(val, "local") == 0 ||
129
strcasecmp(val, "2b") == 0)
130
ret = v5_to_kt(cred, uid, kt, 1);
131
else
132
ret = v5_to_kt(cred, uid, kt, 0);
133
134
free(val);
135
return ret;
136
}
137
138
139
/*
140
*
141
*/
142
143
static int
144
get_cred(struct kafs_data *data, const char *name, const char *inst,
145
const char *realm, uid_t uid, struct kafs_token *kt)
146
{
147
krb5_error_code ret;
148
krb5_creds in_creds, *out_creds;
149
struct krb5_kafs_data *d = data->data;
150
int invalid;
151
152
memset(&in_creds, 0, sizeof(in_creds));
153
154
ret = krb5_make_principal(d->context, &in_creds.server,
155
realm, name, inst, NULL);
156
if(ret)
157
return ret;
158
ret = krb5_cc_get_principal(d->context, d->id, &in_creds.client);
159
if(ret){
160
krb5_free_principal(d->context, in_creds.server);
161
return ret;
162
}
163
164
in_creds.session.keytype = ETYPE_DES_CBC_CRC;
165
166
/* check if des is disable, and in that case enable it for afs */
167
invalid = krb5_enctype_valid(d->context, in_creds.session.keytype);
168
if (invalid)
169
krb5_enctype_enable(d->context, in_creds.session.keytype);
170
171
ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds);
172
if (ret) {
173
in_creds.session.keytype = ETYPE_DES_CBC_MD5;
174
ret = krb5_get_credentials(d->context, 0, d->id, &in_creds, &out_creds);
175
}
176
177
if (invalid)
178
krb5_enctype_disable(d->context, in_creds.session.keytype);
179
180
krb5_free_principal(d->context, in_creds.server);
181
krb5_free_principal(d->context, in_creds.client);
182
if(ret)
183
return ret;
184
185
ret = v5_convert(d->context, d->id, out_creds, uid,
186
(inst != NULL && inst[0] != '\0') ? inst : realm, kt);
187
krb5_free_creds(d->context, out_creds);
188
189
return ret;
190
}
191
192
static const char *
193
get_error(struct kafs_data *data, int error)
194
{
195
struct krb5_kafs_data *d = data->data;
196
return krb5_get_error_message(d->context, error);
197
}
198
199
static void
200
free_error(struct kafs_data *data, const char *str)
201
{
202
struct krb5_kafs_data *d = data->data;
203
krb5_free_error_message(d->context, str);
204
}
205
206
static krb5_error_code
207
afslog_uid_int(struct kafs_data *data, const char *cell, const char *rh,
208
uid_t uid, const char *homedir)
209
{
210
krb5_error_code ret;
211
struct kafs_token kt;
212
krb5_principal princ;
213
const char *trealm; /* ticket realm */
214
struct krb5_kafs_data *d = data->data;
215
216
if (cell == 0 || cell[0] == 0)
217
return _kafs_afslog_all_local_cells (data, uid, homedir);
218
219
ret = krb5_cc_get_principal (d->context, d->id, &princ);
220
if (ret)
221
return ret;
222
223
trealm = krb5_principal_get_realm (d->context, princ);
224
225
kt.ticket = NULL;
226
ret = _kafs_get_cred(data, cell, d->realm, trealm, uid, &kt);
227
krb5_free_principal (d->context, princ);
228
229
if(ret == 0) {
230
ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);
231
free(kt.ticket);
232
}
233
return ret;
234
}
235
236
static char *
237
get_realm(struct kafs_data *data, const char *host)
238
{
239
struct krb5_kafs_data *d = data->data;
240
krb5_realm *realms;
241
char *r;
242
if(krb5_get_host_realm(d->context, host, &realms))
243
return NULL;
244
r = strdup(realms[0]);
245
krb5_free_host_realm(d->context, realms);
246
return r;
247
}
248
249
krb5_error_code
250
krb5_afslog_uid_home(krb5_context context,
251
krb5_ccache id,
252
const char *cell,
253
krb5_const_realm realm,
254
uid_t uid,
255
const char *homedir)
256
{
257
struct kafs_data kd;
258
struct krb5_kafs_data d;
259
krb5_error_code ret;
260
261
kd.name = "krb5";
262
kd.afslog_uid = afslog_uid_int;
263
kd.get_cred = get_cred;
264
kd.get_realm = get_realm;
265
kd.get_error = get_error;
266
kd.free_error = free_error;
267
kd.data = &d;
268
if (context == NULL) {
269
ret = krb5_init_context(&d.context);
270
if (ret)
271
return ret;
272
} else
273
d.context = context;
274
if (id == NULL) {
275
ret = krb5_cc_default(d.context, &d.id);
276
if (ret)
277
goto out;
278
} else
279
d.id = id;
280
d.realm = realm;
281
ret = afslog_uid_int(&kd, cell, 0, uid, homedir);
282
if (id == NULL)
283
krb5_cc_close(context, d.id);
284
out:
285
if (context == NULL)
286
krb5_free_context(d.context);
287
return ret;
288
}
289
290
krb5_error_code
291
krb5_afslog_uid(krb5_context context,
292
krb5_ccache id,
293
const char *cell,
294
krb5_const_realm realm,
295
uid_t uid)
296
{
297
return krb5_afslog_uid_home (context, id, cell, realm, uid, NULL);
298
}
299
300
krb5_error_code
301
krb5_afslog(krb5_context context,
302
krb5_ccache id,
303
const char *cell,
304
krb5_const_realm realm)
305
{
306
return krb5_afslog_uid (context, id, cell, realm, getuid());
307
}
308
309
krb5_error_code
310
krb5_afslog_home(krb5_context context,
311
krb5_ccache id,
312
const char *cell,
313
krb5_const_realm realm,
314
const char *homedir)
315
{
316
return krb5_afslog_uid_home (context, id, cell, realm, getuid(), homedir);
317
}
318
319
/*
320
*
321
*/
322
323
krb5_error_code
324
krb5_realm_of_cell(const char *cell, char **realm)
325
{
326
struct kafs_data kd;
327
328
kd.name = "krb5";
329
kd.get_realm = get_realm;
330
kd.get_error = get_error;
331
kd.free_error = free_error;
332
return _kafs_realm_of_cell(&kd, cell, realm);
333
}
334
335
/*
336
*
337
*/
338
339
int
340
kafs_settoken5(krb5_context context, const char *cell, uid_t uid,
341
krb5_creds *cred)
342
{
343
struct kafs_token kt;
344
int ret;
345
346
ret = v5_convert(context, NULL, cred, uid, cell, &kt);
347
if (ret)
348
return ret;
349
350
ret = kafs_settoken_rxkad(cell, &kt.ct, kt.ticket, kt.ticket_len);
351
352
free(kt.ticket);
353
354
return ret;
355
}
356
357