5 #include <stddef.h> /* NULL */
6 #include <stdlib.h> /* malloc */
7 #include <errno.h> /* ENOMEM */
9 /*-------------------- decrypt_credencdata --------------------*/
12 * decrypt the enc_part of a krb5_cred
14 static krb5_error_code
15 decrypt_credencdata(context, pcred, pkeyblock, pcredenc)
18 krb5_keyblock * pkeyblock;
19 krb5_cred_enc_part * pcredenc;
21 krb5_cred_enc_part * ppart;
22 krb5_encrypt_block eblock;
23 krb5_error_code retval;
26 if (!valid_enctype(pcred->enc_part.enctype))
27 return KRB5_PROG_ETYPE_NOSUPP;
29 /* put together an eblock for this decryption */
30 krb5_use_enctype(context, &eblock, pcred->enc_part.enctype);
31 scratch.length = pcred->enc_part.ciphertext.length;
33 if (!(scratch.data = (char *)malloc(scratch.length)))
36 /* do any necessary key pre-processing */
37 if ((retval = krb5_process_key(context, &eblock, pkeyblock)))
40 /* call the decryption routine */
41 if ((retval = krb5_decrypt(context,
42 (krb5_pointer) pcred->enc_part.ciphertext.data,
43 (krb5_pointer) scratch.data,
44 scratch.length, &eblock, 0))) {
45 (void)krb5_finish_key(context, &eblock);
49 if ((retval = krb5_finish_key(context, &eblock)))
52 /* now decode the decrypted stuff */
53 if ((retval = decode_krb5_enc_cred_part(&scratch, &ppart)))
60 memset(ppart, 0, sizeof(*ppart));
64 memset(scratch.data, 0, scratch.length);
65 krb5_xfree(scratch.data);
69 /*----------------------- krb5_rd_cred_basic -----------------------*/
71 static krb5_error_code
72 krb5_rd_cred_basic(context, pcreddata, pkeyblock, local_addr, remote_addr,
75 krb5_data * pcreddata;
76 krb5_keyblock * pkeyblock;
77 krb5_address * local_addr;
78 krb5_address * remote_addr;
79 krb5_replay_data * replaydata;
80 krb5_creds *** pppcreds;
82 krb5_error_code retval;
86 krb5_cred_enc_part encpart;
88 /* decode cred message */
89 if ((retval = decode_krb5_cred(pcreddata, &pcred)))
92 if ((retval = decrypt_credencdata(context, pcred, pkeyblock, &encpart)))
95 if (!krb5_address_compare(context, remote_addr, encpart.s_address)) {
96 retval = KRB5KRB_AP_ERR_BADADDR;
100 if (encpart.r_address) {
102 if (!krb5_address_compare(context, local_addr, encpart.r_address)) {
103 retval = KRB5KRB_AP_ERR_BADADDR;
107 krb5_address **our_addrs;
109 if ((retval = krb5_os_localaddr(context, &our_addrs))) {
112 if (!krb5_address_search(context, encpart.r_address, our_addrs)) {
113 krb5_free_addresses(context, our_addrs);
114 retval = KRB5KRB_AP_ERR_BADADDR;
117 krb5_free_addresses(context, our_addrs);
121 replaydata->timestamp = encpart.timestamp;
122 replaydata->usec = encpart.usec;
123 replaydata->seq = encpart.nonce;
126 * Allocate the list of creds. The memory is allocated so that
127 * krb5_free_tgt_creds can be used to free the list.
129 for (ncreds = 0; pcred->tickets[ncreds]; ncreds++);
132 (krb5_creds **)malloc((size_t)(sizeof(krb5_creds *) * ncreds + 1))) == NULL) {
138 * For each credential, create a strcture in the list of
139 * credentials and copy the information.
142 krb5_cred_info * pinfo;
146 if ((pcur = (krb5_creds *)malloc(sizeof(krb5_creds))) == NULL) {
151 (*pppcreds)[i] = pcur;
152 pinfo = encpart.ticket_info[i++];
153 memset(pcur, 0, sizeof(krb5_creds));
155 if ((retval = krb5_copy_principal(context, pinfo->client,
159 if ((retval = krb5_copy_principal(context, pinfo->server,
163 if ((retval = krb5_copy_keyblock_contents(context, pinfo->session,
167 if ((retval = krb5_copy_addresses(context, pinfo->caddrs,
171 if ((retval = encode_krb5_ticket(pcred->tickets[i - 1], &pdata)))
174 pcur->ticket = *pdata;
178 pcur->is_skey = FALSE;
179 pcur->magic = KV5M_CREDS;
180 pcur->times = pinfo->times;
181 pcur->ticket_flags = pinfo->flags;
182 pcur->authdata = NULL; /* not used */
183 memset(&pcur->second_ticket, 0, sizeof(pcur->second_ticket));
187 * NULL terminate the list
189 (*pppcreds)[i] = NULL;
194 free((*pppcreds)[i--]);
197 krb5_free_cred(context, pcred);
202 /*----------------------- krb5_rd_cred -----------------------*/
204 #define in_clock_skew(date) (labs((date)-currenttime) < context->clockskew)
207 * This functions takes as input an KRB_CRED message, validates it, and
208 * outputs the nonce and an array of the forwarded credentials.
211 krb5_rd_cred(context, auth_context, pcreddata, pppcreds, outdata)
212 krb5_context context;
213 krb5_auth_context auth_context;
214 krb5_data * pcreddata;
215 krb5_creds *** pppcreds;
216 krb5_replay_data * outdata;
218 krb5_error_code retval;
219 krb5_keyblock * keyblock;
220 krb5_replay_data replaydata;
223 if ((keyblock = auth_context->local_subkey) == NULL)
224 if ((keyblock = auth_context->remote_subkey) == NULL)
225 keyblock = auth_context->keyblock;
227 if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
228 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
230 /* Need a better error */
231 return KRB5_RC_REQUIRED;
233 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
234 (auth_context->rcache == NULL))
235 return KRB5_RC_REQUIRED;
238 krb5_address * premote_fulladdr = NULL;
239 krb5_address * plocal_fulladdr = NULL;
240 krb5_address remote_fulladdr;
241 krb5_address local_fulladdr;
244 if (auth_context->local_addr) {
245 if (auth_context->local_port) {
246 if (!(retval = krb5_make_fulladdr(context,auth_context->local_addr,
247 auth_context->local_port,
249 CLEANUP_PUSH(local_fulladdr.contents, free);
250 plocal_fulladdr = &local_fulladdr;
255 plocal_fulladdr = auth_context->local_addr;
259 if (auth_context->remote_addr) {
260 if (auth_context->remote_port) {
261 if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
262 auth_context->remote_port,
264 CLEANUP_PUSH(remote_fulladdr.contents, free);
265 premote_fulladdr = &remote_fulladdr;
270 premote_fulladdr = auth_context->remote_addr;
274 if ((retval = krb5_rd_cred_basic(context, pcreddata, keyblock,
275 plocal_fulladdr, premote_fulladdr,
276 &replaydata, pppcreds))) {
285 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
286 krb5_donot_replay replay;
287 krb5_timestamp currenttime;
289 if ((retval = krb5_timeofday(context, ¤ttime)))
292 if (!in_clock_skew(replaydata.timestamp)) {
293 retval = KRB5KRB_AP_ERR_SKEW;
297 if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
298 "_forw", &replay.client)))
301 replay.server = ""; /* XXX */
302 replay.cusec = replaydata.usec;
303 replay.ctime = replaydata.timestamp;
304 if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
305 krb5_xfree(replay.client);
308 krb5_xfree(replay.client);
311 if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
312 if (auth_context->remote_seq_number != replaydata.seq) {
313 retval = KRB5KRB_AP_ERR_BADORDER;
316 auth_context->remote_seq_number++;
319 if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
320 (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
321 outdata->timestamp = replaydata.timestamp;
322 outdata->usec = replaydata.usec;
323 outdata->seq = replaydata.seq;
328 krb5_xfree(*pppcreds);