krb5 commit: Modernize KRB-PRIV/KRB-SAFE/KRB-CRED functions
Greg Hudson
ghudson at mit.edu
Mon Feb 25 00:16:38 EST 2019
https://github.com/krb5/krb5/commit/44b601ec43f34a6ed5bf9a737328d2ee4c438f12
commit 44b601ec43f34a6ed5bf9a737328d2ee4c438f12
Author: Greg Hudson <ghudson at mit.edu>
Date: Fri Feb 15 11:59:06 2019 -0500
Modernize KRB-PRIV/KRB-SAFE/KRB-CRED functions
In krb5_mk_safe(), krb5_mk_priv(), krb5_mk_ncred(), krb5_rd_safe(),
and krb5_rd_priv(), modify naming, formatting, and memory management
to meet current standards. Add k5_privsafe helpers to generate replay
data and addresses and to store replay records. For krb5_mk_ncred(),
expand the contract of the encoding function to be similar to the
other two krb5_mk functions, and use pointer aliases to reduce the
number of copies required.
src/include/krb5/krb5.hin | 128 +++++++------
src/lib/krb5/krb/cleanup.h | 30 ---
src/lib/krb5/krb/deps | 27 ++--
src/lib/krb5/krb/int-proto.h | 24 +++
src/lib/krb5/krb/mk_cred.c | 433 +++++++++++++++++-------------------------
src/lib/krb5/krb/mk_priv.c | 330 +++++++++++++-------------------
src/lib/krb5/krb/mk_safe.c | 314 +++++++++++-------------------
src/lib/krb5/krb/privsafe.c | 148 +++++++++++++--
src/lib/krb5/krb/rd_cred.c | 75 ++++----
src/lib/krb5/krb/rd_priv.c | 266 +++++++++++---------------
src/lib/krb5/krb/rd_safe.c | 270 ++++++++++++---------------
11 files changed, 913 insertions(+), 1132 deletions(-)
diff --git a/src/include/krb5/krb5.hin b/src/include/krb5/krb5.hin
index 15b7677..a67eec1 100644
--- a/src/include/krb5/krb5.hin
+++ b/src/include/krb5/krb5.hin
@@ -3310,20 +3310,20 @@ krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf,
* @param [in] context Library context
* @param [in] auth_context Authentication context
* @param [in] inbuf @c KRB-SAFE message to be parsed
- * @param [out] outbuf Data parsed from @c KRB-SAFE message
- * @param [out] outdata Replay data. Specify NULL if not needed
+ * @param [out] userdata_out Data parsed from @c KRB-SAFE message
+ * @param [out] rdata_out Replay data. Specify NULL if not needed
*
* This function parses a @c KRB-SAFE message, verifies its integrity, and
- * stores its data into @a outbuf.
+ * stores its data into @a userdata_out.
*
- * @note The @a outdata argument is required if #KRB5_AUTH_CONTEXT_RET_TIME or
- * #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in the @a auth_context.
+ * @note The @a rdata_out argument is required if #KRB5_AUTH_CONTEXT_RET_TIME
+ * or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in the @a auth_context.
*
* @note @a auth_context must have a remote address set. This address will be
- * used to verify the sender address in the KRB-SAFE message. If @a
- * auth_context has a local address set, it will be used to verify the
- * receiver address in the KRB-SAFE message if the message contains one.
- * Both addresses must use type @c ADDRTYPE_ADDRPORT.
+ * used to verify the sender address in the KRB-SAFE message. If @a
+ * auth_context has a local address set, it will be used to verify the receiver
+ * address in the KRB-SAFE message if the message contains one. Both addresses
+ * must use type @c ADDRTYPE_ADDRPORT.
*
* If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in @a auth_context, the
* sequence number of the KRB-SAFE message is checked against the remote
@@ -3336,14 +3336,15 @@ krb5_rd_error(krb5_context context, const krb5_data *enc_errbuf,
* (which is usually five minutes).
* @li The message must not be a replayed message field in @a auth_context.
*
- * Use krb5_free_data_contents() to free @a outbuf when it is no longer needed.
+ * Use krb5_free_data_contents() to free @a userdata_out when it is no longer
+ * needed.
*
* @retval 0 Success; otherwise - Kerberos error codes
*/
krb5_error_code KRB5_CALLCONV
krb5_rd_safe(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *inbuf, krb5_data *outbuf,
- krb5_replay_data *outdata);
+ const krb5_data *inbuf, krb5_data *userdata_out,
+ krb5_replay_data *rdata_out);
/**
* Process a @c KRB-PRIV message.
@@ -3351,21 +3352,20 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context,
* @param [in] context Library context
* @param [in] auth_context Authentication structure
* @param [in] inbuf @c KRB-PRIV message to be parsed
- * @param [out] outbuf Data parsed from @c KRB-PRIV message
- * @param [out] outdata Replay data. Specify NULL if not needed
+ * @param [out] userdata_out Data parsed from @c KRB-PRIV message
+ * @param [out] rdata_out Replay data. Specify NULL if not needed
*
* This function parses a @c KRB-PRIV message, verifies its integrity, and
- * stores its unencrypted data into @a outbuf.
+ * stores its unencrypted data into @a userdata_out.
*
- * @note If the #KRB5_AUTH_CONTEXT_RET_TIME or
- * #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in @a auth_context, @a
- * outdata is required.
+ * @note If the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE
+ * flag is set in @a auth_context, @a rdata_out is required.
*
* @note @a auth_context must have a remote address set. This address will be
- * used to verify the sender address in the KRB-PRIV message. If @a
- * auth_context has a local address set, it will be used to verify the
- * receiver address in the KRB-PRIV message if the message contains one.
- * Both addresses must use type @c ADDRTYPE_ADDRPORT.
+ * used to verify the sender address in the KRB-PRIV message. If @a
+ * auth_context has a local address set, it will be used to verify the receiver
+ * address in the KRB-PRIV message if the message contains one. Both addresses
+ * must use type @c ADDRTYPE_ADDRPORT.
*
* If the #KRB5_AUTH_CONTEXT_DO_SEQUENCE flag is set in @a auth_context, the
* sequence number of the KRB-SAFE message is checked against the remote
@@ -3378,12 +3378,15 @@ krb5_rd_safe(krb5_context context, krb5_auth_context auth_context,
* (which is usually five minutes).
* @li The message must not be a replayed message field in @a auth_context.
*
+ * Use krb5_free_data_contents() to free @a userdata_out when it is no longer
+ * needed.
+ *
* @retval 0 Success; otherwise - Kerberos error codes
*/
krb5_error_code KRB5_CALLCONV
krb5_rd_priv(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *inbuf, krb5_data *outbuf,
- krb5_replay_data *outdata);
+ const krb5_data *inbuf, krb5_data *userdata_out,
+ krb5_replay_data *rdata_out);
/**
* Convert a string principal name to a krb5_principal structure.
@@ -5245,8 +5248,8 @@ krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg,
* @param [in] context Library context
* @param [in] auth_context Authentication context
* @param [in] userdata User data in the message
- * @param [out] outbuf Formatted @c KRB-SAFE buffer
- * @param [out] outdata Replay data. Specify NULL if not needed
+ * @param [out] der_out Formatted @c KRB-SAFE buffer
+ * @param [out] rdata_out Replay data. Specify NULL if not needed
*
* This function creates an integrity protected @c KRB-SAFE message
* using data supplied by the application.
@@ -5268,19 +5271,20 @@ krb5_kt_read_service_key(krb5_context context, krb5_pointer keyprocarg,
*
* If either #KRB5_AUTH_CONTEXT_DO_SEQUENCE or
* #KRB5_AUTH_CONTEXT_RET_SEQUENCE is set, the @a auth_context local sequence
- * number will be placed in @a outdata as its sequence number.
+ * number will be placed in @a rdata_out as its sequence number.
*
- * @note The @a outdata argument is required if #KRB5_AUTH_CONTEXT_RET_TIME or
- * #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in the @a auth_context.
+ * @note The @a rdata_out argument is required if #KRB5_AUTH_CONTEXT_RET_TIME
+ * or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in the @a auth_context.
*
- * Use krb5_free_data_contents() to free @a outbuf when it is no longer needed.
+ * Use krb5_free_data_contents() to free @a der_out when it is no longer
+ * needed.
*
* @retval 0 Success; otherwise - Kerberos error codes
*/
krb5_error_code KRB5_CALLCONV
krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *userdata, krb5_data *outbuf,
- krb5_replay_data *outdata);
+ const krb5_data *userdata, krb5_data *der_out,
+ krb5_replay_data *rdata_out);
/**
* Format a @c KRB-PRIV message.
@@ -5288,8 +5292,8 @@ krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
* @param [in] context Library context
* @param [in] auth_context Authentication context
* @param [in] userdata User data for @c KRB-PRIV message
- * @param [out] outbuf Formatted @c KRB-PRIV message
- * @param [out] outdata Replay cache handle (NULL if not needed)
+ * @param [out] der_out Formatted @c KRB-PRIV message
+ * @param [out] rdata_out Replay cache handle (NULL if not needed)
*
* This function is similar to krb5_mk_safe(), but the message is encrypted and
* integrity-protected, not just integrity-protected.
@@ -5301,7 +5305,7 @@ krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
*
* @note If the #KRB5_AUTH_CONTEXT_RET_TIME or
* #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in @a auth_context, the @a
- * outdata is required.
+ * rdata_out is required.
*
* @note The flags from @a auth_context specify whether sequence numbers or
* timestamps will be used to identify the message. Valid values are:
@@ -5312,14 +5316,14 @@ krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
* @a auth_context in replay cache.
* @li #KRB5_AUTH_CONTEXT_RET_SEQUENCE - Use local sequence numbers from
* @a auth_context as a sequence number
- * in the encrypted message @a outbuf.
+ * in the encrypted message @a der_out.
*
* @retval 0 Success; otherwise - Kerberos error codes
*/
krb5_error_code KRB5_CALLCONV
krb5_mk_priv(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *userdata, krb5_data *outbuf,
- krb5_replay_data *outdata);
+ const krb5_data *userdata, krb5_data *der_out,
+ krb5_replay_data *rdata_out);
/**
* Client function for @c sendauth protocol.
@@ -5437,15 +5441,15 @@ krb5_recvauth_version(krb5_context context,
*
* @param [in] context Library context
* @param [in] auth_context Authentication context
- * @param [in] ppcreds Null-terminated array of credentials
- * @param [out] ppdata Encoded credentials
- * @param [out] outdata Replay cache information (NULL if not needed)
+ * @param [in] creds Null-terminated array of credentials
+ * @param [out] der_out Encoded credentials
+ * @param [out] rdata_out Replay cache information (NULL if not needed)
*
- * This function takes an array of credentials @a ppcreds and formats
- * a @c KRB-CRED message @a ppdata to pass to krb5_rd_cred().
+ * This function takes an array of credentials @a creds and formats
+ * a @c KRB-CRED message @a der_out to pass to krb5_rd_cred().
*
* @note If the #KRB5_AUTH_CONTEXT_RET_TIME or #KRB5_AUTH_CONTEXT_RET_SEQUENCE
- * flag is set in @a auth_context, @a outdata is required.
+ * flag is set in @a auth_context, @a rdata_out is required.
*
* The message will be encrypted using the send subkey of @a auth_context if it
* is present, or the session key otherwise.
@@ -5461,17 +5465,17 @@ krb5_recvauth_version(krb5_context context,
*/
krb5_error_code KRB5_CALLCONV
krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context,
- krb5_creds **ppcreds, krb5_data **ppdata,
- krb5_replay_data *outdata);
+ krb5_creds **creds, krb5_data **der_out,
+ krb5_replay_data *rdata_out);
/**
* Format a @c KRB-CRED message for a single set of credentials.
*
* @param [in] context Library context
* @param [in] auth_context Authentication context
- * @param [in] pcreds Pointer to credentials
- * @param [out] ppdata Encoded credentials
- * @param [out] outdata Replay cache data (NULL if not needed)
+ * @param [in] creds Pointer to credentials
+ * @param [out] der_out Encoded credentials
+ * @param [out] rdata_out Replay cache data (NULL if not needed)
*
* This is a convenience function that calls krb5_mk_ncred() with a single set
* of credentials.
@@ -5487,33 +5491,33 @@ krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context,
*/
krb5_error_code KRB5_CALLCONV
krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context,
- krb5_creds *pcreds, krb5_data **ppdata,
- krb5_replay_data *outdata);
+ krb5_creds *creds, krb5_data **der_out,
+ krb5_replay_data *rdata_out);
/**
* Read and validate a @c KRB-CRED message.
*
* @param [in] context Library context
* @param [in] auth_context Authentication context
- * @param [in] pcreddata @c KRB-CRED message
- * @param [out] pppcreds Null-terminated array of forwarded credentials
- * @param [out] outdata Replay data (NULL if not needed)
+ * @param [in] creddata @c KRB-CRED message
+ * @param [out] creds_out Null-terminated array of forwarded credentials
+ * @param [out] rdata_out Replay data (NULL if not needed)
*
- * @note The @a outdata argument is required if #KRB5_AUTH_CONTEXT_RET_TIME or
- * #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in the @a auth_context.`
+ * @note The @a rdata_out argument is required if #KRB5_AUTH_CONTEXT_RET_TIME
+ * or #KRB5_AUTH_CONTEXT_RET_SEQUENCE flag is set in the @a auth_context.`
*
- * @a pcreddata will be decrypted using the receiving subkey if it is present
- * in @a auth_context, or the session key if the receiving subkey is not
- * present or fails to decrypt the message.
+ * @a creddata will be decrypted using the receiving subkey if it is present in
+ * @a auth_context, or the session key if the receiving subkey is not present
+ * or fails to decrypt the message.
*
- * Use krb5_free_tgt_creds() to free @a pppcreds when it is no longer needed.
+ * Use krb5_free_tgt_creds() to free @a creds_out when it is no longer needed.
*
* @retval 0 Success; otherwise - Kerberos error codes
*/
krb5_error_code KRB5_CALLCONV
krb5_rd_cred(krb5_context context, krb5_auth_context auth_context,
- krb5_data *pcreddata, krb5_creds ***pppcreds,
- krb5_replay_data *outdata);
+ krb5_data *creddata, krb5_creds ***creds_out,
+ krb5_replay_data *rdata_out);
/**
* Get a forwarded TGT and format a @c KRB-CRED message.
diff --git a/src/lib/krb5/krb/cleanup.h b/src/lib/krb5/krb/cleanup.h
deleted file mode 100644
index 3a01833..0000000
--- a/src/lib/krb5/krb/cleanup.h
+++ /dev/null
@@ -1,30 +0,0 @@
-/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-
-#ifndef KRB5_CLEANUP
-#define KRB5_CLEANUP
-
-struct cleanup {
- void * arg;
- void (*func)(void *);
-};
-
-#define CLEANUP_INIT(x) \
- struct cleanup cleanup_data[x]; \
- int cleanup_count = 0;
-
-#define CLEANUP_PUSH(x, y) \
- cleanup_data[cleanup_count].arg = x; \
- cleanup_data[cleanup_count].func = y; \
- cleanup_count++;
-
-#define CLEANUP_POP(x) \
- if ((--cleanup_count) && x && (cleanup_data[cleanup_count].func)) \
- cleanup_data[cleanup_count].func(cleanup_data[cleanup_count].arg);
-
-#define CLEANUP_DONE() \
- while(cleanup_count--) \
- if (cleanup_data[cleanup_count].func) \
- cleanup_data[cleanup_count].func(cleanup_data[cleanup_count].arg);
-
-
-#endif
diff --git a/src/lib/krb5/krb/deps b/src/lib/krb5/krb/deps
index a4a809b..fc2a16e 100644
--- a/src/lib/krb5/krb/deps
+++ b/src/lib/krb5/krb/deps
@@ -460,12 +460,13 @@ gen_save_subkey.so gen_save_subkey.po $(OUTPRE)gen_save_subkey.$(OBJEXT): \
get_creds.so get_creds.po $(OUTPRE)get_creds.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
- $(COM_ERR_DEPS) $(top_srcdir)/include/k5-buf.h $(top_srcdir)/include/k5-err.h \
- $(top_srcdir)/include/k5-gmt_mktime.h $(top_srcdir)/include/k5-int-pkinit.h \
- $(top_srcdir)/include/k5-int.h $(top_srcdir)/include/k5-platform.h \
- $(top_srcdir)/include/k5-plugin.h $(top_srcdir)/include/k5-thread.h \
- $(top_srcdir)/include/k5-trace.h $(top_srcdir)/include/krb5.h \
- $(top_srcdir)/include/krb5/authdata_plugin.h $(top_srcdir)/include/krb5/plugin.h \
+ $(COM_ERR_DEPS) $(srcdir)/../os/os-proto.h $(top_srcdir)/include/k5-buf.h \
+ $(top_srcdir)/include/k5-err.h $(top_srcdir)/include/k5-gmt_mktime.h \
+ $(top_srcdir)/include/k5-int-pkinit.h $(top_srcdir)/include/k5-int.h \
+ $(top_srcdir)/include/k5-platform.h $(top_srcdir)/include/k5-plugin.h \
+ $(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
+ $(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
+ $(top_srcdir)/include/krb5/locate_plugin.h $(top_srcdir)/include/krb5/plugin.h \
$(top_srcdir)/include/port-sockets.h $(top_srcdir)/include/socket-utils.h \
fast.h get_creds.c int-proto.h
get_etype_info.so get_etype_info.po $(OUTPRE)get_etype_info.$(OBJEXT): \
@@ -627,8 +628,8 @@ mk_cred.so mk_cred.po $(OUTPRE)mk_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_con.h cleanup.h \
- int-proto.h mk_cred.c
+ $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \
+ mk_cred.c
mk_error.so mk_error.po $(OUTPRE)mk_error.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
@@ -649,7 +650,7 @@ mk_priv.so mk_priv.po $(OUTPRE)mk_priv.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_con.h cleanup.h \
+ $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \
mk_priv.c
mk_rep.so mk_rep.po $(OUTPRE)mk_rep.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
@@ -692,7 +693,7 @@ mk_safe.so mk_safe.po $(OUTPRE)mk_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_con.h cleanup.h \
+ $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \
mk_safe.c
pac.so pac.po $(OUTPRE)pac.$(OBJEXT): $(BUILDTOP)/include/autoconf.h \
$(BUILDTOP)/include/krb5/krb5.h $(BUILDTOP)/include/osconf.h \
@@ -875,7 +876,7 @@ rd_cred.so rd_cred.po $(OUTPRE)rd_cred.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_con.h cleanup.h \
+ $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \
rd_cred.c
rd_error.so rd_error.po $(OUTPRE)rd_error.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
@@ -940,8 +941,8 @@ rd_safe.so rd_safe.po $(OUTPRE)rd_safe.$(OBJEXT): $(BUILDTOP)/include/autoconf.h
$(top_srcdir)/include/k5-thread.h $(top_srcdir)/include/k5-trace.h \
$(top_srcdir)/include/krb5.h $(top_srcdir)/include/krb5/authdata_plugin.h \
$(top_srcdir)/include/krb5/plugin.h $(top_srcdir)/include/port-sockets.h \
- $(top_srcdir)/include/socket-utils.h auth_con.h cleanup.h \
- int-proto.h rd_safe.c
+ $(top_srcdir)/include/socket-utils.h auth_con.h int-proto.h \
+ rd_safe.c
recvauth.so recvauth.po $(OUTPRE)recvauth.$(OBJEXT): \
$(BUILDTOP)/include/autoconf.h $(BUILDTOP)/include/krb5/krb5.h \
$(BUILDTOP)/include/osconf.h $(BUILDTOP)/include/profile.h \
diff --git a/src/lib/krb5/krb/int-proto.h b/src/lib/krb5/krb/int-proto.h
index 9783548..4464a13 100644
--- a/src/lib/krb5/krb/int-proto.h
+++ b/src/lib/krb5/krb/int-proto.h
@@ -143,6 +143,30 @@ krb5int_validate_times(krb5_context, krb5_ticket_times *);
krb5_error_code
krb5int_copy_authdatum(krb5_context, const krb5_authdata *, krb5_authdata **);
+/* Set replay data fields in rdata and caller_rdata according to the flags in
+ * authcon. */
+krb5_error_code
+k5_privsafe_gen_rdata(krb5_context context, krb5_auth_context authcon,
+ krb5_replay_data *rdata, krb5_replay_data *caller_rdata);
+
+/*
+ * Set *local_out and *remote_out to addresses based on authcon. The resulting
+ * pointers should not be freed, but addresses may be placed into *lstorage and
+ * *rstorage which the caller must free, even on error.
+ */
+krb5_error_code
+k5_privsafe_gen_addrs(krb5_context context, krb5_auth_context authcon,
+ krb5_address *lstorage, krb5_address *rstorage,
+ krb5_address **local_out, krb5_address **remote_out);
+
+/* If the DO_TIME flag is set in authcon, store a replay record. If check_time
+ * is true, also check that the timestamp is within clock skew. */
+krb5_error_code
+k5_privsafe_check_replay(krb5_context context, krb5_auth_context authcon,
+ krb5_address *addr, const char *uniq,
+ const krb5_replay_data *rdata,
+ krb5_boolean check_time);
+
krb5_boolean
k5_privsafe_check_seqnum(krb5_context ctx, krb5_auth_context ac,
krb5_ui_4 in_seq);
diff --git a/src/lib/krb5/krb/mk_cred.c b/src/lib/krb5/krb/mk_cred.c
index 7616c3a..003a0fd 100644
--- a/src/lib/krb5/krb/mk_cred.c
+++ b/src/lib/krb5/krb/mk_cred.c
@@ -1,308 +1,225 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
+/* lib/krb5/krb/mk_cred.c - definition of krb5_mk_ncred(), krb5_mk_1cred() */
/*
- * NAME
- * cred.c
+ * Copyright (C) 2019 by the Massachusetts Institute of Technology.
+ * All rights reserved.
*
- * DESCRIPTION
- * Provide an interface to assemble and disassemble krb5_cred
- * structures.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
+
#include "k5-int.h"
#include "int-proto.h"
-#include "cleanup.h"
#include "auth_con.h"
-#include <stddef.h> /* NULL */
-#include <stdlib.h> /* malloc */
-#include <errno.h> /* ENOMEM */
-
-/*-------------------- encrypt_credencpart --------------------*/
-
-/*
- * encrypt the enc_part of krb5_cred
- */
+/* Encrypt the enc_part of krb5_cred. key may be NULL to use the unencrypted
+ * KRB-CRED form (RFC 6448). */
static krb5_error_code
-encrypt_credencpart(krb5_context context, krb5_cred_enc_part *pcredpart,
- krb5_key pkey, krb5_enc_data *pencdata)
+encrypt_credencpart(krb5_context context, krb5_cred_enc_part *encpart,
+ krb5_key key, krb5_enc_data *encdata_out)
{
- krb5_error_code retval;
- krb5_data * scratch;
-
- /* start by encoding to-be-encrypted part of the message */
- if ((retval = encode_krb5_enc_cred_part(pcredpart, &scratch)))
- return retval;
-
- /*
- * If the keyblock is NULL, just copy the data from the encoded
- * data to the ciphertext area.
- */
- if (pkey == NULL) {
- pencdata->ciphertext.data = scratch->data;
- pencdata->ciphertext.length = scratch->length;
- free(scratch);
+ krb5_error_code ret;
+ krb5_data *der_enccred;
+
+ /* Start by encoding to-be-encrypted part of the message. */
+ ret = encode_krb5_enc_cred_part(encpart, &der_enccred);
+ if (ret)
+ return ret;
+
+ if (key == NULL) {
+ /* Just copy the encoded data to the ciphertext area. */
+ encdata_out->enctype = ENCTYPE_NULL;
+ encdata_out->ciphertext = *der_enccred;
+ free(der_enccred);
return 0;
}
- /* call the encryption routine */
- retval = k5_encrypt_keyhelper(context, pkey,
- KRB5_KEYUSAGE_KRB_CRED_ENCPART, scratch,
- pencdata);
+ ret = k5_encrypt_keyhelper(context, key, KRB5_KEYUSAGE_KRB_CRED_ENCPART,
+ der_enccred, encdata_out);
- memset(scratch->data, 0, scratch->length);
- krb5_free_data(context, scratch);
-
- return retval;
+ zap(der_enccred->data, der_enccred->length);
+ krb5_free_data(context, der_enccred);
+ return ret;
}
-/*----------------------- krb5_mk_ncred_basic -----------------------*/
-
+/*
+ * Marshal a KRB-CRED message into der_out, encrypted with key (or unencrypted
+ * if key is NULL). Use the timestamp and sequence number from rdata and the
+ * addresses from local_addr and remote_addr (either of which may be NULL).
+ * der_out should be freed by the caller when finished.
+ */
static krb5_error_code
-krb5_mk_ncred_basic(krb5_context context,
- krb5_creds **ppcreds, krb5_int32 nppcreds,
- krb5_key key, krb5_replay_data *replaydata,
- krb5_address *local_addr, krb5_address *remote_addr,
- krb5_cred *pcred)
+create_krbcred(krb5_context context, krb5_creds **creds, krb5_key key,
+ const krb5_replay_data *rdata, krb5_address *local_addr,
+ krb5_address *remote_addr, krb5_data **der_out)
{
- krb5_cred_enc_part credenc;
- krb5_error_code retval;
- size_t size;
- int i;
-
- credenc.magic = KV5M_CRED_ENC_PART;
-
- credenc.s_address = 0;
- credenc.r_address = 0;
- if (local_addr) krb5_copy_addr(context, local_addr, &credenc.s_address);
- if (remote_addr) krb5_copy_addr(context, remote_addr, &credenc.r_address);
-
- credenc.nonce = replaydata->seq;
- credenc.usec = replaydata->usec;
- credenc.timestamp = replaydata->timestamp;
-
- /* Get memory for creds and initialize it */
- size = sizeof(krb5_cred_info *) * (nppcreds + 1);
- credenc.ticket_info = (krb5_cred_info **) calloc(1, size);
- if (credenc.ticket_info == NULL)
- return ENOMEM;
-
- /*
- * For each credential in the list, initialize a cred info
- * structure and copy the ticket into the ticket list.
- */
- for (i = 0; i < nppcreds; i++) {
- credenc.ticket_info[i] = calloc(1, sizeof(krb5_cred_info));
- if (credenc.ticket_info[i] == NULL) {
- retval = ENOMEM;
- goto cleanup;
- }
- credenc.ticket_info[i+1] = NULL;
-
- credenc.ticket_info[i]->magic = KV5M_CRED_INFO;
- credenc.ticket_info[i]->times = ppcreds[i]->times;
- credenc.ticket_info[i]->flags = ppcreds[i]->ticket_flags;
-
- if ((retval = decode_krb5_ticket(&ppcreds[i]->ticket,
- &pcred->tickets[i])))
- goto cleanup;
-
- if ((retval = krb5_copy_keyblock(context, &ppcreds[i]->keyblock,
- &credenc.ticket_info[i]->session)))
- goto cleanup;
-
- if ((retval = krb5_copy_principal(context, ppcreds[i]->client,
- &credenc.ticket_info[i]->client)))
- goto cleanup;
-
- if ((retval = krb5_copy_principal(context, ppcreds[i]->server,
- &credenc.ticket_info[i]->server)))
+ krb5_error_code ret;
+ krb5_cred_enc_part credenc;
+ krb5_cred cred;
+ krb5_ticket **tickets = NULL;
+ krb5_cred_info **ticket_info = NULL, *tinfos = NULL;
+ krb5_enc_data enc;
+ size_t i, ncreds;
+
+ *der_out = NULL;
+ memset(&enc, 0, sizeof(enc));
+
+ for (ncreds = 0; creds[ncreds] != NULL; ncreds++);
+
+ tickets = k5calloc(ncreds + 1, sizeof(*tickets), &ret);
+ if (tickets == NULL)
+ goto cleanup;
+
+ ticket_info = k5calloc(ncreds + 1, sizeof(*ticket_info), &ret);
+ if (ticket_info == NULL)
+ goto cleanup;
+
+ tinfos = k5calloc(ncreds, sizeof(*tinfos), &ret);
+ if (tinfos == NULL)
+ goto cleanup;
+
+ /* For each credential in the list, decode the ticket and create a cred
+ * info structure using alias pointers. */
+ for (i = 0; i < ncreds; i++) {
+ ret = decode_krb5_ticket(&creds[i]->ticket, &tickets[i]);
+ if (ret)
goto cleanup;
- if ((retval = krb5_copy_addresses(context, ppcreds[i]->addresses,
- &credenc.ticket_info[i]->caddrs)))
- goto cleanup;
+ tinfos[i].magic = KV5M_CRED_INFO;
+ tinfos[i].times = creds[i]->times;
+ tinfos[i].flags = creds[i]->ticket_flags;
+ tinfos[i].session = &creds[i]->keyblock;
+ tinfos[i].client = creds[i]->client;
+ tinfos[i].server = creds[i]->server;
+ tinfos[i].caddrs = creds[i]->addresses;
+ ticket_info[i] = &tinfos[i];
}
- /*
- * NULL terminate the lists.
- */
- pcred->tickets[i] = NULL;
-
- /* encrypt the credential encrypted part */
- retval = encrypt_credencpart(context, &credenc, key, &pcred->enc_part);
+ /* Encrypt the credential encrypted part. */
+ credenc.magic = KV5M_CRED_ENC_PART;
+ credenc.s_address = local_addr;
+ credenc.r_address = remote_addr;
+ credenc.nonce = rdata->seq;
+ credenc.usec = rdata->usec;
+ credenc.timestamp = rdata->timestamp;
+ credenc.ticket_info = ticket_info;
+ ret = encrypt_credencpart(context, &credenc, key, &enc);
+ if (ret)
+ goto cleanup;
+
+ /* Encode the KRB-CRED message. */
+ cred.magic = KV5M_CRED;
+ cred.tickets = tickets;
+ cred.enc_part = enc;
+ ret = encode_krb5_cred(&cred, der_out);
+ if (ret)
+ goto cleanup;
cleanup:
- krb5_free_cred_enc_part(context, &credenc);
- return retval;
+ krb5_free_tickets(context, tickets);
+ krb5_free_data_contents(context, &enc.ciphertext);
+ free(tinfos);
+ free(ticket_info);
+ return ret;
}
-/*----------------------- krb5_mk_ncred -----------------------*/
-
-/*
- * This functions takes as input an array of krb5_credentials, and
- * outputs an encoded KRB_CRED message suitable for krb5_rd_cred
- */
krb5_error_code KRB5_CALLCONV
-krb5_mk_ncred(krb5_context context, krb5_auth_context auth_context,
- krb5_creds **ppcreds, krb5_data **ppdata,
- krb5_replay_data *outdata)
+krb5_mk_ncred(krb5_context context, krb5_auth_context authcon,
+ krb5_creds **creds, krb5_data **der_out,
+ krb5_replay_data *rdata_out)
{
- krb5_address * premote_fulladdr = NULL;
- krb5_address * plocal_fulladdr = NULL;
- krb5_address remote_fulladdr;
- krb5_address local_fulladdr;
- krb5_error_code retval;
- krb5_key key;
- krb5_replay_data replaydata;
- krb5_cred * pcred;
- krb5_int32 ncred;
- krb5_boolean increased_sequence = FALSE;
+ krb5_error_code ret;
+ krb5_key key;
+ krb5_replay_data rdata;
+ krb5_data *der_krbcred = NULL;
+ krb5_address *local_addr, *remote_addr, lstorage, rstorage;
- local_fulladdr.contents = 0;
- remote_fulladdr.contents = 0;
- memset(&replaydata, 0, sizeof(krb5_replay_data));
+ *der_out = NULL;
+ memset(&lstorage, 0, sizeof(lstorage));
+ memset(&rstorage, 0, sizeof(rstorage));
- if (ppcreds == NULL)
+ if (creds == NULL)
return KRB5KRB_AP_ERR_BADADDR;
- /*
- * Allocate memory for a NULL terminated list of tickets.
- */
- for (ncred = 0; ppcreds[ncred]; ncred++)
- ;
-
- if ((pcred = (krb5_cred *)calloc(1, sizeof(krb5_cred))) == NULL)
- return ENOMEM;
-
- if ((pcred->tickets
- = (krb5_ticket **)calloc((size_t)ncred+1,
- sizeof(krb5_ticket *))) == NULL) {
- retval = ENOMEM;
- goto error;
- }
-
- /* Get keyblock */
- if ((key = auth_context->send_subkey) == NULL)
- key = auth_context->key;
-
- /* Get replay info */
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->rcache == NULL)) {
- retval = KRB5_RC_REQUIRED;
- goto error;
- }
-
- if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
- && (outdata == NULL)) {
- /* Need a better error */
- retval = KRB5_RC_REQUIRED;
- goto error;
- }
-
- if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
- &replaydata.usec)))
- goto error;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
- outdata->timestamp = replaydata.timestamp;
- outdata->usec = replaydata.usec;
- }
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
- replaydata.seq = auth_context->local_seq_number++;
- increased_sequence = TRUE;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
- outdata->seq = replaydata.seq;
- }
-
- 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)))
- goto error;
- plocal_fulladdr = &local_fulladdr;
- } else {
- plocal_fulladdr = auth_context->local_addr;
- }
- }
-
- if (auth_context->remote_addr) {
- if (auth_context->remote_port) {
- if ((retval = krb5_make_fulladdr(context,auth_context->remote_addr,
- auth_context->remote_port,
- &remote_fulladdr)))
- goto error;
- premote_fulladdr = &remote_fulladdr;
- } else {
- premote_fulladdr = auth_context->remote_addr;
- }
- }
-
- /* Setup creds structure */
- if ((retval = krb5_mk_ncred_basic(context, ppcreds, ncred, key,
- &replaydata, plocal_fulladdr,
- premote_fulladdr, pcred))) {
- goto error;
+ ret = k5_privsafe_gen_rdata(context, authcon, &rdata, rdata_out);
+ if (ret)
+ goto cleanup;
+ /* Historically we always set the timestamp, so keep doing that. */
+ if (rdata.timestamp == 0) {
+ ret = krb5_us_timeofday(context, &rdata.timestamp, &rdata.usec);
+ if (ret)
+ goto cleanup;
}
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
- krb5_donot_replay replay;
+ ret = k5_privsafe_gen_addrs(context, authcon, &lstorage, &rstorage,
+ &local_addr, &remote_addr);
+ if (ret)
+ goto cleanup;
- if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
- "_forw", &replay.client)))
- goto error;
-
- replay.server = ""; /* XXX */
- replay.msghash = NULL;
- replay.cusec = replaydata.usec;
- replay.ctime = replaydata.timestamp;
- if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
- /* should we really error out here? XXX */
- free(replay.client);
- goto error;
- }
- free(replay.client);
- }
+ key = (authcon->send_subkey != NULL) ? authcon->send_subkey : authcon->key;
+ ret = create_krbcred(context, creds, key, &rdata, local_addr, remote_addr,
+ &der_krbcred);
+ if (ret)
+ goto cleanup;
- /* Encode creds structure */
- retval = encode_krb5_cred(pcred, ppdata);
+ ret = k5_privsafe_check_replay(context, authcon, authcon->local_addr,
+ "_forw", &rdata, FALSE);
+ if (ret)
+ goto cleanup;
-error:
- free(local_fulladdr.contents);
- free(remote_fulladdr.contents);
- krb5_free_cred(context, pcred);
+ *der_out = der_krbcred;
+ der_krbcred = NULL;
+ if ((authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+ (authcon->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+ authcon->local_seq_number++;
- if (retval) {
- if (increased_sequence)
- auth_context->local_seq_number--;
+cleanup:
+ free(lstorage.contents);
+ free(rstorage.contents);
+ if (der_krbcred != NULL) {
+ zap(der_krbcred->data, der_krbcred->length);
+ krb5_free_data(context, der_krbcred);
}
- return retval;
+ return ret;
}
-/*----------------------- krb5_mk_1cred -----------------------*/
-
-/*
- * A convenience function that calls krb5_mk_ncred.
- */
krb5_error_code KRB5_CALLCONV
-krb5_mk_1cred(krb5_context context, krb5_auth_context auth_context,
- krb5_creds *pcreds, krb5_data **ppdata,
- krb5_replay_data *outdata)
+krb5_mk_1cred(krb5_context context, krb5_auth_context authcon,
+ krb5_creds *creds, krb5_data **der_out,
+ krb5_replay_data *rdata_out)
{
krb5_error_code retval;
- krb5_creds **ppcreds;
+ krb5_creds **list;
- if ((ppcreds = (krb5_creds **)malloc(sizeof(*ppcreds) * 2)) == NULL) {
+ list = calloc(2, sizeof(*list));
+ if (list == NULL)
return ENOMEM;
- }
-
- ppcreds[0] = pcreds;
- ppcreds[1] = NULL;
-
- retval = krb5_mk_ncred(context, auth_context, ppcreds,
- ppdata, outdata);
- free(ppcreds);
+ list[0] = creds;
+ list[1] = NULL;
+ retval = krb5_mk_ncred(context, authcon, list, der_out, rdata_out);
+ free(list);
return retval;
}
diff --git a/src/lib/krb5/krb/mk_priv.c b/src/lib/krb5/krb/mk_priv.c
index b3d9e68..d66ab8a 100644
--- a/src/lib/krb5/krb/mk_priv.c
+++ b/src/lib/krb5/krb/mk_priv.c
@@ -1,225 +1,153 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/krb/mk_priv.c */
+/* lib/krb5/krb/mk_priv.c - definition of krb5_mk_priv() */
/*
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2019 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "k5-int.h"
-#include "cleanup.h"
+#include "int-proto.h"
#include "auth_con.h"
+/*
+ * Marshal a KRB-PRIV message into der_out, encrypted with key. Use the
+ * timestamp and sequence number from rdata and the addresses from local_addr
+ * and remote_addr (the second of which may be NULL). der_out should be freed
+ * by the caller when finished.
+ */
static krb5_error_code
-mk_priv_basic(krb5_context context, const krb5_data *userdata,
- krb5_key key, krb5_replay_data *replaydata,
- krb5_address *local_addr, krb5_address *remote_addr,
- krb5_data *cstate, krb5_data *outbuf)
+create_krbpriv(krb5_context context, const krb5_data *userdata,
+ krb5_key key, const krb5_replay_data *rdata,
+ krb5_address *local_addr, krb5_address *remote_addr,
+ krb5_data *cstate, krb5_data *der_out)
{
- krb5_enctype enctype = krb5_k_key_enctype(context, key);
- krb5_error_code retval;
- krb5_priv privmsg;
- krb5_priv_enc_part privmsg_enc_part;
- krb5_data *scratch1, *scratch2;
- size_t enclen;
-
- privmsg.enc_part.kvno = 0; /* XXX allow user-set? */
+ krb5_enctype enctype = krb5_k_key_enctype(context, key);
+ krb5_error_code ret;
+ krb5_priv privmsg;
+ krb5_priv_enc_part encpart;
+ krb5_data *der_encpart, *der_krbpriv;
+ size_t enclen;
+
+ memset(&privmsg, 0, sizeof(privmsg));
+ privmsg.enc_part.kvno = 0;
privmsg.enc_part.enctype = enctype;
-
- privmsg_enc_part.user_data = *userdata;
- privmsg_enc_part.s_address = local_addr;
- privmsg_enc_part.r_address = remote_addr;
-
- /* We should check too make sure one exists. */
- privmsg_enc_part.timestamp = replaydata->timestamp;
- privmsg_enc_part.usec = replaydata->usec;
- privmsg_enc_part.seq_number = replaydata->seq;
-
- /* start by encoding to-be-encrypted part of the message */
- if ((retval = encode_krb5_enc_priv_part(&privmsg_enc_part, &scratch1)))
- return retval;
+ encpart.user_data = *userdata;
+ encpart.s_address = local_addr;
+ encpart.r_address = remote_addr;
+ encpart.timestamp = rdata->timestamp;
+ encpart.usec = rdata->usec;
+ encpart.seq_number = rdata->seq;
+
+ /* Start by encoding the to-be-encrypted part of the message. */
+ ret = encode_krb5_enc_priv_part(&encpart, &der_encpart);
+ if (ret)
+ return ret;
/* put together an eblock for this encryption */
- if ((retval = krb5_c_encrypt_length(context, enctype,
- scratch1->length, &enclen)))
- goto clean_scratch;
-
- privmsg.enc_part.ciphertext.length = enclen;
- if (!(privmsg.enc_part.ciphertext.data =
- malloc(privmsg.enc_part.ciphertext.length))) {
- retval = ENOMEM;
- goto clean_scratch;
+ ret = krb5_c_encrypt_length(context, enctype, der_encpart->length,
+ &enclen);
+ if (ret)
+ goto cleanup;
+
+ ret = alloc_data(&privmsg.enc_part.ciphertext, enclen);
+ if (ret)
+ goto cleanup;
+
+ ret = krb5_k_encrypt(context, key, KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
+ (cstate->length > 0) ? cstate : NULL, der_encpart,
+ &privmsg.enc_part);
+ if (ret)
+ goto cleanup;
+
+ ret = encode_krb5_priv(&privmsg, &der_krbpriv);
+ if (ret)
+ goto cleanup;
+
+ *der_out = *der_krbpriv;
+ free(der_krbpriv);
+
+cleanup:
+ zapfree(privmsg.enc_part.ciphertext.data,
+ privmsg.enc_part.ciphertext.length);
+ if (der_encpart != NULL) {
+ zap(der_encpart->data, der_encpart->length);
+ krb5_free_data(context, der_encpart);
}
-
- if ((retval = krb5_k_encrypt(context, key,
- KRB5_KEYUSAGE_KRB_PRIV_ENCPART,
- (cstate->length > 0) ? cstate : NULL,
- scratch1, &privmsg.enc_part)))
- goto clean_encpart;
-
- if ((retval = encode_krb5_priv(&privmsg, &scratch2)))
- goto clean_encpart;
-
- *outbuf = *scratch2;
- free(scratch2);
- retval = 0;
-
-clean_encpart:
- memset(privmsg.enc_part.ciphertext.data, 0,
- privmsg.enc_part.ciphertext.length);
- free(privmsg.enc_part.ciphertext.data);
- privmsg.enc_part.ciphertext.length = 0;
- privmsg.enc_part.ciphertext.data = 0;
-
-clean_scratch:
- memset(scratch1->data, 0, scratch1->length);
- krb5_free_data(context, scratch1);
-
- return retval;
+ return ret;
}
krb5_error_code KRB5_CALLCONV
-krb5_mk_priv(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *userdata, krb5_data *outbuf,
- krb5_replay_data *outdata)
+krb5_mk_priv(krb5_context context, krb5_auth_context authcon,
+ const krb5_data *userdata, krb5_data *der_out,
+ krb5_replay_data *rdata_out)
{
- krb5_error_code retval;
- krb5_key key;
- krb5_replay_data replaydata;
- krb5_data buf = empty_data();
-
- *outbuf = empty_data();
-
- /* Clear replaydata block */
- memset(&replaydata, 0, sizeof(krb5_replay_data));
-
- /* Get keyblock */
- if ((key = auth_context->send_subkey) == NULL)
- key = auth_context->key;
-
- /* Get replay info */
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->rcache == NULL))
- return KRB5_RC_REQUIRED;
-
- if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
- (outdata == NULL))
- /* Need a better error */
- return KRB5_RC_REQUIRED;
-
- if (!auth_context->local_addr)
+ krb5_error_code ret;
+ krb5_key key;
+ krb5_replay_data rdata;
+ krb5_data der_krbpriv = empty_data();
+ krb5_address *local_addr, *remote_addr, lstorage, rstorage;
+
+ *der_out = empty_data();
+ memset(&lstorage, 0, sizeof(lstorage));
+ memset(&rstorage, 0, sizeof(rstorage));
+ if (!authcon->local_addr)
return KRB5_LOCAL_ADDR_REQUIRED;
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
- if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
- &replaydata.usec)))
- return retval;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
- outdata->timestamp = replaydata.timestamp;
- outdata->usec = replaydata.usec;
- }
- }
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
- replaydata.seq = auth_context->local_seq_number++;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
- outdata->seq = replaydata.seq;
- }
-
- {
- krb5_address * premote_fulladdr = NULL;
- krb5_address * plocal_fulladdr;
- krb5_address remote_fulladdr;
- krb5_address local_fulladdr;
- CLEANUP_INIT(2);
-
- 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 {
- goto error;
- }
- } else {
- plocal_fulladdr = auth_context->local_addr;
- }
-
- if (auth_context->remote_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();
- goto error;
- }
- } else {
- premote_fulladdr = auth_context->remote_addr;
- }
- }
-
- if ((retval = mk_priv_basic(context, userdata, key, &replaydata,
- plocal_fulladdr, premote_fulladdr,
- &auth_context->cstate, &buf))) {
- CLEANUP_DONE();
- goto error;
- }
-
- CLEANUP_DONE();
- }
-
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
- krb5_donot_replay replay;
-
- if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
- "_priv", &replay.client)))
- goto error;
-
- replay.server = ""; /* XXX */
- replay.msghash = NULL;
- replay.cusec = replaydata.usec;
- replay.ctime = replaydata.timestamp;
- if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
- /* should we really error out here? XXX */
- free(replay.client);
- goto error;
- }
- free(replay.client);
- }
-
- *outbuf = buf;
- return 0;
-
-error:
- krb5_free_data_contents(context, &buf);
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
- auth_context->local_seq_number--;
-
- return retval;
+ ret = k5_privsafe_gen_rdata(context, authcon, &rdata, rdata_out);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_privsafe_gen_addrs(context, authcon, &lstorage, &rstorage,
+ &local_addr, &remote_addr);
+ if (ret)
+ goto cleanup;
+
+ key = (authcon->send_subkey != NULL) ? authcon->send_subkey : authcon->key;
+ ret = create_krbpriv(context, userdata, key, &rdata, local_addr,
+ remote_addr, &authcon->cstate, &der_krbpriv);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_privsafe_check_replay(context, authcon, authcon->local_addr,
+ "_priv", &rdata, FALSE);
+ if (ret)
+ goto cleanup;
+
+ *der_out = der_krbpriv;
+ der_krbpriv = empty_data();
+ if ((authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+ (authcon->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+ authcon->local_seq_number++;
+
+cleanup:
+ krb5_free_data_contents(context, &der_krbpriv);
+ free(lstorage.contents);
+ free(rstorage.contents);
+ return ret;
}
diff --git a/src/lib/krb5/krb/mk_safe.c b/src/lib/krb5/krb/mk_safe.c
index 1453365..02ee725 100644
--- a/src/lib/krb5/krb/mk_safe.c
+++ b/src/lib/krb5/krb/mk_safe.c
@@ -1,59 +1,56 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/krb/mk_safe.c */
+/* lib/krb5/krb/mk_safe.c - definition of krb5_mk_safe() */
/*
- * Copyright 1990,1991 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2019 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "k5-int.h"
-#include "cleanup.h"
+#include "int-proto.h"
#include "auth_con.h"
/*
- Formats a KRB_SAFE message into outbuf.
-
- userdata is formatted as the user data in the message.
- sumtype specifies the encryption type; key specifies the key which
- might be used to seed the checksum; sender_addr and recv_addr specify
- the full addresses (host and port) of the sender and receiver.
- The host portion of sender_addr is used to form the addresses used in the
- KRB_SAFE message.
-
- The outbuf buffer storage is allocated, and should be freed by the
- caller when finished.
-
- returns system errors
-*/
+ * Marshal a KRB-SAFE message into der_out, with a keyed checksum of type
+ * sumtype. Use the timestamp and sequence number from rdata and the addresses
+ * from local_addr and remote_addr (the second of which may be NULL). der_out
+ * should be freed by the caller when finished.
+ */
static krb5_error_code
-krb5_mk_safe_basic(krb5_context context, const krb5_data *userdata,
- krb5_key key, krb5_replay_data *replaydata,
- krb5_address *local_addr, krb5_address *remote_addr,
- krb5_cksumtype sumtype, krb5_data *outbuf)
+create_krbsafe(krb5_context context, const krb5_data *userdata, krb5_key key,
+ const krb5_replay_data *rdata, krb5_address *local_addr,
+ krb5_address *remote_addr, krb5_cksumtype sumtype,
+ krb5_data *der_out)
{
- krb5_error_code retval;
+ krb5_error_code ret;
krb5_safe safemsg;
krb5_octet zero_octet = 0;
krb5_checksum safe_checksum;
- krb5_data *scratch1, *scratch2;
+ krb5_data *der_krbsafe;
if (sumtype && !krb5_c_valid_cksumtype(sumtype))
return KRB5_PROG_SUMTYPE_NOSUPP;
@@ -61,48 +58,40 @@ krb5_mk_safe_basic(krb5_context context, const krb5_data *userdata,
return KRB5KRB_AP_ERR_INAPP_CKSUM;
safemsg.user_data = *userdata;
- safemsg.s_address = (krb5_address *) local_addr;
- safemsg.r_address = (krb5_address *) remote_addr;
-
- /* We should check too make sure one exists. */
- safemsg.timestamp = replaydata->timestamp;
- safemsg.usec = replaydata->usec;
- safemsg.seq_number = replaydata->seq;
-
- /*
- * To do the checksum stuff, we need to encode the message with a
- * zero-length zero-type checksum, then checksum the encoding, then
- * re-encode with the checksum.
- */
+ safemsg.s_address = local_addr;
+ safemsg.r_address = remote_addr;
+ safemsg.timestamp = rdata->timestamp;
+ safemsg.usec = rdata->usec;
+ safemsg.seq_number = rdata->seq;
+ /* Encode the message with a zero-length zero-type checksum. */
safe_checksum.length = 0;
safe_checksum.checksum_type = 0;
safe_checksum.contents = &zero_octet;
-
safemsg.checksum = &safe_checksum;
-
- if ((retval = encode_krb5_safe(&safemsg, &scratch1)))
- return retval;
-
- if ((retval = krb5_k_make_checksum(context, sumtype, key,
- KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
- scratch1, &safe_checksum)))
- goto cleanup_checksum;
-
+ ret = encode_krb5_safe(&safemsg, &der_krbsafe);
+ if (ret)
+ return ret;
+
+ /* Checksum the encoding. */
+ ret = krb5_k_make_checksum(context, sumtype, key,
+ KRB5_KEYUSAGE_KRB_SAFE_CKSUM, der_krbsafe,
+ &safe_checksum);
+ zap(der_krbsafe->data, der_krbsafe->length);
+ krb5_free_data(context, der_krbsafe);
+ if (ret)
+ return ret;
+
+ /* Encode the message again with the real checksum. */
safemsg.checksum = &safe_checksum;
- if ((retval = encode_krb5_safe(&safemsg, &scratch2))) {
- goto cleanup_checksum;
- }
- *outbuf = *scratch2;
- free(scratch2);
- retval = 0;
+ ret = encode_krb5_safe(&safemsg, &der_krbsafe);
+ krb5_free_checksum_contents(context, &safe_checksum);
+ if (ret)
+ return ret;
-cleanup_checksum:
- free(safe_checksum.contents);
-
- memset(scratch1->data, 0, scratch1->length);
- krb5_free_data(context, scratch1);
- return retval;
+ *der_out = *der_krbsafe;
+ free(der_krbsafe);
+ return 0;
}
/* Return the checksum type for the KRB-SAFE message, or 0 to use the enctype's
@@ -111,15 +100,14 @@ static krb5_cksumtype
safe_cksumtype(krb5_context context, krb5_auth_context auth_context,
krb5_enctype enctype)
{
- krb5_error_code retval;
+ krb5_error_code ret;
unsigned int nsumtypes, i;
krb5_cksumtype *sumtypes;
/* Use the auth context's safe_cksumtype if it is valid for the enctype.
* Otherwise return 0 for the mandatory checksum. */
- retval = krb5_c_keyed_checksum_types(context, enctype, &nsumtypes,
- &sumtypes);
- if (retval != 0)
+ ret = krb5_c_keyed_checksum_types(context, enctype, &nsumtypes, &sumtypes);
+ if (ret != 0)
return 0;
for (i = 0; i < nsumtypes; i++) {
if (auth_context->safe_cksumtype == sumtypes[i])
@@ -130,129 +118,53 @@ safe_cksumtype(krb5_context context, krb5_auth_context auth_context,
}
krb5_error_code KRB5_CALLCONV
-krb5_mk_safe(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *userdata, krb5_data *outbuf,
- krb5_replay_data *outdata)
+krb5_mk_safe(krb5_context context, krb5_auth_context authcon,
+ const krb5_data *userdata, krb5_data *der_out,
+ krb5_replay_data *rdata_out)
{
- krb5_error_code retval;
- krb5_key key;
- krb5_replay_data replaydata;
- krb5_data buf = empty_data();
-
- *outbuf = empty_data();
-
- /* Clear replaydata block */
- memset(&replaydata, 0, sizeof(krb5_replay_data));
-
- /* Get key */
- if ((key = auth_context->send_subkey) == NULL)
- key = auth_context->key;
-
- /* Get replay info */
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->rcache == NULL))
- return KRB5_RC_REQUIRED;
-
- if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
- (outdata == NULL))
- /* Need a better error */
- return KRB5_RC_REQUIRED;
-
- if (!auth_context->local_addr)
+ krb5_error_code ret;
+ krb5_key key;
+ krb5_replay_data rdata;
+ krb5_data der_krbsafe = empty_data();
+ krb5_address *local_addr, *remote_addr, lstorage, rstorage;
+ krb5_cksumtype sumtype;
+
+ *der_out = empty_data();
+ memset(&lstorage, 0, sizeof(lstorage));
+ memset(&rstorage, 0, sizeof(rstorage));
+ if (authcon->local_addr == NULL)
return KRB5_LOCAL_ADDR_REQUIRED;
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME)) {
- if ((retval = krb5_us_timeofday(context, &replaydata.timestamp,
- &replaydata.usec)))
- return retval;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) {
- outdata->timestamp = replaydata.timestamp;
- outdata->usec = replaydata.usec;
- }
- }
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
- replaydata.seq = auth_context->local_seq_number++;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)
- outdata->seq = replaydata.seq;
- }
-
- {
- krb5_address * premote_fulladdr = NULL;
- krb5_address * plocal_fulladdr;
- krb5_address remote_fulladdr;
- krb5_address local_fulladdr;
- krb5_cksumtype sumtype;
-
- CLEANUP_INIT(2);
-
- 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 {
- goto error;
- }
- } else {
- plocal_fulladdr = auth_context->local_addr;
- }
-
- if (auth_context->remote_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();
- goto error;
- }
- } else {
- premote_fulladdr = auth_context->remote_addr;
- }
- }
-
- sumtype = safe_cksumtype(context, auth_context, key->keyblock.enctype);
- if ((retval = krb5_mk_safe_basic(context, userdata, key, &replaydata,
- plocal_fulladdr, premote_fulladdr,
- sumtype, &buf))) {
- CLEANUP_DONE();
- goto error;
- }
-
- CLEANUP_DONE();
- }
-
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) {
- krb5_donot_replay replay;
-
- if ((retval = krb5_gen_replay_name(context, auth_context->local_addr,
- "_safe", &replay.client)))
- goto error;
-
- replay.server = ""; /* XXX */
- replay.msghash = NULL;
- replay.cusec = replaydata.usec;
- replay.ctime = replaydata.timestamp;
- /* should we really error out here? XXX */
- if ((retval = krb5_rc_store(context, auth_context->rcache, &replay)))
- goto error;
- free(replay.client);
- }
-
- *outbuf = buf;
- return 0;
-
-error:
- krb5_free_data_contents(context, &buf);
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
- auth_context->local_seq_number--;
-
- return retval;
+ ret = k5_privsafe_gen_rdata(context, authcon, &rdata, rdata_out);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_privsafe_gen_addrs(context, authcon, &lstorage, &rstorage,
+ &local_addr, &remote_addr);
+ if (ret)
+ goto cleanup;
+
+ key = (authcon->send_subkey != NULL) ? authcon->send_subkey : authcon->key;
+ sumtype = safe_cksumtype(context, authcon, key->keyblock.enctype);
+ ret = create_krbsafe(context, userdata, key, &rdata, local_addr,
+ remote_addr, sumtype, &der_krbsafe);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_privsafe_check_replay(context, authcon, authcon->local_addr,
+ "_safe", &rdata, FALSE);
+ if (ret)
+ goto cleanup;
+
+ *der_out = der_krbsafe;
+ der_krbsafe = empty_data();
+ if ((authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) ||
+ (authcon->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE))
+ authcon->local_seq_number++;
+
+cleanup:
+ krb5_free_data_contents(context, &der_krbsafe);
+ free(lstorage.contents);
+ free(rstorage.contents);
+ return ret;
}
diff --git a/src/lib/krb5/krb/privsafe.c b/src/lib/krb5/krb/privsafe.c
index 264b076..a1e5230 100644
--- a/src/lib/krb5/krb/privsafe.c
+++ b/src/lib/krb5/krb/privsafe.c
@@ -1,33 +1,145 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
/* lib/krb5/krb/privsafe.c - Shared logic for KRB-SAFE and KRB-PRIV messages */
/*
- * Copyright (C) 2011 by the Massachusetts Institute of Technology.
+ * Copyright (C) 2011,2019 by the Massachusetts Institute of Technology.
* All rights reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "k5-int.h"
#include "int-proto.h"
#include "auth_con.h"
+krb5_error_code
+k5_privsafe_gen_rdata(krb5_context context, krb5_auth_context authcon,
+ krb5_replay_data *rdata, krb5_replay_data *caller_rdata)
+{
+ krb5_error_code ret;
+ krb5_int32 flags = authcon->auth_context_flags;
+ krb5_boolean do_time = !!(flags & KRB5_AUTH_CONTEXT_DO_TIME);
+ krb5_boolean do_sequence = !!(flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE);
+ krb5_boolean ret_time = !!(flags & KRB5_AUTH_CONTEXT_RET_TIME);
+ krb5_boolean ret_sequence = !!(flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE);
+
+ memset(rdata, 0, sizeof(*rdata));
+ if ((ret_time || ret_sequence) && caller_rdata == NULL)
+ return KRB5_RC_REQUIRED;
+
+ if (do_time || ret_time) {
+ ret = krb5_us_timeofday(context, &rdata->timestamp, &rdata->usec);
+ if (ret)
+ return ret;
+ if (ret_time) {
+ caller_rdata->timestamp = rdata->timestamp;
+ caller_rdata->usec = rdata->usec;
+ }
+ }
+ if (do_sequence || ret_sequence) {
+ rdata->seq = authcon->local_seq_number;
+ if (ret_sequence)
+ caller_rdata->seq = rdata->seq;
+ }
+
+ return 0;
+}
+
+krb5_error_code
+k5_privsafe_gen_addrs(krb5_context context, krb5_auth_context authcon,
+ krb5_address *lstorage, krb5_address *rstorage,
+ krb5_address **local_out, krb5_address **remote_out)
+{
+ krb5_error_code ret;
+
+ *local_out = NULL;
+ *remote_out = NULL;
+
+ if (authcon->local_addr != NULL) {
+ if (authcon->local_port != NULL) {
+ ret = krb5_make_fulladdr(context, authcon->local_addr,
+ authcon->local_port, lstorage);
+ if (ret)
+ return ret;
+ *local_out = lstorage;
+ } else {
+ *local_out = authcon->local_addr;
+ }
+ }
+
+ if (authcon->remote_addr != NULL) {
+ if (authcon->remote_port != NULL) {
+ ret = krb5_make_fulladdr(context, authcon->remote_addr,
+ authcon->remote_port, rstorage);
+ if (ret)
+ return ret;
+ *remote_out = rstorage;
+ } else {
+ *remote_out = authcon->remote_addr;
+ }
+ }
+
+ return 0;
+}
+
+krb5_error_code
+k5_privsafe_check_replay(krb5_context context, krb5_auth_context authcon,
+ krb5_address *addr, const char *uniq,
+ const krb5_replay_data *rdata,
+ krb5_boolean check_time)
+{
+ krb5_error_code ret;
+ krb5_donot_replay replay;
+ char *client = NULL;
+
+ if (!(authcon->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME))
+ return 0;
+
+ if (authcon->rcache == NULL)
+ return KRB5_RC_REQUIRED;
+
+ if (check_time) {
+ ret = krb5_check_clockskew(context, rdata->timestamp);
+ if (ret)
+ return ret;
+ }
+
+ ret = krb5_gen_replay_name(context, addr, uniq, &client);
+ if (ret)
+ return ret;
+
+ replay.client = client;
+ replay.server = "";
+ replay.msghash = NULL;
+ replay.cusec = rdata->usec;
+ replay.ctime = rdata->timestamp;
+ ret = krb5_rc_store(context, authcon->rcache, &replay);
+ free(replay.client);
+ return ret;
+}
+
/*
* k5_privsafe_check_seqnum
*
diff --git a/src/lib/krb5/krb/rd_cred.c b/src/lib/krb5/krb/rd_cred.c
index b08108b..7fdd103 100644
--- a/src/lib/krb5/krb/rd_cred.c
+++ b/src/lib/krb5/krb/rd_cred.c
@@ -4,37 +4,40 @@
* Copyright 1994-2009,2014 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "k5-int.h"
-#include "cleanup.h"
+#include "int-proto.h"
#include "auth_con.h"
-#include <stdlib.h>
-#include <errno.h>
-
/*
* Decrypt and decode the enc_part of a krb5_cred using the receiving subkey or
* the session key of authcon. If neither key is present, ctext->ciphertext is
- * assumed to be unencrypted plain text.
+ * assumed to be unencrypted plain text (RFC 6448).
*/
static krb5_error_code
decrypt_encpart(krb5_context context, krb5_enc_data *ctext,
@@ -145,7 +148,7 @@ krb5_rd_cred(krb5_context context, krb5_auth_context authcon,
krb5_creds **credlist = NULL;
krb5_cred *krbcred = NULL;
krb5_cred_enc_part *encpart = NULL;
- krb5_donot_replay replay;
+ krb5_replay_data rdata;
const krb5_int32 flags = authcon->auth_context_flags;
*creds_out = NULL;
@@ -170,25 +173,13 @@ krb5_rd_cred(krb5_context context, krb5_auth_context authcon,
if (ret)
goto cleanup;
- if (flags & KRB5_AUTH_CONTEXT_DO_TIME) {
- ret = krb5_check_clockskew(context, encpart->timestamp);
- if (ret)
- goto cleanup;
-
- ret = krb5_gen_replay_name(context, authcon->remote_addr, "_forw",
- &replay.client);
- if (ret)
- goto cleanup;
-
- replay.server = "";
- replay.msghash = NULL;
- replay.cusec = encpart->usec;
- replay.ctime = encpart->timestamp;
- ret = krb5_rc_store(context, authcon->rcache, &replay);
- free(replay.client);
- if (ret)
- goto cleanup;
- }
+ rdata.timestamp = encpart->timestamp;
+ rdata.usec = encpart->usec;
+ rdata.seq = encpart->nonce;
+ ret = k5_privsafe_check_replay(context, authcon, authcon->remote_addr,
+ "_forw", &rdata, TRUE);
+ if (ret)
+ goto cleanup;
if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
if (authcon->remote_seq_number != (uint32_t)encpart->nonce) {
diff --git a/src/lib/krb5/krb/rd_priv.c b/src/lib/krb5/krb/rd_priv.c
index 2912ab1b..34eb656 100644
--- a/src/lib/krb5/krb/rd_priv.c
+++ b/src/lib/krb5/krb/rd_priv.c
@@ -1,27 +1,33 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/krb/rd_priv.c */
+/* lib/krb5/krb/rd_priv.c - krb5_rd_priv() */
/*
- * Copyright 1990,1991,2007 by the Massachusetts Institute of Technology.
+ * Copyright 1990,1991,2007,2019 by the Massachusetts Institute of Technology.
* All Rights Reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "k5-int.h"
@@ -29,160 +35,112 @@
#include "auth_con.h"
/*
-
- Parses a KRB_PRIV message from inbuf, placing the confidential user
- data in *outbuf.
-
- key specifies the key to be used for decryption of the message.
-
- outbuf points to allocated storage which the caller should
- free when finished.
-
- Returns system errors, integrity errors.
-
-*/
-
+ * Unmarshal a KRB-PRIV message from der_krbpriv, placing the confidential user
+ * data in *userdata_out and replay data in *rdata_out. The caller should free
+ * *userdata_out when finished.
+ */
static krb5_error_code
-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)
+read_krbpriv(krb5_context context, krb5_auth_context authcon,
+ const krb5_data *der_krbpriv, const krb5_key key,
+ krb5_replay_data *rdata_out, krb5_data *userdata_out)
{
- krb5_error_code retval;
- krb5_priv * privmsg;
- krb5_data scratch;
- krb5_priv_enc_part * privmsg_enc_part;
- krb5_data *iv = NULL;
+ krb5_error_code ret;
+ krb5_priv *privmsg = NULL;
+ krb5_data plaintext = empty_data();
+ krb5_priv_enc_part *encpart = NULL;
+ krb5_data *cstate;
- if (!krb5_is_krb_priv(inbuf))
+ if (!krb5_is_krb_priv(der_krbpriv))
return KRB5KRB_AP_ERR_MSG_TYPE;
/* decode private message */
- if ((retval = decode_krb5_priv(inbuf, &privmsg)))
- return retval;
-
- if (ac->cstate.length > 0)
- iv = &ac->cstate;
-
- scratch.length = privmsg->enc_part.ciphertext.length;
- if (!(scratch.data = malloc(scratch.length))) {
- retval = ENOMEM;
- goto cleanup_privmsg;
- }
-
- if ((retval = krb5_k_decrypt(context, key,
- KRB5_KEYUSAGE_KRB_PRIV_ENCPART, iv,
- &privmsg->enc_part, &scratch)))
- goto cleanup_scratch;
-
- /* now decode the decrypted stuff */
- if ((retval = decode_krb5_enc_priv_part(&scratch, &privmsg_enc_part)))
- goto cleanup_scratch;
-
- retval = k5_privsafe_check_addrs(context, ac, privmsg_enc_part->s_address,
- privmsg_enc_part->r_address);
- if (retval)
- goto cleanup_data;
-
- replaydata->timestamp = privmsg_enc_part->timestamp;
- replaydata->usec = privmsg_enc_part->usec;
- replaydata->seq = privmsg_enc_part->seq_number;
-
- /* everything is ok - return data to the user */
- *outbuf = privmsg_enc_part->user_data;
- retval = 0;
-
-cleanup_data:;
- if (retval == 0)
- privmsg_enc_part->user_data.data = 0;
- krb5_free_priv_enc_part(context, privmsg_enc_part);
-
-cleanup_scratch:;
- memset(scratch.data, 0, scratch.length);
- free(scratch.data);
-
-cleanup_privmsg:;
- free(privmsg->enc_part.ciphertext.data);
- free(privmsg);
-
- return retval;
+ ret = decode_krb5_priv(der_krbpriv, &privmsg);
+ if (ret)
+ return ret;
+
+ ret = alloc_data(&plaintext, privmsg->enc_part.ciphertext.length);
+ if (ret)
+ goto cleanup;
+
+ cstate = (authcon->cstate.length > 0) ? &authcon->cstate : NULL;
+ ret = krb5_k_decrypt(context, key, KRB5_KEYUSAGE_KRB_PRIV_ENCPART, cstate,
+ &privmsg->enc_part, &plaintext);
+ if (ret)
+ goto cleanup;
+
+ ret = decode_krb5_enc_priv_part(&plaintext, &encpart);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_privsafe_check_addrs(context, authcon, encpart->s_address,
+ encpart->r_address);
+ if (ret)
+ goto cleanup;
+
+ rdata_out->timestamp = encpart->timestamp;
+ rdata_out->usec = encpart->usec;
+ rdata_out->seq = encpart->seq_number;
+
+ *userdata_out = encpart->user_data;
+ encpart->user_data.data = NULL;
+
+cleanup:
+ krb5_free_priv_enc_part(context, encpart);
+ krb5_free_priv(context, privmsg);
+ zapfree(plaintext.data, plaintext.length);
+ return ret;
}
krb5_error_code KRB5_CALLCONV
-krb5_rd_priv(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *inbuf, krb5_data *outbuf,
- krb5_replay_data *outdata)
+krb5_rd_priv(krb5_context context, krb5_auth_context authcon,
+ const krb5_data *inbuf, krb5_data *userdata_out,
+ krb5_replay_data *rdata_out)
{
- krb5_error_code retval;
- krb5_key key;
- krb5_replay_data replaydata;
-
- /* Get key */
- if ((key = auth_context->recv_subkey) == NULL)
- key = auth_context->key;
-
- if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
- (outdata == NULL))
- /* Need a better error */
- return KRB5_RC_REQUIRED;
+ krb5_error_code ret;
+ krb5_key key;
+ krb5_replay_data rdata;
+ krb5_data userdata = empty_data();
+ const krb5_int32 flags = authcon->auth_context_flags;
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->remote_addr == NULL))
- return KRB5_REMOTE_ADDR_REQUIRED;
+ *userdata_out = empty_data();
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->rcache == NULL))
+ if (((flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+ (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && rdata_out == NULL)
return KRB5_RC_REQUIRED;
- 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;
-
- if ((retval = krb5_check_clockskew(context, replaydata.timestamp)))
- goto error;
-
- if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
- "_priv", &replay.client)))
- goto error;
-
- replay.server = ""; /* XXX */
- replay.msghash = NULL;
- replay.cusec = replaydata.usec;
- replay.ctime = replaydata.timestamp;
- if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
- free(replay.client);
- goto error;
- }
- free(replay.client);
- }
+ if ((flags & KRB5_AUTH_CONTEXT_DO_TIME) && authcon->remote_addr == NULL)
+ return KRB5_REMOTE_ADDR_REQUIRED;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
- if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) {
- retval = KRB5KRB_AP_ERR_BADORDER;
- goto error;
+ key = (authcon->recv_subkey != NULL) ? authcon->recv_subkey : authcon->key;
+ memset(&rdata, 0, sizeof(rdata));
+ ret = read_krbpriv(context, authcon, inbuf, key, &rdata, &userdata);
+ if (ret)
+ goto cleanup;
+
+ ret = k5_privsafe_check_replay(context, authcon, authcon->remote_addr,
+ "_priv", &rdata, TRUE);
+ if (ret)
+ goto cleanup;
+
+ if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+ if (!k5_privsafe_check_seqnum(context, authcon, rdata.seq)) {
+ ret = KRB5KRB_AP_ERR_BADORDER;
+ goto cleanup;
}
- auth_context->remote_seq_number++;
+ authcon->remote_seq_number++;
}
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
- outdata->timestamp = replaydata.timestamp;
- outdata->usec = replaydata.usec;
- outdata->seq = replaydata.seq;
+ if ((flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+ (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+ rdata_out->timestamp = rdata.timestamp;
+ rdata_out->usec = rdata.usec;
+ rdata_out->seq = rdata.seq;
}
- /* everything is ok - return data to the user */
- return 0;
-
-error:;
- free(outbuf->data);
- outbuf->length = 0;
- outbuf->data = NULL;
+ *userdata_out = userdata;
+ userdata = empty_data();
- return retval;
+cleanup:
+ krb5_free_data_contents(context, &userdata);
+ return ret;
}
diff --git a/src/lib/krb5/krb/rd_safe.c b/src/lib/krb5/krb/rd_safe.c
index 5d2cee2..eab7f6d 100644
--- a/src/lib/krb5/krb/rd_safe.c
+++ b/src/lib/krb5/krb/rd_safe.c
@@ -1,210 +1,174 @@
/* -*- mode: c; c-basic-offset: 4; indent-tabs-mode: nil -*- */
-/* lib/krb5/krb/rd_safe.c - definition of krb5_rd_safe() */
+/* lib/krb5/krb/rd_safe.c - krb5_rd_safe() */
/*
- * Copyright 1990,1991,2007,2008 by the Massachusetts Institute of Technology.
- * All Rights Reserved.
+ * Copyright 1990,1991,2007,2008,2019 by the Massachusetts Institute of
+ * Technology. All Rights Reserved.
*
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
*
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
+ * * Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * * Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
+ * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
+ * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
+ * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
+ * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
+ * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
+ * OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "k5-int.h"
#include "int-proto.h"
-#include "cleanup.h"
#include "auth_con.h"
/*
- parses a KRB_SAFE message from inbuf, placing the integrity-protected user
- data in *outbuf.
-
- key specifies the key to be used for decryption of the message.
-
- outbuf points to allocated storage which the caller should free when finished.
-
- returns system errors, integrity errors
-*/
+ * Unmarshal a KRB-SAFE message from der_krbsafe, placing the
+ * integrity-protected user data in *userdata_out and replay data in
+ * *rdata_out. The caller should free *userdata_out when finished.
+ */
static krb5_error_code
-rd_safe_basic(krb5_context context, krb5_auth_context ac,
- const krb5_data *inbuf, krb5_key key,
- krb5_replay_data *replaydata, krb5_data *outbuf)
+read_krbsafe(krb5_context context, krb5_auth_context ac,
+ const krb5_data *der_krbsafe, krb5_key key,
+ krb5_replay_data *rdata_out, krb5_data *userdata_out)
{
- krb5_error_code retval;
- krb5_safe * message;
- krb5_data *safe_body = NULL;
- krb5_checksum our_cksum, *his_cksum;
+ krb5_error_code ret;
+ krb5_safe *krbsafe;
+ krb5_data *safe_body = NULL, *der_zerosafe = NULL;
+ krb5_checksum zero_cksum, *safe_cksum;
krb5_octet zero_octet = 0;
- krb5_data *scratch;
krb5_boolean valid;
struct krb5_safe_with_body swb;
- if (!krb5_is_krb_safe(inbuf))
+ *userdata_out = empty_data();
+ if (!krb5_is_krb_safe(der_krbsafe))
return KRB5KRB_AP_ERR_MSG_TYPE;
- if ((retval = decode_krb5_safe_with_body(inbuf, &message, &safe_body)))
- return retval;
+ ret = decode_krb5_safe_with_body(der_krbsafe, &krbsafe, &safe_body);
+ if (ret)
+ return ret;
- if (!krb5_c_valid_cksumtype(message->checksum->checksum_type)) {
- retval = KRB5_PROG_SUMTYPE_NOSUPP;
+ if (!krb5_c_valid_cksumtype(krbsafe->checksum->checksum_type)) {
+ ret = KRB5_PROG_SUMTYPE_NOSUPP;
goto cleanup;
}
- if (!krb5_c_is_coll_proof_cksum(message->checksum->checksum_type) ||
- !krb5_c_is_keyed_cksum(message->checksum->checksum_type)) {
- retval = KRB5KRB_AP_ERR_INAPP_CKSUM;
+ if (!krb5_c_is_coll_proof_cksum(krbsafe->checksum->checksum_type) ||
+ !krb5_c_is_keyed_cksum(krbsafe->checksum->checksum_type)) {
+ ret = KRB5KRB_AP_ERR_INAPP_CKSUM;
goto cleanup;
}
- retval = k5_privsafe_check_addrs(context, ac, message->s_address,
- message->r_address);
- if (retval)
+ ret = k5_privsafe_check_addrs(context, ac, krbsafe->s_address,
+ krbsafe->r_address);
+ if (ret)
goto cleanup;
- /* verify the checksum */
- /*
- * In order to recreate what was checksummed, we regenerate the message
- * without checksum and then have the cryptographic subsystem verify
- * the checksum for us. This is because some checksum methods have
- * a confounder encrypted as part of the checksum.
- */
- his_cksum = message->checksum;
-
- our_cksum.length = 0;
- our_cksum.checksum_type = 0;
- our_cksum.contents = &zero_octet;
-
- message->checksum = &our_cksum;
-
+ /* Regenerate the KRB-SAFE message without the checksum. */
+ safe_cksum = krbsafe->checksum;
+ zero_cksum.length = 0;
+ zero_cksum.checksum_type = 0;
+ zero_cksum.contents = &zero_octet;
+ krbsafe->checksum = &zero_cksum;
swb.body = safe_body;
- swb.safe = message;
- retval = encode_krb5_safe_with_body(&swb, &scratch);
- message->checksum = his_cksum;
- if (retval)
+ swb.safe = krbsafe;
+ ret = encode_krb5_safe_with_body(&swb, &der_zerosafe);
+ krbsafe->checksum = safe_cksum;
+ if (ret)
goto cleanup;
- retval = krb5_k_verify_checksum(context, key,
- KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
- scratch, his_cksum, &valid);
-
- (void) memset(scratch->data, 0, scratch->length);
- krb5_free_data(context, scratch);
-
+ /* Verify the checkum over the re-encoded message. */
+ ret = krb5_k_verify_checksum(context, key, KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
+ der_zerosafe, safe_cksum, &valid);
if (!valid) {
- /*
- * Checksum over only the KRB-SAFE-BODY, like RFC 1510 says, in
- * case someone actually implements it correctly.
- */
- retval = krb5_k_verify_checksum(context, key,
- KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
- safe_body, his_cksum, &valid);
+ /* Checksum over only the KRB-SAFE-BODY as specified in RFC 1510. */
+ ret = krb5_k_verify_checksum(context, key,
+ KRB5_KEYUSAGE_KRB_SAFE_CKSUM,
+ safe_body, safe_cksum, &valid);
if (!valid) {
- retval = KRB5KRB_AP_ERR_MODIFIED;
+ ret = KRB5KRB_AP_ERR_MODIFIED;
goto cleanup;
}
}
- replaydata->timestamp = message->timestamp;
- replaydata->usec = message->usec;
- replaydata->seq = message->seq_number;
+ rdata_out->timestamp = krbsafe->timestamp;
+ rdata_out->usec = krbsafe->usec;
+ rdata_out->seq = krbsafe->seq_number;
- *outbuf = message->user_data;
- message->user_data.data = NULL;
- retval = 0;
+ *userdata_out = krbsafe->user_data;
+ krbsafe->user_data.data = NULL;
cleanup:
- krb5_free_safe(context, message);
+ if (der_zerosafe != NULL) {
+ zap(der_zerosafe->data, der_zerosafe->length);
+ krb5_free_data(context, der_zerosafe);
+ }
krb5_free_data(context, safe_body);
- return retval;
+ krb5_free_safe(context, krbsafe);
+ return ret;
}
krb5_error_code KRB5_CALLCONV
-krb5_rd_safe(krb5_context context, krb5_auth_context auth_context,
- const krb5_data *inbuf, krb5_data *outbuf,
- krb5_replay_data *outdata)
+krb5_rd_safe(krb5_context context, krb5_auth_context authcon,
+ const krb5_data *inbuf, krb5_data *userdata_out,
+ krb5_replay_data *rdata_out)
{
- krb5_error_code retval;
- krb5_key key;
- krb5_replay_data replaydata;
-
- if (((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) &&
- (outdata == NULL))
- /* Need a better error */
+ krb5_error_code ret;
+ krb5_key key;
+ krb5_replay_data rdata;
+ krb5_data userdata = empty_data();
+ const krb5_int32 flags = authcon->auth_context_flags;
+
+ *userdata_out = empty_data();
+
+ if (((flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+ (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) && rdata_out == NULL)
return KRB5_RC_REQUIRED;
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->remote_addr == NULL))
+ if ((flags & KRB5_AUTH_CONTEXT_DO_TIME) && authcon->remote_addr == NULL)
return KRB5_REMOTE_ADDR_REQUIRED;
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_TIME) &&
- (auth_context->rcache == NULL))
- return KRB5_RC_REQUIRED;
+ key = (authcon->recv_subkey != NULL) ? authcon->recv_subkey : authcon->key;
+ memset(&rdata, 0, sizeof(rdata));
+ ret = read_krbsafe(context, authcon, inbuf, key, &rdata, &userdata);
+ if (ret)
+ goto cleanup;
- /* Get key */
- if ((key = auth_context->recv_subkey) == NULL)
- key = auth_context->key;
-
- 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;
-
- if ((retval = krb5_check_clockskew(context, replaydata.timestamp)))
- goto error;
-
- if ((retval = krb5_gen_replay_name(context, auth_context->remote_addr,
- "_safe", &replay.client)))
- goto error;
-
- replay.server = ""; /* XXX */
- replay.msghash = NULL;
- replay.cusec = replaydata.usec;
- replay.ctime = replaydata.timestamp;
- if ((retval = krb5_rc_store(context, auth_context->rcache, &replay))) {
- free(replay.client);
- goto error;
- }
- free(replay.client);
- }
+ ret = k5_privsafe_check_replay(context, authcon, authcon->remote_addr,
+ "_safe", &rdata, TRUE);
+ if (ret)
+ goto cleanup;
- if (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
- if (!k5_privsafe_check_seqnum(context, auth_context, replaydata.seq)) {
- retval = KRB5KRB_AP_ERR_BADORDER;
- goto error;
+ if (flags & KRB5_AUTH_CONTEXT_DO_SEQUENCE) {
+ if (!k5_privsafe_check_seqnum(context, authcon, rdata.seq)) {
+ ret = KRB5KRB_AP_ERR_BADORDER;
+ goto cleanup;
}
- auth_context->remote_seq_number++;
+ authcon->remote_seq_number++;
}
- if ((auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
- (auth_context->auth_context_flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
- outdata->timestamp = replaydata.timestamp;
- outdata->usec = replaydata.usec;
- outdata->seq = replaydata.seq;
+ if ((flags & KRB5_AUTH_CONTEXT_RET_TIME) ||
+ (flags & KRB5_AUTH_CONTEXT_RET_SEQUENCE)) {
+ rdata_out->timestamp = rdata.timestamp;
+ rdata_out->usec = rdata.usec;
+ rdata_out->seq = rdata.seq;
}
- /* everything is ok - return data to the user */
- return 0;
-
-error:
- free(outbuf->data);
- return retval;
+ *userdata_out = userdata;
+ userdata = empty_data();
+cleanup:
+ krb5_free_data_contents(context, &userdata);
+ return ret;
}
More information about the cvs-krb5
mailing list