2 * Copyright (c) 1997 - 2003 Kungliga Tekniska Högskolan
3 * (Royal Institute of Technology, Stockholm, Sweden).
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
10 * 1. Redistributions of source code must retain the above copyright
11 * 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.
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.
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
34 #include <krb5_locl.h>
36 __RCSID("$Heimdal: rd_safe.c 19827 2007-01-11 02:54:59Z lha $"
39 static krb5_error_code
40 verify_checksum(krb5_context context
,
41 krb5_auth_context auth_context
,
53 safe
->cksum
.cksumtype
= 0;
54 safe
->cksum
.checksum
.data
= NULL
;
55 safe
->cksum
.checksum
.length
= 0;
57 ASN1_MALLOC_ENCODE(KRB_SAFE
, buf
, buf_size
, safe
, &len
, ret
);
61 krb5_abortx(context
, "internal error in ASN.1 encoder");
63 if (auth_context
->remote_subkey
)
64 key
= auth_context
->remote_subkey
;
65 else if (auth_context
->local_subkey
)
66 key
= auth_context
->local_subkey
;
68 key
= auth_context
->keyblock
;
70 ret
= krb5_crypto_init(context
, key
, 0, &crypto
);
73 ret
= krb5_verify_checksum (context
,
75 KRB5_KU_KRB_SAFE_CKSUM
,
79 krb5_crypto_destroy(context
, crypto
);
86 krb5_error_code KRB5_LIB_FUNCTION
87 krb5_rd_safe(krb5_context context
,
88 krb5_auth_context auth_context
,
89 const krb5_data
*inbuf
,
91 krb5_replay_data
*outdata
)
98 krb5_data_zero(outbuf
);
100 if ((auth_context
->flags
&
101 (KRB5_AUTH_CONTEXT_RET_TIME
| KRB5_AUTH_CONTEXT_RET_SEQUENCE
)) &&
103 krb5_set_error_string(context
, "rd_safe: need outdata to return data");
104 return KRB5_RC_REQUIRED
; /* XXX better error, MIT returns this */
107 ret
= decode_KRB_SAFE (inbuf
->data
, inbuf
->length
, &safe
, &len
);
110 if (safe
.pvno
!= 5) {
111 ret
= KRB5KRB_AP_ERR_BADVERSION
;
112 krb5_clear_error_string (context
);
115 if (safe
.msg_type
!= krb_safe
) {
116 ret
= KRB5KRB_AP_ERR_MSG_TYPE
;
117 krb5_clear_error_string (context
);
120 if (!krb5_checksum_is_keyed(context
, safe
.cksum
.cksumtype
)
121 || !krb5_checksum_is_collision_proof(context
, safe
.cksum
.cksumtype
)) {
122 ret
= KRB5KRB_AP_ERR_INAPP_CKSUM
;
123 krb5_clear_error_string (context
);
127 /* check sender address */
129 if (safe
.safe_body
.s_address
130 && auth_context
->remote_address
131 && !krb5_address_compare (context
,
132 auth_context
->remote_address
,
133 safe
.safe_body
.s_address
)) {
134 ret
= KRB5KRB_AP_ERR_BADADDR
;
135 krb5_clear_error_string (context
);
139 /* check receiver address */
141 if (safe
.safe_body
.r_address
142 && auth_context
->local_address
143 && !krb5_address_compare (context
,
144 auth_context
->local_address
,
145 safe
.safe_body
.r_address
)) {
146 ret
= KRB5KRB_AP_ERR_BADADDR
;
147 krb5_clear_error_string (context
);
151 /* check timestamp */
152 if (auth_context
->flags
& KRB5_AUTH_CONTEXT_DO_TIME
) {
155 krb5_timeofday (context
, &sec
);
157 if (safe
.safe_body
.timestamp
== NULL
||
158 safe
.safe_body
.usec
== NULL
||
159 abs(*safe
.safe_body
.timestamp
- sec
) > context
->max_skew
) {
160 ret
= KRB5KRB_AP_ERR_SKEW
;
161 krb5_clear_error_string (context
);
165 /* XXX - check replay cache */
167 /* check sequence number. since MIT krb5 cannot generate a sequence
168 number of zero but instead generates no sequence number, we accept that
171 if (auth_context
->flags
& KRB5_AUTH_CONTEXT_DO_SEQUENCE
) {
172 if ((safe
.safe_body
.seq_number
== NULL
173 && auth_context
->remote_seqnumber
!= 0)
174 || (safe
.safe_body
.seq_number
!= NULL
175 && *safe
.safe_body
.seq_number
!=
176 auth_context
->remote_seqnumber
)) {
177 ret
= KRB5KRB_AP_ERR_BADORDER
;
178 krb5_clear_error_string (context
);
181 auth_context
->remote_seqnumber
++;
184 ret
= verify_checksum (context
, auth_context
, &safe
);
188 outbuf
->length
= safe
.safe_body
.user_data
.length
;
189 outbuf
->data
= malloc(outbuf
->length
);
190 if (outbuf
->data
== NULL
&& outbuf
->length
!= 0) {
192 krb5_set_error_string (context
, "malloc: out of memory");
193 krb5_data_zero(outbuf
);
196 memcpy (outbuf
->data
, safe
.safe_body
.user_data
.data
, outbuf
->length
);
198 if ((auth_context
->flags
&
199 (KRB5_AUTH_CONTEXT_RET_TIME
| KRB5_AUTH_CONTEXT_RET_SEQUENCE
))) {
200 /* if these fields are not present in the safe-part, silently
202 memset(outdata
, 0, sizeof(*outdata
));
203 if(safe
.safe_body
.timestamp
)
204 outdata
->timestamp
= *safe
.safe_body
.timestamp
;
205 if(safe
.safe_body
.usec
)
206 outdata
->usec
= *safe
.safe_body
.usec
;
207 if(safe
.safe_body
.seq_number
)
208 outdata
->seq
= *safe
.safe_body
.seq_number
;
212 free_KRB_SAFE (&safe
);