2 * lib/krb5/krb/rd_priv.c
4 * Copyright 1990,1991 by the Massachusetts Institute of Technology.
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.
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. M.I.T. makes no representations about the suitability of
20 * this software for any purpose. It is provided "as is" without express
21 * or implied warranty.
30 extern krb5_deltat krb5_clockskew;
31 #define in_clock_skew(date) (labs((date)-currenttime) < krb5_clockskew)
35 Parses a KRB_PRIV message from inbuf, placing the confidential user
38 key specifies the key to be used for decryption of the message.
40 remote_addr and local_addr specify the full
41 addresses (host and port) of the sender and receiver.
43 outbuf points to allocated storage which the caller should
46 i_vector is used as an initialization vector for the
47 encryption, and if non-NULL its contents are replaced with the last
48 block of the encrypted data upon exit.
50 Returns system errors, integrity errors.
54 static krb5_error_code
55 krb5_rd_priv_basic(context, inbuf, keyblock, local_addr, remote_addr,
56 i_vector, replaydata, outbuf)
58 const krb5_data * inbuf;
59 const krb5_keyblock * keyblock;
60 const krb5_address * local_addr;
61 const krb5_address * remote_addr;
62 krb5_pointer i_vector;
63 krb5_replay_data * replaydata;
66 krb5_error_code retval;
69 krb5_encrypt_block eblock;
70 krb5_priv_enc_part * privmsg_enc_part;
72 if (!krb5_is_krb_priv(inbuf))
73 return KRB5KRB_AP_ERR_MSG_TYPE;
75 /* decode private message */
76 if (retval = decode_krb5_priv(inbuf, &privmsg))
79 if (!valid_etype(privmsg->enc_part.etype)) {
80 retval = KRB5_PROG_ETYPE_NOSUPP;
84 /* put together an eblock for this decryption */
85 krb5_use_cstype(context, &eblock, privmsg->enc_part.etype);
86 scratch.length = privmsg->enc_part.ciphertext.length;
88 if (!(scratch.data = malloc(scratch.length))) {
93 /* do any necessary key pre-processing */
94 if (retval = krb5_process_key(context, &eblock, keyblock))
97 /* call the decryption routine */
98 if (retval = krb5_decrypt(context,
99 (krb5_pointer) privmsg->enc_part.ciphertext.data,
100 (krb5_pointer) scratch.data,
101 scratch.length, &eblock, i_vector)) {
102 krb5_finish_key(context, &eblock);
103 goto cleanup_scratch;
106 /* if i_vector is set, put last block into the i_vector */
109 privmsg->enc_part.ciphertext.data +
110 (privmsg->enc_part.ciphertext.length -
111 eblock.crypto_entry->block_length),
112 eblock.crypto_entry->block_length);
114 if (retval = krb5_finish_key(context, &eblock))
115 goto cleanup_scratch;
117 /* now decode the decrypted stuff */
118 if (retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part))
119 goto cleanup_scratch;
121 if (!krb5_address_compare(context,remote_addr,privmsg_enc_part->s_address)){
122 retval = KRB5KRB_AP_ERR_BADADDR;
126 if (privmsg_enc_part->r_address) {
128 if (!krb5_address_compare(context, local_addr,
129 privmsg_enc_part->r_address)) {
130 retval = KRB5KRB_AP_ERR_BADADDR;
134 krb5_address **our_addrs;
136 if (retval = krb5_os_localaddr(&our_addrs)) {
139 if (!krb5_address_search(context, privmsg_enc_part->r_address, our_addrs)) {
140 krb5_free_addresses(context, our_addrs);
141 retval = KRB5KRB_AP_ERR_BADADDR;
144 krb5_free_addresses(context, our_addrs);
148 replaydata->timestamp = privmsg_enc_part->timestamp;
149 replaydata->usec = privmsg_enc_part->usec;
150 replaydata->seq = privmsg_enc_part->seq_number;
152 /* everything is ok - return data to the user */
153 *outbuf = privmsg_enc_part->user_data;
158 memset(privmsg_enc_part->user_data.data, 0,
159 privmsg_enc_part->user_data.length);
160 krb5_xfree(privmsg_enc_part->user_data.data);
162 krb5_xfree(privmsg_enc_part);
165 memset(scratch.data, 0, scratch.length);
166 krb5_xfree(scratch.data);
169 krb5_xfree(privmsg->enc_part.ciphertext.data);
176 krb5_rd_priv(context, auth_context, inbuf, outbuf, outdata)
177 krb5_context context;
178 krb5_auth_context * auth_context;
179 const krb5_data * inbuf;
181 krb5_replay_data * outdata;
183 krb5_error_code retval;
184 krb5_replay_data replaydata;
186 if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
187 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
189 /* Need a better error */
190 return KRB5_RC_REQUIRED;
192 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
193 (auth_context->rcache == NULL))
194 return KRB5_RC_REQUIRED;
196 if (retval = krb5_rd_priv_basic(context, inbuf, auth_context->keyblock,
197 auth_context->local_addr, auth_context->remote_addr,
198 auth_context->i_vector, &replaydata, outbuf))
201 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
202 krb5_donot_replay replay;
203 krb5_timestamp currenttime;
205 if (retval = krb5_timeofday(context, ¤ttime))
208 if (!in_clock_skew(replaydata.timestamp)) {
209 retval = KRB5KRB_AP_ERR_SKEW;
213 if (retval = krb5_gen_replay_name(context, auth_context->remote_addr,
214 "_priv", &replay.client))
217 replay.server = ""; /* XXX */
218 replay.cusec = replaydata.usec;
219 replay.ctime = replaydata.timestamp;
220 if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) {
221 krb5_xfree(replay.client);
224 krb5_xfree(replay.client);
227 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
228 if (auth_context->remote_seq_number != replaydata.seq) {
229 retval = KRB5KRB_AP_ERR_BADORDER;
232 auth_context->remote_seq_number++;
235 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
236 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
237 outdata->timestamp = replaydata.timestamp;
238 outdata->usec = replaydata.usec;
239 outdata->seq = replaydata.seq;
242 /* everything is ok - return data to the user */
246 krb5_xfree(outbuf->data);