1 /* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
2 /* lib/krb5/krb/rd_priv.c */
4 * Copyright 1990,1991,2007 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. 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.
28 #include "int-proto.h"
33 Parses a KRB_PRIV message from inbuf, placing the confidential user
36 key specifies the key to be used for decryption of the message.
38 outbuf points to allocated storage which the caller should
41 Returns system errors, integrity errors.
45 static krb5_error_code
46 rd_priv_basic(krb5_context context, krb5_auth_context ac,
47 const krb5_data *inbuf, const krb5_key key,
48 krb5_replay_data *replaydata, krb5_data *outbuf)
50 krb5_error_code retval;
53 krb5_priv_enc_part * privmsg_enc_part;
55 krb5_data ivdata, *iv = NULL;
58 if (!krb5_is_krb_priv(inbuf))
59 return KRB5KRB_AP_ERR_MSG_TYPE;
61 /* decode private message */
62 if ((retval = decode_krb5_priv(inbuf, &privmsg)))
65 if (ac->i_vector != NULL) {
66 enctype = krb5_k_key_enctype(context, key);
67 if ((retval = krb5_c_block_size(context, enctype, &blocksize)))
69 ivdata = make_data(ac->i_vector, blocksize);
73 scratch.length = privmsg->enc_part.ciphertext.length;
74 if (!(scratch.data = malloc(scratch.length))) {
79 if ((retval = krb5_k_decrypt(context, key,
80 KRB5_KEYUSAGE_KRB_PRIV_ENCPART, iv,
81 &privmsg->enc_part, &scratch)))
84 /* now decode the decrypted stuff */
85 if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)))
88 retval = k5_privsafe_check_addrs(context, ac, privmsg_enc_part->s_address,
89 privmsg_enc_part->r_address);
93 replaydata->timestamp = privmsg_enc_part->timestamp;
94 replaydata->usec = privmsg_enc_part->usec;
95 replaydata->seq = privmsg_enc_part->seq_number;
97 /* everything is ok - return data to the user */
98 *outbuf = privmsg_enc_part->user_data;
103 privmsg_enc_part->user_data.data = 0;
104 krb5_free_priv_enc_part(context, privmsg_enc_part);
107 memset(scratch.data, 0, scratch.length);
111 free(privmsg->enc_part.ciphertext.data);
117 krb5_error_code KRB5_CALLCONV
118 krb5_rd_priv(krb5_context context, krb5_auth_context auth_context,
119 const krb5_data *inbuf, krb5_data *outbuf,
120 krb5_replay_data *outdata)
122 krb5_error_code retval;
124 krb5_replay_data replaydata;
127 if ((key = auth_context->recv_subkey) == NULL)
128 key = auth_context->key;
130 if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
131 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
133 /* Need a better error */
134 return KRB5_RC_REQUIRED;
136 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
137 (auth_context->remote_addr == NULL))
138 return KRB5_REMOTE_ADDR_REQUIRED;
140 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
141 (auth_context->rcache == NULL))
142 return KRB5_RC_REQUIRED;
144 memset(&replaydata, 0, sizeof(replaydata));
145 retval = rd_priv_basic(context, auth_context, inbuf, key, &replaydata,
150 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
151 krb5_donot_replay replay;
153 if ((retval = krb5_check_clockskew(context, replaydata.timestamp)))
156 if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
157 "_priv", &replay.client)))
160 replay.server = ""; /* XXX */
161 replay.msghash = NULL;
162 replay.cusec = replaydata.usec;
163 replay.ctime = replaydata.timestamp;
164 if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
171 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
172 if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) {
173 retval = KRB5KRB_AP_ERR_BADORDER;
176 auth_context->remote_seq_number++;
179 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
180 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
181 outdata->timestamp = replaydata.timestamp;
182 outdata->usec = replaydata.usec;
183 outdata->seq = replaydata.seq;
186 /* everything is ok - return data to the user */