1 /* $NetBSD: 8003.c,v 1.1.1.2 2014/04/24 12:45:29 pettai Exp $ */
4 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
5 * (Royal Institute of Technology, Stockholm, Sweden).
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in the
17 * documentation and/or other materials provided with the distribution.
19 * 3. Neither the name of the Institute nor the names of its contributors
20 * may be used to endorse or promote products derived from this software
21 * without specific prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26 * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 #include "gsskrb5_locl.h"
39 _gsskrb5_encode_om_uint32(OM_uint32 n
, u_char
*p
)
41 p
[0] = (n
>> 0) & 0xFF;
42 p
[1] = (n
>> 8) & 0xFF;
43 p
[2] = (n
>> 16) & 0xFF;
44 p
[3] = (n
>> 24) & 0xFF;
49 _gsskrb5_encode_be_om_uint32(OM_uint32 n
, u_char
*p
)
51 p
[0] = (n
>> 24) & 0xFF;
52 p
[1] = (n
>> 16) & 0xFF;
53 p
[2] = (n
>> 8) & 0xFF;
54 p
[3] = (n
>> 0) & 0xFF;
59 _gsskrb5_decode_om_uint32(const void *ptr
, OM_uint32
*n
)
61 const u_char
*p
= ptr
;
62 *n
= (p
[0] << 0) | (p
[1] << 8) | (p
[2] << 16) | (p
[3] << 24);
67 _gsskrb5_decode_be_om_uint32(const void *ptr
, OM_uint32
*n
)
69 const u_char
*p
= ptr
;
70 *n
= (p
[0] <<24) | (p
[1] << 16) | (p
[2] << 8) | (p
[3] << 0);
74 static krb5_error_code
75 hash_input_chan_bindings (const gss_channel_bindings_t b
,
81 ctx
= EVP_MD_CTX_create();
82 EVP_DigestInit_ex(ctx
, EVP_md5(), NULL
);
84 _gsskrb5_encode_om_uint32 (b
->initiator_addrtype
, num
);
85 EVP_DigestUpdate(ctx
, num
, sizeof(num
));
86 _gsskrb5_encode_om_uint32 (b
->initiator_address
.length
, num
);
87 EVP_DigestUpdate(ctx
, num
, sizeof(num
));
88 if (b
->initiator_address
.length
)
90 b
->initiator_address
.value
,
91 b
->initiator_address
.length
);
92 _gsskrb5_encode_om_uint32 (b
->acceptor_addrtype
, num
);
93 EVP_DigestUpdate(ctx
, num
, sizeof(num
));
94 _gsskrb5_encode_om_uint32 (b
->acceptor_address
.length
, num
);
95 EVP_DigestUpdate(ctx
, num
, sizeof(num
));
96 if (b
->acceptor_address
.length
)
98 b
->acceptor_address
.value
,
99 b
->acceptor_address
.length
);
100 _gsskrb5_encode_om_uint32 (b
->application_data
.length
, num
);
101 EVP_DigestUpdate(ctx
, num
, sizeof(num
));
102 if (b
->application_data
.length
)
103 EVP_DigestUpdate(ctx
,
104 b
->application_data
.value
,
105 b
->application_data
.length
);
106 EVP_DigestFinal_ex(ctx
, p
, NULL
);
107 EVP_MD_CTX_destroy(ctx
);
113 * create a checksum over the chanel bindings in
114 * `input_chan_bindings', `flags' and `fwd_data' and return it in
119 _gsskrb5_create_8003_checksum (
120 OM_uint32
*minor_status
,
121 const gss_channel_bindings_t input_chan_bindings
,
123 const krb5_data
*fwd_data
,
129 * see rfc1964 (section 1.1.1 (Initial Token), and the checksum value
131 result
->cksumtype
= CKSUMTYPE_GSSAPI
;
132 if (fwd_data
->length
> 0 && (flags
& GSS_C_DELEG_FLAG
))
133 result
->checksum
.length
= 24 + 4 + fwd_data
->length
;
135 result
->checksum
.length
= 24;
136 result
->checksum
.data
= malloc (result
->checksum
.length
);
137 if (result
->checksum
.data
== NULL
) {
138 *minor_status
= ENOMEM
;
139 return GSS_S_FAILURE
;
142 p
= result
->checksum
.data
;
143 _gsskrb5_encode_om_uint32 (16, p
);
145 if (input_chan_bindings
== GSS_C_NO_CHANNEL_BINDINGS
) {
148 hash_input_chan_bindings (input_chan_bindings
, p
);
151 _gsskrb5_encode_om_uint32 (flags
, p
);
154 if (fwd_data
->length
> 0 && (flags
& GSS_C_DELEG_FLAG
)) {
156 *p
++ = (1 >> 0) & 0xFF; /* DlgOpt */ /* == 1 */
157 *p
++ = (1 >> 8) & 0xFF; /* DlgOpt */ /* == 0 */
158 *p
++ = (fwd_data
->length
>> 0) & 0xFF; /* Dlgth */
159 *p
++ = (fwd_data
->length
>> 8) & 0xFF; /* Dlgth */
160 memcpy(p
, (unsigned char *) fwd_data
->data
, fwd_data
->length
);
162 p
+= fwd_data
->length
;
165 return GSS_S_COMPLETE
;
169 * verify the checksum in `cksum' over `input_chan_bindings'
170 * returning `flags' and `fwd_data'
174 _gsskrb5_verify_8003_checksum(
175 OM_uint32
*minor_status
,
176 const gss_channel_bindings_t input_chan_bindings
,
177 const Checksum
*cksum
,
181 unsigned char hash
[16];
185 static unsigned char zeros
[16];
187 /* XXX should handle checksums > 24 bytes */
188 if(cksum
->cksumtype
!= CKSUMTYPE_GSSAPI
|| cksum
->checksum
.length
< 24) {
190 return GSS_S_BAD_BINDINGS
;
193 p
= cksum
->checksum
.data
;
194 _gsskrb5_decode_om_uint32(p
, &length
);
195 if(length
!= sizeof(hash
)) {
197 return GSS_S_BAD_BINDINGS
;
202 if (input_chan_bindings
!= GSS_C_NO_CHANNEL_BINDINGS
203 && memcmp(p
, zeros
, sizeof(zeros
)) != 0) {
204 if(hash_input_chan_bindings(input_chan_bindings
, hash
) != 0) {
206 return GSS_S_BAD_BINDINGS
;
208 if(ct_memcmp(hash
, p
, sizeof(hash
)) != 0) {
210 return GSS_S_BAD_BINDINGS
;
216 _gsskrb5_decode_om_uint32(p
, flags
);
219 if (cksum
->checksum
.length
> 24 && (*flags
& GSS_C_DELEG_FLAG
)) {
220 if(cksum
->checksum
.length
< 28) {
222 return GSS_S_BAD_BINDINGS
;
225 DlgOpt
= (p
[0] << 0) | (p
[1] << 8);
229 return GSS_S_BAD_BINDINGS
;
232 fwd_data
->length
= (p
[0] << 0) | (p
[1] << 8);
234 if(cksum
->checksum
.length
< 28 + fwd_data
->length
) {
236 return GSS_S_BAD_BINDINGS
;
238 fwd_data
->data
= malloc(fwd_data
->length
);
239 if (fwd_data
->data
== NULL
) {
240 *minor_status
= ENOMEM
;
241 return GSS_S_FAILURE
;
243 memcpy(fwd_data
->data
, p
, fwd_data
->length
);
246 return GSS_S_COMPLETE
;