17c478bd9Sstevel@tonic-gate /* 2*5e01956fSGlenn Barry * Copyright (c) 1999, 2010, Oracle and/or its affiliates. All rights reserved. 37c478bd9Sstevel@tonic-gate */ 47c478bd9Sstevel@tonic-gate /* 57c478bd9Sstevel@tonic-gate * lib/krb5/krb/rd_priv.c 67c478bd9Sstevel@tonic-gate * 77c478bd9Sstevel@tonic-gate * Copyright 1990,1991 by the Massachusetts Institute of Technology. 87c478bd9Sstevel@tonic-gate * All Rights Reserved. 97c478bd9Sstevel@tonic-gate * 107c478bd9Sstevel@tonic-gate * Export of this software from the United States of America may 117c478bd9Sstevel@tonic-gate * require a specific license from the United States Government. 127c478bd9Sstevel@tonic-gate * It is the responsibility of any person or organization contemplating 137c478bd9Sstevel@tonic-gate * export to obtain such a license before exporting. 147c478bd9Sstevel@tonic-gate * 157c478bd9Sstevel@tonic-gate * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and 167c478bd9Sstevel@tonic-gate * distribute this software and its documentation for any purpose and 177c478bd9Sstevel@tonic-gate * without fee is hereby granted, provided that the above copyright 187c478bd9Sstevel@tonic-gate * notice appear in all copies and that both that copyright notice and 197c478bd9Sstevel@tonic-gate * this permission notice appear in supporting documentation, and that 207c478bd9Sstevel@tonic-gate * the name of M.I.T. not be used in advertising or publicity pertaining 217c478bd9Sstevel@tonic-gate * to distribution of the software without specific, written prior 227c478bd9Sstevel@tonic-gate * permission. Furthermore if you modify this software you must label 237c478bd9Sstevel@tonic-gate * your software as modified software and not distribute it in such a 247c478bd9Sstevel@tonic-gate * fashion that it might be confused with the original M.I.T. software. 257c478bd9Sstevel@tonic-gate * M.I.T. makes no representations about the suitability of 267c478bd9Sstevel@tonic-gate * this software for any purpose. It is provided "as is" without express 277c478bd9Sstevel@tonic-gate * or implied warranty. 287c478bd9Sstevel@tonic-gate * 297c478bd9Sstevel@tonic-gate * 307c478bd9Sstevel@tonic-gate * krb5_rd_priv() 317c478bd9Sstevel@tonic-gate */ 327c478bd9Sstevel@tonic-gate 33159d09a2SMark Phalan #include "k5-int.h" 347c478bd9Sstevel@tonic-gate #include "cleanup.h" 35159d09a2SMark Phalan #include "auth_con.h" 367c478bd9Sstevel@tonic-gate 377c478bd9Sstevel@tonic-gate 387c478bd9Sstevel@tonic-gate /* 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate Parses a KRB_PRIV message from inbuf, placing the confidential user 417c478bd9Sstevel@tonic-gate data in *outbuf. 427c478bd9Sstevel@tonic-gate 437c478bd9Sstevel@tonic-gate key specifies the key to be used for decryption of the message. 447c478bd9Sstevel@tonic-gate 457c478bd9Sstevel@tonic-gate remote_addr and local_addr specify the full 467c478bd9Sstevel@tonic-gate addresses (host and port) of the sender and receiver. 477c478bd9Sstevel@tonic-gate 487c478bd9Sstevel@tonic-gate outbuf points to allocated storage which the caller should 497c478bd9Sstevel@tonic-gate free when finished. 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate i_vector is used as an initialization vector for the 527c478bd9Sstevel@tonic-gate encryption, and if non-NULL its contents are replaced with the last 537c478bd9Sstevel@tonic-gate block of the encrypted data upon exit. 547c478bd9Sstevel@tonic-gate 557c478bd9Sstevel@tonic-gate Returns system errors, integrity errors. 567c478bd9Sstevel@tonic-gate 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate 597c478bd9Sstevel@tonic-gate static krb5_error_code 60159d09a2SMark Phalan krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf, const krb5_keyblock *keyblock, const krb5_address *local_addr, const krb5_address *remote_addr, krb5_pointer i_vector, krb5_replay_data *replaydata, krb5_data *outbuf) 617c478bd9Sstevel@tonic-gate { 627c478bd9Sstevel@tonic-gate krb5_error_code retval; 637c478bd9Sstevel@tonic-gate krb5_priv * privmsg; 647c478bd9Sstevel@tonic-gate krb5_data scratch; 657c478bd9Sstevel@tonic-gate krb5_priv_enc_part * privmsg_enc_part; 667c478bd9Sstevel@tonic-gate size_t blocksize; 677c478bd9Sstevel@tonic-gate krb5_data ivdata; 687c478bd9Sstevel@tonic-gate 697c478bd9Sstevel@tonic-gate if (!krb5_is_krb_priv(inbuf)) 707c478bd9Sstevel@tonic-gate return KRB5KRB_AP_ERR_MSG_TYPE; 717c478bd9Sstevel@tonic-gate 727c478bd9Sstevel@tonic-gate /* decode private message */ 737c478bd9Sstevel@tonic-gate if ((retval = decode_krb5_priv(inbuf, &privmsg))) 747c478bd9Sstevel@tonic-gate return retval; 757c478bd9Sstevel@tonic-gate 767c478bd9Sstevel@tonic-gate if (i_vector) { 777c478bd9Sstevel@tonic-gate if ((retval = krb5_c_block_size(context, keyblock->enctype, 787c478bd9Sstevel@tonic-gate &blocksize))) 797c478bd9Sstevel@tonic-gate goto cleanup_privmsg; 807c478bd9Sstevel@tonic-gate 817c478bd9Sstevel@tonic-gate ivdata.length = blocksize; 827c478bd9Sstevel@tonic-gate ivdata.data = i_vector; 837c478bd9Sstevel@tonic-gate } 847c478bd9Sstevel@tonic-gate 857c478bd9Sstevel@tonic-gate scratch.length = privmsg->enc_part.ciphertext.length; 867c478bd9Sstevel@tonic-gate if (!(scratch.data = malloc(scratch.length))) { 877c478bd9Sstevel@tonic-gate retval = ENOMEM; 887c478bd9Sstevel@tonic-gate goto cleanup_privmsg; 897c478bd9Sstevel@tonic-gate } 907c478bd9Sstevel@tonic-gate 917c478bd9Sstevel@tonic-gate if ((retval = krb5_c_decrypt(context, keyblock, 927c478bd9Sstevel@tonic-gate KRB5_KEYUSAGE_KRB_PRIV_ENCPART, 937c478bd9Sstevel@tonic-gate i_vector?&ivdata:0, 947c478bd9Sstevel@tonic-gate &privmsg->enc_part, &scratch))) 957c478bd9Sstevel@tonic-gate goto cleanup_scratch; 967c478bd9Sstevel@tonic-gate 977c478bd9Sstevel@tonic-gate /* now decode the decrypted stuff */ 987c478bd9Sstevel@tonic-gate if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part))) 997c478bd9Sstevel@tonic-gate goto cleanup_scratch; 1007c478bd9Sstevel@tonic-gate 1017c478bd9Sstevel@tonic-gate if (!krb5_address_compare(context,remote_addr,privmsg_enc_part->s_address)){ 1027c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_BADADDR; 1037c478bd9Sstevel@tonic-gate goto cleanup_data; 1047c478bd9Sstevel@tonic-gate } 1057c478bd9Sstevel@tonic-gate 1067c478bd9Sstevel@tonic-gate if (privmsg_enc_part->r_address) { 1077c478bd9Sstevel@tonic-gate if (local_addr) { 1087c478bd9Sstevel@tonic-gate if (!krb5_address_compare(context, local_addr, 1097c478bd9Sstevel@tonic-gate privmsg_enc_part->r_address)) { 1107c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_BADADDR; 1117c478bd9Sstevel@tonic-gate goto cleanup_data; 1127c478bd9Sstevel@tonic-gate } 1137c478bd9Sstevel@tonic-gate } else { 1147c478bd9Sstevel@tonic-gate krb5_address **our_addrs; 1157c478bd9Sstevel@tonic-gate 1167c478bd9Sstevel@tonic-gate if ((retval = krb5_os_localaddr(context, &our_addrs))) { 1177c478bd9Sstevel@tonic-gate goto cleanup_data; 1187c478bd9Sstevel@tonic-gate } 1197c478bd9Sstevel@tonic-gate if (!krb5_address_search(context, privmsg_enc_part->r_address, 1207c478bd9Sstevel@tonic-gate our_addrs)) { 1217c478bd9Sstevel@tonic-gate krb5_free_addresses(context, our_addrs); 1227c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_BADADDR; 1237c478bd9Sstevel@tonic-gate goto cleanup_data; 1247c478bd9Sstevel@tonic-gate } 1257c478bd9Sstevel@tonic-gate krb5_free_addresses(context, our_addrs); 1267c478bd9Sstevel@tonic-gate } 1277c478bd9Sstevel@tonic-gate } 1287c478bd9Sstevel@tonic-gate 1297c478bd9Sstevel@tonic-gate replaydata->timestamp = privmsg_enc_part->timestamp; 1307c478bd9Sstevel@tonic-gate replaydata->usec = privmsg_enc_part->usec; 1317c478bd9Sstevel@tonic-gate replaydata->seq = privmsg_enc_part->seq_number; 1327c478bd9Sstevel@tonic-gate 1337c478bd9Sstevel@tonic-gate /* everything is ok - return data to the user */ 1347c478bd9Sstevel@tonic-gate *outbuf = privmsg_enc_part->user_data; 1357c478bd9Sstevel@tonic-gate retval = 0; 1367c478bd9Sstevel@tonic-gate 1377c478bd9Sstevel@tonic-gate cleanup_data:; 1387c478bd9Sstevel@tonic-gate if (retval == 0) 1397c478bd9Sstevel@tonic-gate privmsg_enc_part->user_data.data = 0; 1407c478bd9Sstevel@tonic-gate krb5_free_priv_enc_part(context, privmsg_enc_part); 1417c478bd9Sstevel@tonic-gate 1427c478bd9Sstevel@tonic-gate cleanup_scratch:; 143159d09a2SMark Phalan /* Solaris Kerberos */ 1447c478bd9Sstevel@tonic-gate (void) memset(scratch.data, 0, scratch.length); 1457c478bd9Sstevel@tonic-gate krb5_xfree(scratch.data); 1467c478bd9Sstevel@tonic-gate 1477c478bd9Sstevel@tonic-gate cleanup_privmsg:; 1487c478bd9Sstevel@tonic-gate krb5_xfree(privmsg->enc_part.ciphertext.data); 1497c478bd9Sstevel@tonic-gate krb5_xfree(privmsg); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate return retval; 1527c478bd9Sstevel@tonic-gate } 1537c478bd9Sstevel@tonic-gate 1547c478bd9Sstevel@tonic-gate krb5_error_code KRB5_CALLCONV 155159d09a2SMark Phalan krb5_rd_priv(krb5_context context, krb5_auth_context auth_context, const krb5_data *inbuf, krb5_data *outbuf, krb5_replay_data *outdata) 1567c478bd9Sstevel@tonic-gate { 1577c478bd9Sstevel@tonic-gate krb5_error_code retval; 1587c478bd9Sstevel@tonic-gate krb5_keyblock * keyblock; 1597c478bd9Sstevel@tonic-gate krb5_replay_data replaydata; 1607c478bd9Sstevel@tonic-gate 1617c478bd9Sstevel@tonic-gate /* Get keyblock */ 1627c478bd9Sstevel@tonic-gate if ((keyblock = auth_context->recv_subkey) == NULL) 1637c478bd9Sstevel@tonic-gate keyblock = auth_context->keyblock; 1647c478bd9Sstevel@tonic-gate 1657c478bd9Sstevel@tonic-gate if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || 1667c478bd9Sstevel@tonic-gate (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && 1677c478bd9Sstevel@tonic-gate (outdata == NULL)) 1687c478bd9Sstevel@tonic-gate /* Need a better error */ 1697c478bd9Sstevel@tonic-gate return KRB5_RC_REQUIRED; 1707c478bd9Sstevel@tonic-gate 1717c478bd9Sstevel@tonic-gate if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) && 1727c478bd9Sstevel@tonic-gate (auth_context->rcache == NULL)) 1737c478bd9Sstevel@tonic-gate return KRB5_RC_REQUIRED; 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate { 1767c478bd9Sstevel@tonic-gate krb5_address * premote_fulladdr = NULL; 1777c478bd9Sstevel@tonic-gate krb5_address * plocal_fulladdr = NULL; 1787c478bd9Sstevel@tonic-gate krb5_address remote_fulladdr; 1797c478bd9Sstevel@tonic-gate krb5_address local_fulladdr; 1807c478bd9Sstevel@tonic-gate CLEANUP_INIT(2); 1817c478bd9Sstevel@tonic-gate 1827c478bd9Sstevel@tonic-gate if (auth_context->local_addr) { 1837c478bd9Sstevel@tonic-gate if (auth_context->local_port) { 1847c478bd9Sstevel@tonic-gate if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr, 1857c478bd9Sstevel@tonic-gate auth_context->local_port, 1867c478bd9Sstevel@tonic-gate &local_fulladdr))){ 1877c478bd9Sstevel@tonic-gate CLEANUP_PUSH(local_fulladdr.contents, free); 1887c478bd9Sstevel@tonic-gate plocal_fulladdr = &local_fulladdr; 1897c478bd9Sstevel@tonic-gate } else { 1907c478bd9Sstevel@tonic-gate return retval; 1917c478bd9Sstevel@tonic-gate } 1927c478bd9Sstevel@tonic-gate } else { 1937c478bd9Sstevel@tonic-gate plocal_fulladdr = auth_context->local_addr; 1947c478bd9Sstevel@tonic-gate } 1957c478bd9Sstevel@tonic-gate } 1967c478bd9Sstevel@tonic-gate 1977c478bd9Sstevel@tonic-gate if (auth_context->remote_addr) { 1987c478bd9Sstevel@tonic-gate if (auth_context->remote_port) { 1997c478bd9Sstevel@tonic-gate if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr, 2007c478bd9Sstevel@tonic-gate auth_context->remote_port, 2017c478bd9Sstevel@tonic-gate &remote_fulladdr))){ 2027c478bd9Sstevel@tonic-gate CLEANUP_PUSH(remote_fulladdr.contents, free); 2037c478bd9Sstevel@tonic-gate premote_fulladdr = &remote_fulladdr; 2047c478bd9Sstevel@tonic-gate } else { 2057c478bd9Sstevel@tonic-gate CLEANUP_DONE(); 2067c478bd9Sstevel@tonic-gate return retval; 2077c478bd9Sstevel@tonic-gate } 2087c478bd9Sstevel@tonic-gate } else { 2097c478bd9Sstevel@tonic-gate premote_fulladdr = auth_context->remote_addr; 2107c478bd9Sstevel@tonic-gate } 2117c478bd9Sstevel@tonic-gate } 2127c478bd9Sstevel@tonic-gate 2137c478bd9Sstevel@tonic-gate if ((retval = krb5_rd_priv_basic(context, inbuf, keyblock, 2147c478bd9Sstevel@tonic-gate plocal_fulladdr, 2157c478bd9Sstevel@tonic-gate premote_fulladdr, 2167c478bd9Sstevel@tonic-gate auth_context->i_vector, 2177c478bd9Sstevel@tonic-gate &replaydata, outbuf))) { 2187c478bd9Sstevel@tonic-gate CLEANUP_DONE(); 2197c478bd9Sstevel@tonic-gate return retval; 2207c478bd9Sstevel@tonic-gate } 2217c478bd9Sstevel@tonic-gate 2227c478bd9Sstevel@tonic-gate CLEANUP_DONE(); 2237c478bd9Sstevel@tonic-gate } 2247c478bd9Sstevel@tonic-gate 2257c478bd9Sstevel@tonic-gate if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) { 2267c478bd9Sstevel@tonic-gate krb5_donot_replay replay; 2277c478bd9Sstevel@tonic-gate 228*5e01956fSGlenn Barry if ((retval = krb5int_check_clockskew(context, replaydata.timestamp))) 2297c478bd9Sstevel@tonic-gate goto error; 2307c478bd9Sstevel@tonic-gate 2317c478bd9Sstevel@tonic-gate if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr, 2327c478bd9Sstevel@tonic-gate "_priv", &replay.client))) 2337c478bd9Sstevel@tonic-gate goto error; 2347c478bd9Sstevel@tonic-gate 2357c478bd9Sstevel@tonic-gate replay.server = ""; /* XXX */ 2367c478bd9Sstevel@tonic-gate replay.cusec = replaydata.usec; 2377c478bd9Sstevel@tonic-gate replay.ctime = replaydata.timestamp; 238159d09a2SMark Phalan if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) { 2397c478bd9Sstevel@tonic-gate krb5_xfree(replay.client); 2407c478bd9Sstevel@tonic-gate goto error; 2417c478bd9Sstevel@tonic-gate } 2427c478bd9Sstevel@tonic-gate krb5_xfree(replay.client); 2437c478bd9Sstevel@tonic-gate } 2447c478bd9Sstevel@tonic-gate 2457c478bd9Sstevel@tonic-gate if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) { 246505d05c7Sgtb if (!krb5int_auth_con_chkseqnum(context, auth_context, 247505d05c7Sgtb replaydata.seq)) { 2487c478bd9Sstevel@tonic-gate retval = KRB5KRB_AP_ERR_BADORDER; 2497c478bd9Sstevel@tonic-gate goto error; 2507c478bd9Sstevel@tonic-gate } 2517c478bd9Sstevel@tonic-gate auth_context->remote_seq_number++; 2527c478bd9Sstevel@tonic-gate } 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) || 2557c478bd9Sstevel@tonic-gate (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) { 2567c478bd9Sstevel@tonic-gate outdata->timestamp = replaydata.timestamp; 2577c478bd9Sstevel@tonic-gate outdata->usec = replaydata.usec; 2587c478bd9Sstevel@tonic-gate outdata->seq = replaydata.seq; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate /* everything is ok - return data to the user */ 2627c478bd9Sstevel@tonic-gate return 0; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate error:; 2657c478bd9Sstevel@tonic-gate krb5_xfree(outbuf->data); 2667c478bd9Sstevel@tonic-gate return retval; 2677c478bd9Sstevel@tonic-gate 2687c478bd9Sstevel@tonic-gate } 269159d09a2SMark Phalan 270