Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/crypto/heimdal/lib/gssapi/krb5/8003.c
34923 views
1
/*
2
* Copyright (c) 1997 - 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 "gsskrb5_locl.h"
35
36
krb5_error_code
37
_gsskrb5_encode_om_uint32(OM_uint32 n, u_char *p)
38
{
39
p[0] = (n >> 0) & 0xFF;
40
p[1] = (n >> 8) & 0xFF;
41
p[2] = (n >> 16) & 0xFF;
42
p[3] = (n >> 24) & 0xFF;
43
return 0;
44
}
45
46
krb5_error_code
47
_gsskrb5_encode_be_om_uint32(OM_uint32 n, u_char *p)
48
{
49
p[0] = (n >> 24) & 0xFF;
50
p[1] = (n >> 16) & 0xFF;
51
p[2] = (n >> 8) & 0xFF;
52
p[3] = (n >> 0) & 0xFF;
53
return 0;
54
}
55
56
krb5_error_code
57
_gsskrb5_decode_om_uint32(const void *ptr, OM_uint32 *n)
58
{
59
const u_char *p = ptr;
60
*n = (p[0] << 0) | (p[1] << 8) | (p[2] << 16) | (p[3] << 24);
61
return 0;
62
}
63
64
krb5_error_code
65
_gsskrb5_decode_be_om_uint32(const void *ptr, OM_uint32 *n)
66
{
67
const u_char *p = ptr;
68
*n = (p[0] <<24) | (p[1] << 16) | (p[2] << 8) | (p[3] << 0);
69
return 0;
70
}
71
72
static krb5_error_code
73
hash_input_chan_bindings (const gss_channel_bindings_t b,
74
u_char *p)
75
{
76
u_char num[4];
77
EVP_MD_CTX *ctx;
78
79
ctx = EVP_MD_CTX_create();
80
EVP_DigestInit_ex(ctx, EVP_md5(), NULL);
81
82
_gsskrb5_encode_om_uint32 (b->initiator_addrtype, num);
83
EVP_DigestUpdate(ctx, num, sizeof(num));
84
_gsskrb5_encode_om_uint32 (b->initiator_address.length, num);
85
EVP_DigestUpdate(ctx, num, sizeof(num));
86
if (b->initiator_address.length)
87
EVP_DigestUpdate(ctx,
88
b->initiator_address.value,
89
b->initiator_address.length);
90
_gsskrb5_encode_om_uint32 (b->acceptor_addrtype, num);
91
EVP_DigestUpdate(ctx, num, sizeof(num));
92
_gsskrb5_encode_om_uint32 (b->acceptor_address.length, num);
93
EVP_DigestUpdate(ctx, num, sizeof(num));
94
if (b->acceptor_address.length)
95
EVP_DigestUpdate(ctx,
96
b->acceptor_address.value,
97
b->acceptor_address.length);
98
_gsskrb5_encode_om_uint32 (b->application_data.length, num);
99
EVP_DigestUpdate(ctx, num, sizeof(num));
100
if (b->application_data.length)
101
EVP_DigestUpdate(ctx,
102
b->application_data.value,
103
b->application_data.length);
104
EVP_DigestFinal_ex(ctx, p, NULL);
105
EVP_MD_CTX_destroy(ctx);
106
107
return 0;
108
}
109
110
/*
111
* create a checksum over the chanel bindings in
112
* `input_chan_bindings', `flags' and `fwd_data' and return it in
113
* `result'
114
*/
115
116
OM_uint32
117
_gsskrb5_create_8003_checksum (
118
OM_uint32 *minor_status,
119
const gss_channel_bindings_t input_chan_bindings,
120
OM_uint32 flags,
121
const krb5_data *fwd_data,
122
Checksum *result)
123
{
124
u_char *p;
125
126
/*
127
* see rfc1964 (section 1.1.1 (Initial Token), and the checksum value
128
* field's format) */
129
result->cksumtype = CKSUMTYPE_GSSAPI;
130
if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG))
131
result->checksum.length = 24 + 4 + fwd_data->length;
132
else
133
result->checksum.length = 24;
134
result->checksum.data = malloc (result->checksum.length);
135
if (result->checksum.data == NULL) {
136
*minor_status = ENOMEM;
137
return GSS_S_FAILURE;
138
}
139
140
p = result->checksum.data;
141
_gsskrb5_encode_om_uint32 (16, p);
142
p += 4;
143
if (input_chan_bindings == GSS_C_NO_CHANNEL_BINDINGS) {
144
memset (p, 0, 16);
145
} else {
146
hash_input_chan_bindings (input_chan_bindings, p);
147
}
148
p += 16;
149
_gsskrb5_encode_om_uint32 (flags, p);
150
p += 4;
151
152
if (fwd_data->length > 0 && (flags & GSS_C_DELEG_FLAG)) {
153
154
*p++ = (1 >> 0) & 0xFF; /* DlgOpt */ /* == 1 */
155
*p++ = (1 >> 8) & 0xFF; /* DlgOpt */ /* == 0 */
156
*p++ = (fwd_data->length >> 0) & 0xFF; /* Dlgth */
157
*p++ = (fwd_data->length >> 8) & 0xFF; /* Dlgth */
158
memcpy(p, (unsigned char *) fwd_data->data, fwd_data->length);
159
160
p += fwd_data->length;
161
}
162
163
return GSS_S_COMPLETE;
164
}
165
166
/*
167
* verify the checksum in `cksum' over `input_chan_bindings'
168
* returning `flags' and `fwd_data'
169
*/
170
171
OM_uint32
172
_gsskrb5_verify_8003_checksum(
173
OM_uint32 *minor_status,
174
const gss_channel_bindings_t input_chan_bindings,
175
const Checksum *cksum,
176
OM_uint32 *flags,
177
krb5_data *fwd_data)
178
{
179
unsigned char hash[16];
180
unsigned char *p;
181
OM_uint32 length;
182
int DlgOpt;
183
static unsigned char zeros[16];
184
185
/* XXX should handle checksums > 24 bytes */
186
if(cksum->cksumtype != CKSUMTYPE_GSSAPI || cksum->checksum.length < 24) {
187
*minor_status = 0;
188
return GSS_S_BAD_BINDINGS;
189
}
190
191
p = cksum->checksum.data;
192
_gsskrb5_decode_om_uint32(p, &length);
193
if(length != sizeof(hash)) {
194
*minor_status = 0;
195
return GSS_S_BAD_BINDINGS;
196
}
197
198
p += 4;
199
200
if (input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS
201
&& memcmp(p, zeros, sizeof(zeros)) != 0) {
202
if(hash_input_chan_bindings(input_chan_bindings, hash) != 0) {
203
*minor_status = 0;
204
return GSS_S_BAD_BINDINGS;
205
}
206
if(ct_memcmp(hash, p, sizeof(hash)) != 0) {
207
*minor_status = 0;
208
return GSS_S_BAD_BINDINGS;
209
}
210
}
211
212
p += sizeof(hash);
213
214
_gsskrb5_decode_om_uint32(p, flags);
215
p += 4;
216
217
if (cksum->checksum.length > 24 && (*flags & GSS_C_DELEG_FLAG)) {
218
if(cksum->checksum.length < 28) {
219
*minor_status = 0;
220
return GSS_S_BAD_BINDINGS;
221
}
222
223
DlgOpt = (p[0] << 0) | (p[1] << 8);
224
p += 2;
225
if (DlgOpt != 1) {
226
*minor_status = 0;
227
return GSS_S_BAD_BINDINGS;
228
}
229
230
fwd_data->length = (p[0] << 0) | (p[1] << 8);
231
p += 2;
232
if(cksum->checksum.length < 28 + fwd_data->length) {
233
*minor_status = 0;
234
return GSS_S_BAD_BINDINGS;
235
}
236
fwd_data->data = malloc(fwd_data->length);
237
if (fwd_data->data == NULL) {
238
*minor_status = ENOMEM;
239
return GSS_S_FAILURE;
240
}
241
memcpy(fwd_data->data, p, fwd_data->length);
242
}
243
244
return GSS_S_COMPLETE;
245
}
246
247