2 * lib/krb5/krb/mk_safe.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.
31 Formats a KRB_SAFE message into outbuf.
33 userdata is formatted as the user data in the message.
34 sumtype specifies the encryption type; key specifies the key which
35 might be used to seed the checksum; sender_addr and recv_addr specify
36 the full addresses (host and port) of the sender and receiver.
37 The host portion of sender_addr is used to form the addresses used in the
40 The outbuf buffer storage is allocated, and should be freed by the
45 static krb5_error_code
46 krb5_mk_safe_basic(context, userdata, keyblock, replaydata, local_addr,
47 remote_addr, sumtype, outbuf)
49 const krb5_data * userdata;
50 const krb5_keyblock * keyblock;
51 krb5_replay_data * replaydata;
52 const krb5_address * local_addr;
53 const krb5_address * remote_addr;
54 const krb5_cksumtype sumtype;
57 krb5_error_code retval;
59 krb5_octet zero_octet = 0;
60 krb5_checksum safe_checksum;
61 krb5_data *scratch1, *scratch2;
63 if (!valid_cksumtype(sumtype))
64 return KRB5_PROG_SUMTYPE_NOSUPP;
65 if (!is_coll_proof_cksum(sumtype) || !is_keyed_cksum(sumtype))
66 return KRB5KRB_AP_ERR_INAPP_CKSUM;
68 safemsg.user_data = *userdata;
69 safemsg.s_address = (krb5_address *) local_addr;
70 safemsg.r_address = (krb5_address *) remote_addr;
72 /* We should check too make sure one exists. */
73 safemsg.timestamp = replaydata->timestamp;
74 safemsg.usec = replaydata->usec;
75 safemsg.seq_number = replaydata->seq;
78 * To do the checksum stuff, we need to encode the message with a
79 * zero-length zero-type checksum, then checksum the encoding, then
80 * re-encode with the checksum.
83 safe_checksum.length = 0;
84 safe_checksum.checksum_type = 0;
85 safe_checksum.contents = &zero_octet;
87 safemsg.checksum = &safe_checksum;
89 if (retval = encode_krb5_safe(&safemsg, &scratch1))
92 if (!(safe_checksum.contents =
93 (krb5_octet *) malloc(krb5_checksum_size(context, sumtype)))) {
97 if (retval = krb5_calculate_checksum(context, sumtype, scratch1->data,
99 (krb5_pointer) keyblock->contents,
100 keyblock->length, &safe_checksum)) {
101 goto cleanup_checksum;
103 safemsg.checksum = &safe_checksum;
104 if (retval = encode_krb5_safe(&safemsg, &scratch2)) {
105 goto cleanup_checksum;
108 krb5_xfree(scratch2);
112 krb5_xfree(safe_checksum.contents);
115 memset((char *)scratch1->data, 0, scratch1->length);
116 krb5_free_data(context, scratch1);
121 krb5_mk_safe(context, auth_context, userdata, outbuf, outdata)
122 krb5_context context;
123 krb5_auth_context * auth_context;
124 const krb5_data * userdata;
126 krb5_replay_data * outdata;
128 krb5_replay_data replaydata;
129 krb5_error_code retval;
131 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
132 (auth_context->rcache == NULL))
133 return KRB5_RC_REQUIRED;
135 if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
136 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
138 /* Need a better error */
139 return KRB5_RC_REQUIRED;
141 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
142 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
143 if (retval = krb5_us_timeofday(context, &replaydata.timestamp,
146 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
147 outdata->timestamp = replaydata.timestamp;
148 outdata->usec = replaydata.usec;
151 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
152 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
153 replaydata.seq = auth_context->local_seq_number++;
154 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE) {
155 outdata->seq = replaydata.seq;
159 if (retval = krb5_mk_safe_basic(context, userdata, auth_context->keyblock,
160 &replaydata, auth_context->local_addr, auth_context->remote_addr,
161 auth_context->cksumtype, outbuf))
164 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
165 krb5_donot_replay replay;
167 if (retval = krb5_gen_replay_name(context, auth_context->local_addr,
168 "_safe", &replay.client)) {
173 replay.server = ""; /* XXX */
174 replay.cusec = replaydata.usec;
175 replay.ctime = replaydata.timestamp;
176 if (retval = krb5_rc_store(context, auth_context->rcache, &replay)) {
177 /* should we really error out here? XXX */
181 krb5_xfree(replay.client);
187 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
188 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
189 auth_context->local_seq_number--;