xref: /netbsd-src/crypto/external/bsd/heimdal/dist/lib/krb5/rd_safe.c (revision d3273b5b76f5afaafe308cead5511dbb8df8c5e9)
1*d3273b5bSchristos /*	$NetBSD: rd_safe.c,v 1.2 2017/01/28 21:31:49 christos Exp $	*/
2ca1c9b0cSelric 
3ca1c9b0cSelric /*
4ca1c9b0cSelric  * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
5ca1c9b0cSelric  * (Royal Institute of Technology, Stockholm, Sweden).
6ca1c9b0cSelric  * All rights reserved.
7ca1c9b0cSelric  *
8ca1c9b0cSelric  * Redistribution and use in source and binary forms, with or without
9ca1c9b0cSelric  * modification, are permitted provided that the following conditions
10ca1c9b0cSelric  * are met:
11ca1c9b0cSelric  *
12ca1c9b0cSelric  * 1. Redistributions of source code must retain the above copyright
13ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer.
14ca1c9b0cSelric  *
15ca1c9b0cSelric  * 2. Redistributions in binary form must reproduce the above copyright
16ca1c9b0cSelric  *    notice, this list of conditions and the following disclaimer in the
17ca1c9b0cSelric  *    documentation and/or other materials provided with the distribution.
18ca1c9b0cSelric  *
19ca1c9b0cSelric  * 3. Neither the name of the Institute nor the names of its contributors
20ca1c9b0cSelric  *    may be used to endorse or promote products derived from this software
21ca1c9b0cSelric  *    without specific prior written permission.
22ca1c9b0cSelric  *
23ca1c9b0cSelric  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
24ca1c9b0cSelric  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
25ca1c9b0cSelric  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
26ca1c9b0cSelric  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
27ca1c9b0cSelric  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
28ca1c9b0cSelric  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
29ca1c9b0cSelric  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
30ca1c9b0cSelric  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
31ca1c9b0cSelric  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
32ca1c9b0cSelric  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
33ca1c9b0cSelric  * SUCH DAMAGE.
34ca1c9b0cSelric  */
35ca1c9b0cSelric 
36ca1c9b0cSelric #include "krb5_locl.h"
37ca1c9b0cSelric 
38ca1c9b0cSelric static krb5_error_code
verify_checksum(krb5_context context,krb5_auth_context auth_context,KRB_SAFE * safe)39ca1c9b0cSelric verify_checksum(krb5_context context,
40ca1c9b0cSelric 		krb5_auth_context auth_context,
41ca1c9b0cSelric 		KRB_SAFE *safe)
42ca1c9b0cSelric {
43ca1c9b0cSelric     krb5_error_code ret;
44ca1c9b0cSelric     u_char *buf;
45ca1c9b0cSelric     size_t buf_size;
464f77a458Spettai     size_t len = 0;
47ca1c9b0cSelric     Checksum c;
48ca1c9b0cSelric     krb5_crypto crypto;
49ca1c9b0cSelric     krb5_keyblock *key;
50ca1c9b0cSelric 
51ca1c9b0cSelric     c = safe->cksum;
52ca1c9b0cSelric     safe->cksum.cksumtype       = 0;
53ca1c9b0cSelric     safe->cksum.checksum.data   = NULL;
54ca1c9b0cSelric     safe->cksum.checksum.length = 0;
55ca1c9b0cSelric 
56ca1c9b0cSelric     ASN1_MALLOC_ENCODE(KRB_SAFE, buf, buf_size, safe, &len, ret);
57ca1c9b0cSelric     if(ret)
58ca1c9b0cSelric 	return ret;
59ca1c9b0cSelric     if(buf_size != len)
60ca1c9b0cSelric 	krb5_abortx(context, "internal error in ASN.1 encoder");
61ca1c9b0cSelric 
62ca1c9b0cSelric     if (auth_context->remote_subkey)
63ca1c9b0cSelric 	key = auth_context->remote_subkey;
64ca1c9b0cSelric     else if (auth_context->local_subkey)
65ca1c9b0cSelric 	key = auth_context->local_subkey;
66ca1c9b0cSelric     else
67ca1c9b0cSelric 	key = auth_context->keyblock;
68ca1c9b0cSelric 
69ca1c9b0cSelric     ret = krb5_crypto_init(context, key, 0, &crypto);
70ca1c9b0cSelric     if (ret)
71ca1c9b0cSelric 	goto out;
72ca1c9b0cSelric     ret = krb5_verify_checksum (context,
73ca1c9b0cSelric 				crypto,
74ca1c9b0cSelric 				KRB5_KU_KRB_SAFE_CKSUM,
75ca1c9b0cSelric 				buf + buf_size - len,
76ca1c9b0cSelric 				len,
77ca1c9b0cSelric 				&c);
78ca1c9b0cSelric     krb5_crypto_destroy(context, crypto);
79ca1c9b0cSelric out:
80ca1c9b0cSelric     safe->cksum = c;
81ca1c9b0cSelric     free (buf);
82ca1c9b0cSelric     return ret;
83ca1c9b0cSelric }
84ca1c9b0cSelric 
85ca1c9b0cSelric KRB5_LIB_FUNCTION krb5_error_code KRB5_LIB_CALL
krb5_rd_safe(krb5_context context,krb5_auth_context auth_context,const krb5_data * inbuf,krb5_data * outbuf,krb5_replay_data * outdata)86ca1c9b0cSelric krb5_rd_safe(krb5_context context,
87ca1c9b0cSelric 	     krb5_auth_context auth_context,
88ca1c9b0cSelric 	     const krb5_data *inbuf,
89ca1c9b0cSelric 	     krb5_data *outbuf,
90ca1c9b0cSelric 	     krb5_replay_data *outdata)
91ca1c9b0cSelric {
92ca1c9b0cSelric     krb5_error_code ret;
93ca1c9b0cSelric     KRB_SAFE safe;
94ca1c9b0cSelric     size_t len;
95ca1c9b0cSelric 
96ca1c9b0cSelric     krb5_data_zero(outbuf);
97ca1c9b0cSelric 
98ca1c9b0cSelric     if ((auth_context->flags &
99ca1c9b0cSelric 	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE)))
100ca1c9b0cSelric     {
101ca1c9b0cSelric 	if (outdata == NULL) {
102ca1c9b0cSelric 	    krb5_set_error_message(context, KRB5_RC_REQUIRED,
103ca1c9b0cSelric 				   N_("rd_safe: need outdata "
104ca1c9b0cSelric 				      "to return data", ""));
105ca1c9b0cSelric 	    return KRB5_RC_REQUIRED; /* XXX better error, MIT returns this */
106ca1c9b0cSelric 	}
107ca1c9b0cSelric 	/* if these fields are not present in the safe-part, silently
108ca1c9b0cSelric            return zero */
109ca1c9b0cSelric 	memset(outdata, 0, sizeof(*outdata));
110ca1c9b0cSelric     }
111ca1c9b0cSelric 
112ca1c9b0cSelric     ret = decode_KRB_SAFE (inbuf->data, inbuf->length, &safe, &len);
113ca1c9b0cSelric     if (ret)
114ca1c9b0cSelric 	return ret;
115ca1c9b0cSelric     if (safe.pvno != 5) {
116ca1c9b0cSelric 	ret = KRB5KRB_AP_ERR_BADVERSION;
117ca1c9b0cSelric 	krb5_clear_error_message (context);
118ca1c9b0cSelric 	goto failure;
119ca1c9b0cSelric     }
120ca1c9b0cSelric     if (safe.msg_type != krb_safe) {
121ca1c9b0cSelric 	ret = KRB5KRB_AP_ERR_MSG_TYPE;
122ca1c9b0cSelric 	krb5_clear_error_message (context);
123ca1c9b0cSelric 	goto failure;
124ca1c9b0cSelric     }
125ca1c9b0cSelric     if (!krb5_checksum_is_keyed(context, safe.cksum.cksumtype)
126ca1c9b0cSelric 	|| !krb5_checksum_is_collision_proof(context, safe.cksum.cksumtype)) {
127ca1c9b0cSelric 	ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
128ca1c9b0cSelric 	krb5_clear_error_message (context);
129ca1c9b0cSelric 	goto failure;
130ca1c9b0cSelric     }
131ca1c9b0cSelric 
132ca1c9b0cSelric     /* check sender address */
133ca1c9b0cSelric 
134ca1c9b0cSelric     if (safe.safe_body.s_address
135ca1c9b0cSelric 	&& auth_context->remote_address
136ca1c9b0cSelric 	&& !krb5_address_compare (context,
137ca1c9b0cSelric 				  auth_context->remote_address,
138ca1c9b0cSelric 				  safe.safe_body.s_address)) {
139ca1c9b0cSelric 	ret = KRB5KRB_AP_ERR_BADADDR;
140ca1c9b0cSelric 	krb5_clear_error_message (context);
141ca1c9b0cSelric 	goto failure;
142ca1c9b0cSelric     }
143ca1c9b0cSelric 
144ca1c9b0cSelric     /* check receiver address */
145ca1c9b0cSelric 
146ca1c9b0cSelric     if (safe.safe_body.r_address
147ca1c9b0cSelric 	&& auth_context->local_address
148ca1c9b0cSelric 	&& !krb5_address_compare (context,
149ca1c9b0cSelric 				  auth_context->local_address,
150ca1c9b0cSelric 				  safe.safe_body.r_address)) {
151ca1c9b0cSelric 	ret = KRB5KRB_AP_ERR_BADADDR;
152ca1c9b0cSelric 	krb5_clear_error_message (context);
153ca1c9b0cSelric 	goto failure;
154ca1c9b0cSelric     }
155ca1c9b0cSelric 
156ca1c9b0cSelric     /* check timestamp */
157ca1c9b0cSelric     if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_TIME) {
158ca1c9b0cSelric 	krb5_timestamp sec;
159ca1c9b0cSelric 
160ca1c9b0cSelric 	krb5_timeofday (context, &sec);
161ca1c9b0cSelric 
162ca1c9b0cSelric 	if (safe.safe_body.timestamp == NULL ||
163ca1c9b0cSelric 	    safe.safe_body.usec      == NULL ||
164b9d004c6Schristos 	    labs(*safe.safe_body.timestamp - sec) > context->max_skew) {
165ca1c9b0cSelric 	    ret = KRB5KRB_AP_ERR_SKEW;
166ca1c9b0cSelric 	    krb5_clear_error_message (context);
167ca1c9b0cSelric 	    goto failure;
168ca1c9b0cSelric 	}
169ca1c9b0cSelric     }
170ca1c9b0cSelric     /* XXX - check replay cache */
171ca1c9b0cSelric 
172ca1c9b0cSelric     /* check sequence number. since MIT krb5 cannot generate a sequence
173ca1c9b0cSelric        number of zero but instead generates no sequence number, we accept that
174ca1c9b0cSelric     */
175ca1c9b0cSelric 
176ca1c9b0cSelric     if (auth_context->flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
177ca1c9b0cSelric 	if ((safe.safe_body.seq_number == NULL
178ca1c9b0cSelric 	     && auth_context->remote_seqnumber != 0)
179ca1c9b0cSelric 	    || (safe.safe_body.seq_number != NULL
180ca1c9b0cSelric 		&& *safe.safe_body.seq_number !=
181ca1c9b0cSelric 		auth_context->remote_seqnumber)) {
182ca1c9b0cSelric 	    ret = KRB5KRB_AP_ERR_BADORDER;
183ca1c9b0cSelric 	    krb5_clear_error_message (context);
184ca1c9b0cSelric 	    goto failure;
185ca1c9b0cSelric 	}
186ca1c9b0cSelric 	auth_context->remote_seqnumber++;
187ca1c9b0cSelric     }
188ca1c9b0cSelric 
189ca1c9b0cSelric     ret = verify_checksum (context, auth_context, &safe);
190ca1c9b0cSelric     if (ret)
191ca1c9b0cSelric 	goto failure;
192ca1c9b0cSelric 
193ca1c9b0cSelric     outbuf->length = safe.safe_body.user_data.length;
194ca1c9b0cSelric     outbuf->data   = malloc(outbuf->length);
195ca1c9b0cSelric     if (outbuf->data == NULL && outbuf->length != 0) {
196b9d004c6Schristos 	ret = krb5_enomem(context);
197ca1c9b0cSelric 	krb5_data_zero(outbuf);
198ca1c9b0cSelric 	goto failure;
199ca1c9b0cSelric     }
200ca1c9b0cSelric     memcpy (outbuf->data, safe.safe_body.user_data.data, outbuf->length);
201ca1c9b0cSelric 
202ca1c9b0cSelric     if ((auth_context->flags &
203ca1c9b0cSelric 	 (KRB5_AUTH_CONTEXT_RET_TIME | KRB5_AUTH_CONTEXT_RET_SEQUENCE))) {
204ca1c9b0cSelric 
205ca1c9b0cSelric 	if(safe.safe_body.timestamp)
206ca1c9b0cSelric 	    outdata->timestamp = *safe.safe_body.timestamp;
207ca1c9b0cSelric 	if(safe.safe_body.usec)
208ca1c9b0cSelric 	    outdata->usec = *safe.safe_body.usec;
209ca1c9b0cSelric 	if(safe.safe_body.seq_number)
210ca1c9b0cSelric 	    outdata->seq = *safe.safe_body.seq_number;
211ca1c9b0cSelric     }
212ca1c9b0cSelric 
213ca1c9b0cSelric   failure:
214ca1c9b0cSelric     free_KRB_SAFE (&safe);
215ca1c9b0cSelric     return ret;
216ca1c9b0cSelric }
217