k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac,
krb5_ui_4 in_seq);
+krb5_error_code
+k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac,
+ krb5_address *msg_s_addr, krb5_address *msg_r_addr);
+
#endif /* KRB5_INT_FUNC_PROTO__ */
}
return 0;
}
+
+/*
+ * Verify the sender and receiver addresses from a KRB-SAFE or KRB-PRIV message
+ * against the auth context. msg_r_addr may be NULL, but msg_s_addr must not
+ * be. The auth context's remote addr must be set.
+ */
+krb5_error_code
+k5_privsafe_check_addrs(krb5_context context, krb5_auth_context ac,
+ krb5_address *msg_s_addr, krb5_address *msg_r_addr)
+{
+ krb5_error_code ret = 0;
+ krb5_address **our_addrs = NULL;
+ const krb5_address *local_addr, *remote_addr;
+ krb5_address local_fulladdr, remote_fulladdr;
+
+ local_fulladdr.contents = remote_fulladdr.contents = NULL;
+
+ /* Determine the remote comparison address. */
+ if (ac->remote_port != NULL) {
+ ret = krb5_make_fulladdr(context, ac->remote_addr, ac->remote_port,
+ &remote_fulladdr);
+ if (ret)
+ goto cleanup;
+ remote_addr = &remote_fulladdr;
+ } else
+ remote_addr = ac->remote_addr;
+
+ /* Determine the local comparison address (possibly NULL). */
+ if (ac->local_addr != NULL) {
+ if (ac->local_port != NULL) {
+ ret = krb5_make_fulladdr(context, ac->local_addr, ac->local_port,
+ &local_fulladdr);
+ if (ret)
+ goto cleanup;
+ local_addr = &local_fulladdr;
+ } else
+ local_addr = ac->local_addr;
+ } else
+ local_addr = NULL;
+
+ /* Check the remote address against the message's sender address. */
+ if (!krb5_address_compare(context, remote_addr, msg_s_addr)) {
+ ret = KRB5KRB_AP_ERR_BADADDR;
+ goto cleanup;
+ }
+
+ /* Receiver address is optional; only check it if supplied. */
+ if (msg_r_addr == NULL)
+ goto cleanup;
+
+ /* Check the message's receiver address against the local address, or
+ * against all local addresses if no specific local address is set. */
+ if (local_addr != NULL) {
+ if (!krb5_address_compare(context, local_addr, msg_r_addr)) {
+ ret = KRB5KRB_AP_ERR_BADADDR;
+ goto cleanup;
+ }
+ } else {
+ ret = krb5_os_localaddr(context, &our_addrs);
+ if (ret)
+ goto cleanup;
+
+ if (!krb5_address_search(context, msg_r_addr, our_addrs)) {
+ ret = KRB5KRB_AP_ERR_BADADDR;
+ goto cleanup;
+ }
+ }
+
+cleanup:
+ free(local_fulladdr.contents);
+ free(remote_fulladdr.contents);
+ krb5_free_addresses(context, our_addrs);
+ return ret;
+}
#include "k5-int.h"
#include "int-proto.h"
-#include "cleanup.h"
#include "auth_con.h"
/*
key specifies the key to be used for decryption of the message.
- remote_addr and local_addr specify the full
- addresses (host and port) of the sender and receiver.
-
outbuf points to allocated storage which the caller should
free when finished.
- i_vector is used as an initialization vector for the
- encryption, and if non-NULL its contents are replaced with the last
- block of the encrypted data upon exit.
-
Returns system errors, integrity errors.
*/
static krb5_error_code
-krb5_rd_priv_basic(krb5_context context, const krb5_data *inbuf,
- const krb5_key key, const krb5_address *local_addr,
- const krb5_address *remote_addr, krb5_pointer i_vector,
- krb5_replay_data *replaydata, krb5_data *outbuf)
+rd_priv_basic(krb5_context context, krb5_auth_context ac,
+ const krb5_data *inbuf, const krb5_key key,
+ krb5_replay_data *replaydata, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_priv * privmsg;
krb5_data scratch;
krb5_priv_enc_part * privmsg_enc_part;
size_t blocksize;
- krb5_data ivdata;
+ krb5_data ivdata, *iv = NULL;
krb5_enctype enctype;
if (!krb5_is_krb_priv(inbuf))
if ((retval = decode_krb5_priv(inbuf, &privmsg)))
return retval;
- if (i_vector) {
+ if (ac->i_vector != NULL) {
enctype = krb5_k_key_enctype(context, key);
if ((retval = krb5_c_block_size(context, enctype, &blocksize)))
goto cleanup_privmsg;
-
- ivdata.length = blocksize;
- ivdata.data = i_vector;
+ ivdata = make_data(ac->i_vector, blocksize);
+ iv = &ivdata;
}
scratch.length = privmsg->enc_part.ciphertext.length;
}
if ((retval = krb5_k_decrypt(context, key,
- KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
- i_vector?&ivdata:0,
+ KRB5_KEYUSAGE_KRB_PRIV_ENCPART, iv,
&privmsg->enc_part, &scratch)))
goto cleanup_scratch;
if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)))
goto cleanup_scratch;
- if (!krb5_address_compare(context,remote_addr,privmsg_enc_part->s_address)){
- retval = KRB5KRB_AP_ERR_BADADDR;
+ retval = k5_privsafe_check_addrs(context, ac, privmsg_enc_part->s_address,
+ privmsg_enc_part->r_address);
+ if (retval)
goto cleanup_data;
- }
-
- if (privmsg_enc_part->r_address) {
- if (local_addr) {
- if (!krb5_address_compare(context, local_addr,
- privmsg_enc_part->r_address)) {
- retval = KRB5KRB_AP_ERR_BADADDR;
- goto cleanup_data;
- }
- } else {
- krb5_address **our_addrs;
-
- if ((retval = krb5_os_localaddr(context, &our_addrs))) {
- goto cleanup_data;
- }
- if (!krb5_address_search(context, privmsg_enc_part->r_address,
- our_addrs)) {
- krb5_free_addresses(context, our_addrs);
- retval = KRB5KRB_AP_ERR_BADADDR;
- goto cleanup_data;
- }
- krb5_free_addresses(context, our_addrs);
- }
- }
replaydata->timestamp = privmsg_enc_part->timestamp;
replaydata->usec = privmsg_enc_part->usec;
(auth_context->rcache == NULL))
return KRB5_RC_REQUIRED;
- {
- krb5_address * premote_fulladdr;
- krb5_address * plocal_fulladdr = NULL;
- krb5_address remote_fulladdr;
- krb5_address local_fulladdr;
- CLEANUP_INIT(2);
-
- if (auth_context->local_addr) {
- if (auth_context->local_port) {
- if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
- &local_fulladdr))){
- CLEANUP_PUSH(local_fulladdr.contents, free);
- plocal_fulladdr = &local_fulladdr;
- } else {
- return retval;
- }
- } else {
- plocal_fulladdr = auth_context->local_addr;
- }
- }
-
- if (auth_context->remote_port) {
- if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
- &remote_fulladdr))){
- CLEANUP_PUSH(remote_fulladdr.contents, free);
- premote_fulladdr = &remote_fulladdr;
- } else {
- CLEANUP_DONE();
- return retval;
- }
- } else {
- premote_fulladdr = auth_context->remote_addr;
- }
-
- memset(&replaydata, 0, sizeof(replaydata));
- if ((retval = krb5_rd_priv_basic(context, inbuf, key,
- plocal_fulladdr,
- premote_fulladdr,
- auth_context->i_vector,
- &replaydata, outbuf))) {
- CLEANUP_DONE();
- return retval;
- }
-
- CLEANUP_DONE();
- }
+ memset(&replaydata, 0, sizeof(replaydata));
+ retval = rd_priv_basic(context, auth_context, inbuf, key, &replaydata,
+ outbuf);
+ if (retval)
+ return retval;
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_donot_replay replay;
key specifies the key to be used for decryption of the message.
- sender_addr and recv_addr specify the full addresses (host and port) of
- the sender and receiver.
-
outbuf points to allocated storage which the caller should free when finished.
returns system errors, integrity errors
*/
static krb5_error_code
-rd_safe_basic(krb5_context context, const krb5_data *inbuf,
- krb5_key key,
- const krb5_address *recv_addr,
- const krb5_address *sender_addr,
- krb5_replay_data *replaydata, krb5_data *outbuf)
+rd_safe_basic(krb5_context context, krb5_auth_context ac,
+ const krb5_data *inbuf, krb5_key key,
+ krb5_replay_data *replaydata, krb5_data *outbuf)
{
krb5_error_code retval;
krb5_safe * message;
goto cleanup;
}
- if (!krb5_address_compare(context, sender_addr, message->s_address)) {
- retval = KRB5KRB_AP_ERR_BADADDR;
+ retval = k5_privsafe_check_addrs(context, ac, message->s_address,
+ message->r_address);
+ if (retval)
goto cleanup;
- }
-
- if (message->r_address) {
- if (recv_addr) {
- if (!krb5_address_compare(context, recv_addr, message->r_address)) {
- retval = KRB5KRB_AP_ERR_BADADDR;
- goto cleanup;
- }
- } else {
- krb5_address **our_addrs;
-
- if ((retval = krb5_os_localaddr(context, &our_addrs)))
- goto cleanup;
-
- if (!krb5_address_search(context, message->r_address, our_addrs)) {
- krb5_free_addresses(context, our_addrs);
- retval = KRB5KRB_AP_ERR_BADADDR;
- goto cleanup;
- }
- krb5_free_addresses(context, our_addrs);
- }
- }
/* verify the checksum */
/*
if ((key = auth_context->recv_subkey) == NULL)
key = auth_context->key;
- {
- krb5_address * premote_fulladdr;
- krb5_address * plocal_fulladdr = NULL;
- krb5_address remote_fulladdr;
- krb5_address local_fulladdr;
- CLEANUP_INIT(2);
-
- if (auth_context->local_addr) {
- if (auth_context->local_port) {
- if (!(retval = krb5_make_fulladdr(context, auth_context->local_addr,
- auth_context->local_port,
- &local_fulladdr))){
- CLEANUP_PUSH(local_fulladdr.contents, free);
- plocal_fulladdr = &local_fulladdr;
- } else {
- return retval;
- }
- } else {
- plocal_fulladdr = auth_context->local_addr;
- }
- }
-
- if (auth_context->remote_port) {
- if (!(retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
- &remote_fulladdr))){
- CLEANUP_PUSH(remote_fulladdr.contents, free);
- premote_fulladdr = &remote_fulladdr;
- } else {
- return retval;
- }
- } else {
- premote_fulladdr = auth_context->remote_addr;
- }
-
- memset(&replaydata, 0, sizeof(replaydata));
- if ((retval = rd_safe_basic(context, inbuf, key,
- plocal_fulladdr, premote_fulladdr,
- &replaydata, outbuf))) {
- CLEANUP_DONE();
- return retval;
- }
-
- CLEANUP_DONE();
- }
-
+ memset(&replaydata, 0, sizeof(replaydata));
+ retval = rd_safe_basic(context, auth_context, inbuf, key, &replaydata,
+ outbuf);
+ if (retval)
+ return retval;
if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
krb5_donot_replay replay;