1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/rd_rep.c */
3 /*
4 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
5 * All Rights Reserved.
6 *
7 * Export of this software from the United States of America may
8 * require a specific license from the United States Government.
9 * It is the responsibility of any person or organization contemplating
10 * export to obtain such a license before exporting.
11 *
12 * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
13 * distribute this software and its documentation for any purpose and
14 * without fee is hereby granted, provided that the above copyright
15 * notice appear in all copies and that both that copyright notice and
16 * this permission notice appear in supporting documentation, and that
17 * the name of M.I.T. not be used in advertising or publicity pertaining
18 * to distribution of the software without specific, written prior
19 * permission. Furthermore if you modify this software you must label
20 * your software as modified software and not distribute it in such a
21 * fashion that it might be confused with the original M.I.T. software.
22 * M.I.T. makes no representations about the suitability of
23 * this software for any purpose. It is provided "as is" without express
24 * or implied warranty.
25 */
26 /*
27 * Copyright (c) 2006-2008, Novell, Inc.
28 * All rights reserved.
29 *
30 * Redistribution and use in source and binary forms, with or without
31 * modification, are permitted provided that the following conditions are met:
32 *
33 * * Redistributions of source code must retain the above copyright notice,
34 * this list of conditions and the following disclaimer.
35 * * Redistributions in binary form must reproduce the above copyright
36 * notice, this list of conditions and the following disclaimer in the
37 * documentation and/or other materials provided with the distribution.
38 * * The copyright holder's name is not used to endorse or promote products
39 * derived from this software without specific prior written permission.
40 *
41 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
42 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
45 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
46 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
47 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
48 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
49 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
50 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
51 * POSSIBILITY OF SUCH DAMAGE.
52 */
53
54 #include "k5-int.h"
55 #include "auth_con.h"
56
57 /*
58 * Parses a KRB_AP_REP message, returning its contents.
59 *
60 * repl is filled in with with a pointer to allocated memory containing
61 * the fields from the encrypted response.
62 *
63 * the key in kblock is used to decrypt the message.
64 *
65 * returns system errors, encryption errors, replay errors
66 */
67
68 krb5_error_code KRB5_CALLCONV
krb5_rd_rep(krb5_context context,krb5_auth_context auth_context,const krb5_data * inbuf,krb5_ap_rep_enc_part ** repl)69 krb5_rd_rep(krb5_context context, krb5_auth_context auth_context,
70 const krb5_data *inbuf, krb5_ap_rep_enc_part **repl)
71 {
72 krb5_error_code retval;
73 krb5_ap_rep *reply = NULL;
74 krb5_ap_rep_enc_part *enc = NULL;
75 krb5_data scratch;
76
77 *repl = NULL;
78
79 if (!krb5_is_ap_rep(inbuf))
80 return KRB5KRB_AP_ERR_MSG_TYPE;
81
82 /* Decode inbuf. */
83 retval = decode_krb5_ap_rep(inbuf, &reply);
84 if (retval)
85 return retval;
86
87 /* Put together an eblock for this encryption. */
88 scratch.length = reply->enc_part.ciphertext.length;
89 scratch.data = malloc(scratch.length);
90 if (scratch.data == NULL) {
91 retval = ENOMEM;
92 goto clean_scratch;
93 }
94
95 retval = krb5_k_decrypt(context, auth_context->key,
96 KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
97 &reply->enc_part, &scratch);
98 if (retval)
99 goto clean_scratch;
100
101 /* Now decode the decrypted stuff. */
102 retval = decode_krb5_ap_rep_enc_part(&scratch, &enc);
103 if (retval)
104 goto clean_scratch;
105
106 /* Check reply fields. */
107 if ((enc->ctime != auth_context->authentp->ctime)
108 || (enc->cusec != auth_context->authentp->cusec)) {
109 retval = KRB5_MUTUAL_FAILED;
110 goto clean_scratch;
111 }
112
113 /* Set auth subkey. */
114 if (enc->subkey) {
115 retval = krb5_auth_con_setrecvsubkey(context, auth_context,
116 enc->subkey);
117 if (retval)
118 goto clean_scratch;
119 retval = krb5_auth_con_setsendsubkey(context, auth_context,
120 enc->subkey);
121 if (retval) {
122 (void) krb5_auth_con_setrecvsubkey(context, auth_context, NULL);
123 goto clean_scratch;
124 }
125 /* Not used for anything yet. */
126 auth_context->negotiated_etype = enc->subkey->enctype;
127 }
128
129 /* Get remote sequence number. */
130 auth_context->remote_seq_number = enc->seq_number;
131
132 TRACE_RD_REP(context, enc->ctime, enc->cusec, enc->subkey,
133 enc->seq_number);
134
135 *repl = enc;
136 enc = NULL;
137
138 clean_scratch:
139 if (scratch.data)
140 memset(scratch.data, 0, scratch.length);
141 free(scratch.data);
142 krb5_free_ap_rep(context, reply);
143 krb5_free_ap_rep_enc_part(context, enc);
144 return retval;
145 }
146
147 krb5_error_code KRB5_CALLCONV
krb5_rd_rep_dce(krb5_context context,krb5_auth_context auth_context,const krb5_data * inbuf,krb5_ui_4 * nonce)148 krb5_rd_rep_dce(krb5_context context, krb5_auth_context auth_context,
149 const krb5_data *inbuf, krb5_ui_4 *nonce)
150 {
151 krb5_error_code retval;
152 krb5_ap_rep * reply;
153 krb5_data scratch;
154 krb5_ap_rep_enc_part *repl = NULL;
155
156 if (!krb5_is_ap_rep(inbuf))
157 return KRB5KRB_AP_ERR_MSG_TYPE;
158
159 /* decode it */
160
161 if ((retval = decode_krb5_ap_rep(inbuf, &reply)))
162 return retval;
163
164 /* put together an eblock for this encryption */
165
166 scratch.length = reply->enc_part.ciphertext.length;
167 if (!(scratch.data = malloc(scratch.length))) {
168 krb5_free_ap_rep(context, reply);
169 return(ENOMEM);
170 }
171
172 if ((retval = krb5_k_decrypt(context, auth_context->key,
173 KRB5_KEYUSAGE_AP_REP_ENCPART, 0,
174 &reply->enc_part, &scratch)))
175 goto clean_scratch;
176
177 /* now decode the decrypted stuff */
178 retval = decode_krb5_ap_rep_enc_part(&scratch, &repl);
179 if (retval)
180 goto clean_scratch;
181
182 *nonce = repl->seq_number;
183 if (*nonce != auth_context->local_seq_number) {
184 retval = KRB5_MUTUAL_FAILED;
185 goto clean_scratch;
186 }
187
188 /* Must be NULL to prevent echoing for client AP-REP */
189 if (repl->subkey != NULL) {
190 retval = KRB5_MUTUAL_FAILED;
191 goto clean_scratch;
192 }
193
194 TRACE_RD_REP_DCE(context, repl->ctime, repl->cusec, repl->seq_number);
195
196 clean_scratch:
197 memset(scratch.data, 0, scratch.length);
198
199 if (repl != NULL)
200 krb5_free_ap_rep_enc_part(context, repl);
201 krb5_free_ap_rep(context, reply);
202 free(scratch.data);
203 return retval;
204 }
205