summaryrefslogtreecommitdiffstats
path: root/src/lib/gssapi
diff options
context:
space:
mode:
authorMarc Horowitz <marc@mit.edu>1998-10-30 02:56:35 +0000
committerMarc Horowitz <marc@mit.edu>1998-10-30 02:56:35 +0000
commit1440ab035ba04550ddbbfbff1ee9b5571e3d95db (patch)
tree9d5e8d2e151a930e044c7d0f7c64053d244577a0 /src/lib/gssapi
parent61ddbf948ba6ee70c1bc049268c3dfa73bc9983e (diff)
downloadkrb5-1440ab035ba04550ddbbfbff1ee9b5571e3d95db.tar.gz
krb5-1440ab035ba04550ddbbfbff1ee9b5571e3d95db.tar.xz
krb5-1440ab035ba04550ddbbfbff1ee9b5571e3d95db.zip
pull up 3des implementation from the marc-3des branch
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@11001 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/lib/gssapi')
-rw-r--r--src/lib/gssapi/Makefile.in2
-rw-r--r--src/lib/gssapi/generic/ChangeLog5
-rw-r--r--src/lib/gssapi/generic/gssapi.hin8
-rw-r--r--src/lib/gssapi/generic/gssapi_err_generic.et3
-rw-r--r--src/lib/gssapi/generic/util_token.c7
-rw-r--r--src/lib/gssapi/krb5/ChangeLog39
-rw-r--r--src/lib/gssapi/krb5/Makefile.in6
-rw-r--r--src/lib/gssapi/krb5/accept_sec_context.c980
-rw-r--r--src/lib/gssapi/krb5/acquire_cred.c115
-rw-r--r--src/lib/gssapi/krb5/add_cred.c309
-rw-r--r--src/lib/gssapi/krb5/canon_name.c17
-rw-r--r--src/lib/gssapi/krb5/delete_sec_context.c15
-rw-r--r--src/lib/gssapi/krb5/disp_status.c10
-rw-r--r--src/lib/gssapi/krb5/gssapiP_krb5.h77
-rw-r--r--src/lib/gssapi/krb5/gssapi_err_krb5.et1
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.c39
-rw-r--r--src/lib/gssapi/krb5/gssapi_krb5.h3
-rw-r--r--src/lib/gssapi/krb5/init_sec_context.c604
-rw-r--r--src/lib/gssapi/krb5/inq_cred.c57
-rw-r--r--src/lib/gssapi/krb5/inq_names.c3
-rw-r--r--src/lib/gssapi/krb5/k5seal.c356
-rw-r--r--src/lib/gssapi/krb5/k5unseal.c585
-rw-r--r--src/lib/gssapi/krb5/rel_oid.c3
-rw-r--r--src/lib/gssapi/krb5/ser_sctx.c305
-rw-r--r--src/lib/gssapi/krb5/util_cksum.c27
-rw-r--r--src/lib/gssapi/krb5/util_crypt.c161
-rw-r--r--src/lib/gssapi/krb5/util_ctxsetup.c208
-rw-r--r--src/lib/gssapi/krb5/util_seed.c16
-rw-r--r--src/lib/gssapi/krb5/util_seqnum.c12
-rw-r--r--src/lib/gssapi/krb5/wrap_size_limit.c108
30 files changed, 3118 insertions, 963 deletions
diff --git a/src/lib/gssapi/Makefile.in b/src/lib/gssapi/Makefile.in
index 6835596f7..843207133 100644
--- a/src/lib/gssapi/Makefile.in
+++ b/src/lib/gssapi/Makefile.in
@@ -9,7 +9,7 @@ LOCAL_SUBDIRS= generic krb5
MAC_SUBDIRS = generic krb5
LIB=gssapi_krb5
-LIBMAJOR=1
+LIBMAJOR=2
LIBMINOR=1
STOBJLISTS=generic/OBJS.ST krb5/OBJS.ST
SHLIB_EXPDEPS=\
diff --git a/src/lib/gssapi/generic/ChangeLog b/src/lib/gssapi/generic/ChangeLog
index 74f13a4a3..601ca76f6 100644
--- a/src/lib/gssapi/generic/ChangeLog
+++ b/src/lib/gssapi/generic/ChangeLog
@@ -1,3 +1,8 @@
+1998-10-27 Marc Horowitz <marc@mit.edu>
+
+ * gssapi.hin: define GSS_S_DUPLICATE_ELEMENT, GSS_S_NAME_NOT_MN,
+ and GSS_S_GAP_TOKEN as per gss v2 c bindings
+
1998-06-08 Theodore Ts'o <tytso@rsts-11.mit.edu>
* oid_ops.c (generic_gss_release_oid): Recognize our own "self"
diff --git a/src/lib/gssapi/generic/gssapi.hin b/src/lib/gssapi/generic/gssapi.hin
index d00e19ab9..a30b79431 100644
--- a/src/lib/gssapi/generic/gssapi.hin
+++ b/src/lib/gssapi/generic/gssapi.hin
@@ -307,11 +307,10 @@ typedef int gss_cred_usage_t;
#define GSS_S_BAD_QOP (((OM_uint32) 14ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAUTHORIZED (((OM_uint32) 15ul) << GSS_C_ROUTINE_ERROR_OFFSET)
#define GSS_S_UNAVAILABLE (((OM_uint32) 16ul) << GSS_C_ROUTINE_ERROR_OFFSET)
-/*
- * XXX new functions. Check to get official error number assigments?
- */
#define GSS_S_DUPLICATE_ELEMENT \
(((OM_uint32) 17ul) << GSS_C_ROUTINE_ERROR_OFFSET)
+#define GSS_S_NAME_NOT_MN \
+ (((OM_uint32) 18ul) << GSS_C_ROUTINE_ERROR_OFFSET)
/*
* Supplementary info bits:
@@ -320,9 +319,6 @@ typedef int gss_cred_usage_t;
#define GSS_S_DUPLICATE_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 1))
#define GSS_S_OLD_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 2))
#define GSS_S_UNSEQ_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 3))
-/*
- * XXX not in the cbindings yet. remove this comment when it is
- */
#define GSS_S_GAP_TOKEN (1 << (GSS_C_SUPPLEMENTARY_OFFSET + 4))
diff --git a/src/lib/gssapi/generic/gssapi_err_generic.et b/src/lib/gssapi/generic/gssapi_err_generic.et
index ddeed4227..99ba45fe3 100644
--- a/src/lib/gssapi/generic/gssapi_err_generic.et
+++ b/src/lib/gssapi/generic/gssapi_err_generic.et
@@ -40,4 +40,7 @@ error_code G_BAD_HOSTNAME, "Hostname in SERVICE-NAME string could not be canonic
error_code G_WRONG_MECH, "Mechanism is incorrect"
error_code G_BAD_TOK_HEADER, "Token header is malformed or corrupt"
error_code G_BAD_DIRECTION, "Packet was replayed in wrong direction"
+error_code G_TOK_TRUNC, "Token is missing data"
+error_code G_REFLECT, "Token was reflected"
+error_code G_WRONG_TOKID, "Received token ID does not match expected token ID"
end
diff --git a/src/lib/gssapi/generic/util_token.c b/src/lib/gssapi/generic/util_token.c
index 627b5011b..9e186a153 100644
--- a/src/lib/gssapi/generic/util_token.c
+++ b/src/lib/gssapi/generic/util_token.c
@@ -205,9 +205,12 @@ gss_int32 g_verify_token_header(mech, body_size, buf_in, tok_type, toksize)
if ((toksize-=2) < 0)
return(G_BAD_TOK_HEADER);
+ if (ret)
+ return(ret);
+
if ((*buf++ != ((tok_type>>8)&0xff)) ||
- (*buf++ != (tok_type&0xff)))
- return(G_BAD_TOK_HEADER);
+ (*buf++ != (tok_type&0xff)))
+ return(G_WRONG_TOKID);
if (!ret) {
*buf_in = buf;
diff --git a/src/lib/gssapi/krb5/ChangeLog b/src/lib/gssapi/krb5/ChangeLog
index a94aeb72d..e12dfdb2b 100644
--- a/src/lib/gssapi/krb5/ChangeLog
+++ b/src/lib/gssapi/krb5/ChangeLog
@@ -1,3 +1,42 @@
+1998-10-27 Marc Horowitz <marc@mit.edu>
+
+ * Makefile.in, accept_sec_context.c, acquire_cred.c, canon_name.c,
+ delete_sec_context.c, disp_status.c, gssapiP_krb5.h,
+ gssapi_err_krb5.et, gssapi_krb5.c, gssapi_krb5.h,
+ init_sec_context.c, inq_cred.c, inq_names.c, k5seal.c, k5unseal.c,
+ rel_oid.c, ser_sctx.c, util_cksum.c, util_crypt.c, util_seed.c,
+ util_seqnum.c, wrap_size_limit.c: convert to new crypto api.
+ Implement new krb5 v2 gssapi mechanism.
+
+ * add_cred.c, util_ctxsetup.c: New files needed to implement the
+ krb5 v2 mech.
+
+Mon Sep 21 00:32:28 1998 Tom Yu <tlyu@mit.edu>
+
+ * accept_sec_context.c (krb5_gss_accept_sec_context): Free authdat
+ even on success to avoid a memory leak.
+
+ * util_cksum.c (kg_checksum_channel_bindings): Fix memory leak by
+ not allocating cksum->contents unless we have to return a
+ zero-filled one.
+
+ * k5unseal.c (kg_unseal_v1): Fix memorly leak by not allocating
+ md5cksum.contents.
+
+ * k5seal.c (make_seal_token_v1): Fix memory leak by not allocating
+ md5cksum.contents.
+
+ * accept_sec_context.c (krb5_gss_accept_sec_context): Only free
+ ap_req.data if it was allocated by kg2_parse_token(), otherwise we
+ lose very badly trying to free the middle of a potentially
+ malloc()'ed block, possibly coredumping.
+
+Thu Sep 3 19:35:44 1998 Tom Yu <tlyu@mit.edu>
+
+ * accept_sec_context.c (krb5_gss_accept_sec_context): Fix typo;
+ bash the enctype in ctx->subkey->enctype rather than just
+ "enctype", which nothing checks.
+
Fri Jul 24 21:13:53 1998 Tom Yu <tlyu@mit.edu>
* wrap_size_limit.c (krb5_gss_wrap_size_limit): Fix to round down
diff --git a/src/lib/gssapi/krb5/Makefile.in b/src/lib/gssapi/krb5/Makefile.in
index 5b74b81d9..00b575c34 100644
--- a/src/lib/gssapi/krb5/Makefile.in
+++ b/src/lib/gssapi/krb5/Makefile.in
@@ -18,6 +18,7 @@ gssapi_err_krb5.c: gssapi_err_krb5.et
SRCS = \
$(srcdir)/accept_sec_context.c \
$(srcdir)/acquire_cred.c \
+ $(srcdir)/add_cred.c \
$(srcdir)/canon_name.c \
$(srcdir)/compare_name.c \
$(srcdir)/context_time.c \
@@ -50,6 +51,7 @@ SRCS = \
$(srcdir)/unseal.c \
$(srcdir)/util_cksum.c \
$(srcdir)/util_crypt.c \
+ $(srcdir)/util_ctxsetup.c \
$(srcdir)/util_seed.c \
$(srcdir)/util_seqnum.c \
$(srcdir)/val_cred.c \
@@ -63,6 +65,7 @@ SRCS = \
OBJS = \
accept_sec_context.$(OBJEXT) \
acquire_cred.$(OBJEXT) \
+ add_cred.$(OBJEXT) \
canon_name.$(OBJEXT) \
compare_name.$(OBJEXT) \
context_time.$(OBJEXT) \
@@ -95,6 +98,7 @@ OBJS = \
unseal.$(OBJEXT) \
util_cksum.$(OBJEXT) \
util_crypt.$(OBJEXT) \
+ util_ctxsetup.$(OBJEXT) \
util_seed.$(OBJEXT) \
util_seqnum.$(OBJEXT) \
val_cred.$(OBJEXT) \
@@ -108,6 +112,7 @@ OBJS = \
STLIBOBJS = \
accept_sec_context.o \
acquire_cred.o \
+ add_cred.o \
canon_name.o \
compare_name.o \
context_time.o \
@@ -140,6 +145,7 @@ STLIBOBJS = \
unseal.o \
util_cksum.o \
util_crypt.o \
+ util_ctxsetup.o \
util_seed.o \
util_seqnum.o \
val_cred.o \
diff --git a/src/lib/gssapi/krb5/accept_sec_context.c b/src/lib/gssapi/krb5/accept_sec_context.c
index ee204d3e0..90e988ae0 100644
--- a/src/lib/gssapi/krb5/accept_sec_context.c
+++ b/src/lib/gssapi/krb5/accept_sec_context.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "k5-int.h"
#include "gssapiP_krb5.h"
#include <memory.h>
@@ -58,9 +84,8 @@ rd_req_keyproc(krb5_pointer keyprocarg, krb5_principal server,
/* Decode, decrypt and store the forwarded creds in the local ccache. */
static krb5_error_code
-rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
+rd_and_store_for_creds(context, inbuf, out_cred)
krb5_context context;
- krb5_auth_context auth_context;
krb5_data *inbuf;
krb5_gss_cred_id_t *out_cred;
{
@@ -69,10 +94,16 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
krb5_ccache ccache;
krb5_gss_cred_id_t cred = NULL;
extern krb5_cc_ops krb5_mcc_ops;
+ krb5_auth_context auth_context = NULL;
- if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
+ if ((retval = krb5_auth_con_init(context, &auth_context)))
return(retval);
+ krb5_auth_con_setflags(context, auth_context, 0);
+
+ if ((retval = krb5_rd_cred(context, auth_context, inbuf, &creds, NULL)))
+ goto cleanup;
+
/* Lots of kludging going on here... Some day the ccache interface
will be rewritten though */
@@ -91,47 +122,51 @@ rd_and_store_for_creds(context, auth_context, inbuf, out_cred)
/* generate a delegated credential handle */
if (out_cred) {
- /* allocate memory for a cred_t... */
- if (!(cred =
- (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
- retval = ENOMEM; /* out of memory? */
- goto cleanup;
- }
+ /* allocate memory for a cred_t... */
+ if (!(cred =
+ (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))) {
+ retval = ENOMEM; /* out of memory? */
+ goto cleanup;
+ }
- /* zero it out... */
- memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
+ /* zero it out... */
+ memset(cred, 0, sizeof(krb5_gss_cred_id_rec));
- /* copy the client principle into it... */
- if ((retval =
- krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
- retval = ENOMEM; /* out of memory? */
- xfree(cred); /* clean up memory on failure */
- cred = NULL;
- goto cleanup;
- }
-
- cred->usage = GSS_C_INITIATE; /* we can't accept with this */
- /* cred->princ already set */
- cred->actual_mechs = gss_mech_set_krb5_both; /* both mechs work */
- cred->prerfc_mech = cred->rfc_mech = 1; /* Ibid. */
- cred->keytab = NULL; /* no keytab associated with this... */
- cred->ccache = ccache; /* but there is a credential cache */
- cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
+ /* copy the client principle into it... */
+ if ((retval =
+ krb5_copy_principal(context, creds[0]->client, &(cred->princ)))) {
+ retval = ENOMEM; /* out of memory? */
+ xfree(cred); /* clean up memory on failure */
+ cred = NULL;
+ goto cleanup;
+ }
+
+ cred->usage = GSS_C_INITIATE; /* we can't accept with this */
+ /* cred->princ already set */
+ cred->prerfc_mech = 1; /* this cred will work with all three mechs */
+ cred->rfc_mech = 1;
+ cred->rfcv2_mech = 1;
+ cred->keytab = NULL; /* no keytab associated with this... */
+ cred->ccache = ccache; /* but there is a credential cache */
+ cred->tgt_expire = creds[0]->times.endtime; /* store the end time */
}
/* If there were errors, there might have been a memory leak
- if (!cred)
- if ((retval = krb5_cc_close(context, ccache)))
- goto cleanup;
- */
+ if (!cred)
+ if ((retval = krb5_cc_close(context, ccache)))
+ goto cleanup;
+ */
cleanup:
krb5_free_tgt_creds(context, creds);
if (!cred && ccache)
- (void)krb5_cc_close(context, ccache);
+ (void)krb5_cc_close(context, ccache);
if (out_cred)
- *out_cred = cred; /* return credential */
+ *out_cred = cred; /* return credential */
+
+ if (auth_context)
+ krb5_auth_con_free(context, auth_context);
return retval;
}
@@ -158,16 +193,17 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
unsigned char *ptr, *ptr2;
char *sptr;
long tmp;
+ size_t md5len;
int bigend;
krb5_gss_cred_id_t cred = 0;
- krb5_data ap_req;
+ krb5_data ap_rep, ap_req, mic;
int i;
krb5_error_code code;
krb5_address addr, *paddr;
krb5_authenticator *authdat = 0;
- krb5_checksum md5;
+ krb5_checksum reqcksum;
krb5_principal name = NULL;
- int gss_flags = 0;
+ krb5_ui_4 gss_flags = 0;
int decode_req_message = 0;
krb5_gss_ctx_id_rec *ctx = 0;
krb5_enctype enctype;
@@ -177,14 +213,18 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
krb5_auth_context auth_context = NULL;
krb5_ticket * ticket = NULL;
int option_id;
- krb5_data option;
- krb5_auth_context auth_context_cred = NULL;
+ krb5_data option, cksumdata;
const gss_OID_desc *mech_used = NULL;
OM_uint32 major_status = GSS_S_FAILURE;
krb5_error krb_error_data;
krb5_data scratch;
gss_cred_id_t cred_handle = NULL;
krb5_gss_cred_id_t deleg_cred = NULL;
+ int token_length;
+ int gsskrb5_vers;
+ int nctypes;
+ krb5_cksumtype *ctypes;
+ struct kg2_option fwcred;
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
@@ -196,7 +236,11 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
output_token->length = 0;
output_token->value = NULL;
token.value = 0;
- md5.contents = 0;
+ reqcksum.contents = 0;
+ mic.data = 0;
+ ap_req.data = 0;
+ ap_rep.data = 0;
+ cksumdata.data = 0;
if (mech_type)
*mech_type = GSS_C_NULL_OID;
@@ -217,18 +261,19 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
/* handle default cred handle */
if (verifier_cred_handle == GSS_C_NO_CREDENTIAL) {
- major_status = krb5_gss_acquire_cred(&code, GSS_C_NO_NAME,
- GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
- GSS_C_ACCEPT, &cred_handle,
- NULL, NULL);
- if (major_status != GSS_S_COMPLETE)
- goto fail;
- } else
- cred_handle = verifier_cred_handle;
+ major_status = krb5_gss_acquire_cred(&code, GSS_C_NO_NAME,
+ GSS_C_INDEFINITE, GSS_C_NO_OID_SET,
+ GSS_C_ACCEPT, &cred_handle,
+ NULL, NULL);
+ if (major_status != GSS_S_COMPLETE)
+ goto fail;
+ } else {
+ cred_handle = verifier_cred_handle;
+ }
- major_status = krb5_gss_validate_cred(minor_status, verifier_cred_handle);
+ major_status = krb5_gss_validate_cred(&code, verifier_cred_handle);
if (GSS_ERROR(major_status))
- goto fail;
+ goto fail;
cred = (krb5_gss_cred_id_t) cred_handle;
@@ -236,9 +281,9 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if ((cred->usage != GSS_C_ACCEPT) &&
(cred->usage != GSS_C_BOTH)) {
- code = 0;
- major_status = GSS_S_NO_CRED;
- goto fail;
+ code = 0;
+ major_status = GSS_S_NO_CRED;
+ goto fail;
}
/* verify the token's integrity, and leave the token in ap_req.
@@ -246,60 +291,92 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
ptr = (unsigned char *) input_token->value;
- if ((err = g_verify_token_header((gss_OID) gss_mech_krb5, &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length))) {
- /*
- * Previous versions of this library used the old mech_id
- * and some broken behavior (wrong IV on checksum
- * encryption). We support the old mech_id for
- * compatibility, and use it to decide when to use the
- * old behavior.
- */
- if (err != G_WRONG_MECH ||
- (code = g_verify_token_header((gss_OID) gss_mech_krb5_old,
- &(ap_req.length),
- &ptr, KG_TOK_CTX_AP_REQ,
- input_token->length))) {
- major_status = GSS_S_DEFECTIVE_TOKEN;
- goto fail;
- } else {
-#if 0 /* Don't restrict mechanisms when accepting contexts */
- if (! cred->prerfc_mech) {
- code = G_WRONG_MECH;
- major_status = GSS_S_DEFECTIVE_TOKEN;
- goto fail;
- }
-#endif
- mech_used = gss_mech_krb5_old;
- }
+ if (!(code = g_verify_token_header((gss_OID) gss_mech_krb5,
+ &(ap_req.length),
+ &ptr, KG_TOK_CTX_AP_REQ,
+ input_token->length))) {
+ if (! cred->rfc_mech) {
+ code = G_WRONG_MECH;
+ major_status = GSS_S_DEFECTIVE_TOKEN;
+ goto fail;
+ }
+ mech_used = gss_mech_krb5;
+ gsskrb5_vers = 1000;
+ } else if ((code == G_WRONG_MECH) &&
+ !(code = g_verify_token_header((gss_OID) gss_mech_krb5_old,
+ &(ap_req.length),
+ &ptr, KG_TOK_CTX_AP_REQ,
+ input_token->length))) {
+ /*
+ * Previous versions of this library used the old mech_id
+ * and some broken behavior (wrong IV on checksum
+ * encryption). We support the old mech_id for
+ * compatibility, and use it to decide when to use the
+ * old behavior.
+ */
+ if (! cred->prerfc_mech) {
+ code = G_WRONG_MECH;
+ major_status = GSS_S_DEFECTIVE_TOKEN;
+ goto fail;
+ }
+ mech_used = gss_mech_krb5_old;
+ gsskrb5_vers = 1000;
+ } else if ((code == G_WRONG_MECH) &&
+ !(code = g_verify_token_header((gss_OID) gss_mech_krb5_v2,
+ &token_length,
+ &ptr, KG2_TOK_INITIAL,
+ input_token->length))) {
+ if (! cred->rfcv2_mech) {
+ code = G_WRONG_MECH;
+ major_status = GSS_S_DEFECTIVE_TOKEN;
+ goto fail;
+ }
+ mech_used = gss_mech_krb5_v2;
+ gsskrb5_vers = 2000;
} else {
-#if 0 /* Don't restrict mechanisms when accepting contexts */
- if (! cred->rfc_mech) {
- code = G_WRONG_MECH;
- major_status = GSS_S_DEFECTIVE_TOKEN;
- goto fail;
- }
-#endif
- mech_used = gss_mech_krb5;
+ major_status = GSS_S_DEFECTIVE_TOKEN;
+ goto fail;
}
- sptr = (char *) ptr;
- TREAD_STR(sptr, ap_req.data, ap_req.length);
- decode_req_message = 1;
+ if (gsskrb5_vers == 2000) {
+ /* gss krb5 v2 */
+
+ fwcred.option_id = KRB5_GSS_FOR_CREDS_OPTION;
+ fwcred.data = NULL;
+
+ if (GSS_ERROR(major_status =
+ kg2_parse_token(&code, ptr, token_length,
+ &gss_flags, &nctypes, &ctypes,
+ delegated_cred_handle?1:0,
+ &fwcred, &ap_req, NULL))) {
+ goto fail;
+ }
+
+ gss_flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3];
+
+ gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag;
+ if there's a delegation, we'll
+ set it below */
+ } else {
+ /* gss krb5 v1 */
+
+ sptr = (char *) ptr;
+ TREAD_STR(sptr, ap_req.data, ap_req.length);
+ decode_req_message = 1;
+ }
/* construct the sender_addr */
if ((input_chan_bindings != GSS_C_NO_CHANNEL_BINDINGS) &&
(input_chan_bindings->initiator_addrtype == GSS_C_AF_INET)) {
- /* XXX is this right? */
- addr.addrtype = ADDRTYPE_INET;
- addr.length = input_chan_bindings->initiator_address.length;
- addr.contents = input_chan_bindings->initiator_address.value;
+ /* XXX is this right? */
+ addr.addrtype = ADDRTYPE_INET;
+ addr.length = input_chan_bindings->initiator_address.length;
+ addr.contents = input_chan_bindings->initiator_address.value;
- paddr = &addr;
+ paddr = &addr;
} else {
- paddr = NULL;
+ paddr = NULL;
}
/* decode the AP_REQ message */
@@ -307,13 +384,18 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
/* decode the message */
if ((code = krb5_auth_con_init(context, &auth_context))) {
- *minor_status = code;
- return(GSS_S_FAILURE);
+ major_status = GSS_S_FAILURE;
+ goto fail;
}
if ((code = krb5_auth_con_setrcache(context, auth_context, cred->rcache))) {
- *minor_status = code;
- return(GSS_S_FAILURE);
+ major_status = GSS_S_FAILURE;
+ goto fail;
}
+ if ((code = krb5_auth_con_setaddrs(context, auth_context, NULL, paddr))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
if ((code = krb5_rd_req(context, &auth_context, &ap_req, cred->princ,
cred->keytab, NULL, &ticket))) {
major_status = GSS_S_FAILURE;
@@ -328,137 +410,142 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if ((authdat->authenticator->subkey == NULL) ||
(authdat->ticket->enc_part2 == NULL)) {
code = KG_NO_SUBKEY;
+ major_status = GSS_S_FAILURE;
goto fail;
}
#endif
- /* verify that the checksum is correct */
+ if (gsskrb5_vers == 2000) {
+ bigend = 1;
+ } else {
+ /* gss krb5 v1 */
- /*
- The checksum may be either exactly 24 bytes, in which case
- no options are specified, or greater than 24 bytes, in which case
- one or more options are specified. Currently, the only valid
- option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
- */
-
- if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
- (authdat->checksum->length < 24)) {
- code = 0;
- major_status = GSS_S_BAD_BINDINGS;
+ /* stash this now, for later. */
+ if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5,
+ &md5len)) {
+ major_status = GSS_S_FAILURE;
goto fail;
- }
+ }
- /*
- "Be liberal in what you accept, and
- conservative in what you send"
- -- rfc1123
+ /* verify that the checksum is correct */
- This code will let this acceptor interoperate with an initiator
- using little-endian or big-endian integer encoding.
- */
+ /*
+ The checksum may be either exactly 24 bytes, in which case
+ no options are specified, or greater than 24 bytes, in which case
+ one or more options are specified. Currently, the only valid
+ option is KRB5_GSS_FOR_CREDS_OPTION ( = 1 ).
+ */
+
+ if ((authdat->checksum->checksum_type != CKSUMTYPE_KG_CB) ||
+ (authdat->checksum->length < 24)) {
+ code = 0;
+ major_status = GSS_S_BAD_BINDINGS;
+ goto fail;
+ }
- ptr = (unsigned char *) authdat->checksum->contents;
- bigend = 0;
+ /*
+ "Be liberal in what you accept, and
+ conservative in what you send"
+ -- rfc1123
- TREAD_INT(ptr, tmp, bigend);
+ This code will let this acceptor interoperate with an initiator
+ using little-endian or big-endian integer encoding.
+ */
- if (tmp != krb5_checksum_size(context, CKSUMTYPE_RSA_MD5)) {
ptr = (unsigned char *) authdat->checksum->contents;
- bigend = 1;
+ bigend = 0;
TREAD_INT(ptr, tmp, bigend);
- if (tmp != krb5_checksum_size(context, CKSUMTYPE_RSA_MD5)) {
- major_status = GSS_S_FAILURE;
- code = KG_BAD_LENGTH;
- goto fail;
+ if (tmp != md5len) {
+ ptr = (unsigned char *) authdat->checksum->contents;
+ bigend = 1;
+
+ TREAD_INT(ptr, tmp, bigend);
+
+ if (tmp != md5len) {
+ code = KG_BAD_LENGTH;
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
}
- }
- /* at this point, bigend is set according to the initiator's byte order */
+ /* at this point, bigend is set according to the initiator's
+ byte order */
- if ((code = kg_checksum_channel_bindings(context, input_chan_bindings, &md5,
- bigend))) {
- major_status = GSS_S_BAD_BINDINGS;
- goto fail;
- }
+ if ((code = kg_checksum_channel_bindings(context, input_chan_bindings,
+ &reqcksum, bigend))) {
+ major_status = GSS_S_BAD_BINDINGS;
+ goto fail;
+ }
- TREAD_STR(ptr, ptr2, md5.length);
- if (memcmp(ptr2, md5.contents, md5.length) != 0) {
+ TREAD_STR(ptr, ptr2, reqcksum.length);
+ if (memcmp(ptr2, reqcksum.contents, reqcksum.length) != 0) {
code = 0;
major_status = GSS_S_BAD_BINDINGS;
goto fail;
- }
-
- xfree(md5.contents);
- md5.contents = 0;
-
- TREAD_INT(ptr, gss_flags, bigend);
- gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; if there's
- a delegation, we'll set it below */
- decode_req_message = 0;
-
- /* if the checksum length > 24, there are options to process */
+ }
- if(authdat->checksum->length > 24) {
+ xfree(reqcksum.contents);
+ reqcksum.contents = 0;
- i = authdat->checksum->length - 24;
+ TREAD_INT(ptr, gss_flags, bigend);
+ gss_flags &= ~GSS_C_DELEG_FLAG; /* mask out the delegation flag; if
+ there's a delegation, we'll set
+ it below */
+ decode_req_message = 0;
- while(i>0) {
+ /* if the checksum length > 24, there are options to process */
- TREAD_INT16(ptr, option_id, bigend);
+ if(authdat->checksum->length > 24) {
- switch(option_id) {
+ i = authdat->checksum->length - 24;
- case KRB5_GSS_FOR_CREDS_OPTION:
+ while(i>0) {
- TREAD_INT16(ptr, option.length, bigend);
+ TREAD_INT16(ptr, option_id, bigend);
- /* have to use ptr2, since option.data is wrong type and
- macro uses ptr as both lvalue and rvalue */
+ switch(option_id) {
- TREAD_STR(ptr, ptr2, bigend);
- option.data = (char FAR *) ptr2;
+ case KRB5_GSS_FOR_CREDS_OPTION:
- /* get a temporary auth_context structure for the
- call to rd_and_store_for_creds() and clear its flags */
+ TREAD_INT16(ptr, option.length, bigend);
- if ((code = krb5_auth_con_init(context,
- &auth_context_cred))) {
- major_status = GSS_S_FAILURE;
- goto fail;
- }
+ /* have to use ptr2, since option.data is wrong type and
+ macro uses ptr as both lvalue and rvalue */
- krb5_auth_con_setflags(context, auth_context_cred, 0);
+ TREAD_STR(ptr, ptr2, bigend);
+ option.data = (char FAR *) ptr2;
- /* store the delegated credential */
+ /* store the delegated credential */
- rd_and_store_for_creds(context, auth_context_cred,
- &option,
- (delegated_cred_handle) ?
- &deleg_cred : NULL);
+ if (code = rd_and_store_for_creds(context, &option,
+ (delegated_cred_handle) ?
+ &deleg_cred : NULL)) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
- i -= option.length + 4;
+ i -= option.length + 4;
- krb5_auth_con_free(context, auth_context_cred);
+ gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */
- gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */
+ break;
- break;
+ /* default: */
+ /* unknown options aren't an error */
- /* default: */
- /* unknown options aren't an error */
+ } /* switch */
+ } /* while */
+ } /* if */
+ }
- } /* switch */
- } /* while */
- } /* if */
-
/* create the ctx struct and start filling it in */
if ((ctx = (krb5_gss_ctx_id_rec *) xmalloc(sizeof(krb5_gss_ctx_id_rec)))
== NULL) {
- major_status = GSS_S_FAILURE;
code = ENOMEM;
+ major_status = GSS_S_FAILURE;
goto fail;
}
@@ -469,83 +556,177 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
ctx->gss_flags = KG_IMPLFLAGS(gss_flags);
ctx->seed_init = 0;
ctx->big_endian = bigend;
-
- major_status = GSS_S_FAILURE;
+ ctx->gsskrb5_version = gsskrb5_vers;
/* Intern the ctx pointer so that delete_sec_context works */
if (! kg_save_ctx_id((gss_ctx_id_t) ctx)) {
- code = G_VALIDATE_FAILED;
- xfree(ctx);
- ctx = 0;
- goto fail;
+ xfree(ctx);
+ ctx = 0;
+
+ code = G_VALIDATE_FAILED;
+ major_status = GSS_S_FAILURE;
+ goto fail;
}
-
- if ((code = krb5_copy_principal(context, cred->princ, &ctx->here)))
- goto fail;
- if ((code = krb5_copy_principal(context, authdat->client, &ctx->there)))
- goto fail;
+ if ((code = krb5_copy_principal(context, cred->princ, &ctx->here))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
- /* done with authdat */
- krb5_free_authenticator(context, authdat);
- authdat = 0;
+ if ((code = krb5_copy_principal(context, authdat->client, &ctx->there))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
if ((code = krb5_auth_con_getremotesubkey(context, auth_context,
- &ctx->subkey)))
- goto fail;
+ &ctx->subkey))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
/* use the session key if the subkey isn't present */
if (ctx->subkey == NULL) {
if ((code = krb5_auth_con_getkey(context, auth_context,
- &ctx->subkey)))
- goto fail;
+ &ctx->subkey))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
}
if (ctx->subkey == NULL) {
/* this isn't a very good error, but it's not clear to me this
can actually happen */
+ major_status = GSS_S_FAILURE;
code = KRB5KDC_ERR_NULL_KEY;
goto fail;
}
- switch(ctx->subkey->enctype) {
- case ENCTYPE_DES_CBC_MD5:
- case ENCTYPE_DES_CBC_CRC:
- enctype = ENCTYPE_DES_CBC_RAW;
- ctx->signalg = 0;
- ctx->cksum_size = 8;
- ctx->sealalg = 0;
- break;
+ if (gsskrb5_vers == 2000) {
+ int cblen;
+ krb5_boolean valid;
+
+ /* intersect the token ctypes with the local ctypes */
+
+ if (code = krb5_c_keyed_checksum_types(context, ctx->subkey->enctype,
+ &ctx->nctypes, &ctx->ctypes))
+ goto fail;
+
+ if (nctypes == 0) {
+ code = KRB5_CRYPTO_INTERNAL;
+ goto fail;
+ }
+
+ kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes);
+
+ if (nctypes == 0) {
+ code = KG_NO_CTYPES;
+ goto fail;
+ }
+
+ /* process the delegated cred, if any */
+
+ if (fwcred.data) {
+ krb5_data option;
+
+ option.length = fwcred.length;
+ option.data = fwcred.data;
+
+ if (code = rd_and_store_for_creds(context, &option, &deleg_cred)) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
+ gss_flags |= GSS_C_DELEG_FLAG; /* got a delegation */
+ }
+
+ /* construct the checksum buffer */
+
+ cblen = 4*5;
+ if (input_chan_bindings)
+ cblen += (input_chan_bindings->initiator_address.length+
+ input_chan_bindings->acceptor_address.length+
+ input_chan_bindings->application_data.length);
+
+ cksumdata.length = cblen + ((char *)(ap_req.data-2) - (char *)(ptr-2));
+
+ if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) {
+ code = ENOMEM;
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
+ ptr2 = cksumdata.data;
+
+ if (input_chan_bindings) {
+ TWRITE_INT(ptr2, input_chan_bindings->initiator_addrtype, 1);
+ TWRITE_BUF(ptr2, input_chan_bindings->initiator_address, 1);
+ TWRITE_INT(ptr2, input_chan_bindings->acceptor_addrtype, 1);
+ TWRITE_BUF(ptr2, input_chan_bindings->acceptor_address, 1);
+ TWRITE_BUF(ptr2, input_chan_bindings->application_data, 1);
+ } else {
+ memset(ptr2, 0, cblen);
+ ptr2 += cblen;
+ }
+
+ memcpy(ptr2, ptr-2, ((char *)(ap_req.data-2) - (char *)(ptr-2)));
+
+ if (code = krb5_c_verify_checksum(context, ctx->subkey,
+ KRB5_KEYUSAGE_AP_REQ_AUTH_CKSUM,
+ &cksumdata, authdat->checksum,
+ &valid)) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
+ free(cksumdata.data);
+ cksumdata.data = 0;
+
+ if (!valid) {
+ code = 0;
+ major_status = GSS_S_BAD_SIG;
+ goto fail;
+ }
+ } else {
+ /* gss krb5 v1 */
+
+ switch(ctx->subkey->enctype) {
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+ ctx->signalg = 0;
+ ctx->cksum_size = 8;
+ ctx->sealalg = 0;
+ break;
#if 0
- case ENCTYPE_DES3_CBC_MD5:
- enctype = ENCTYPE_DES3_CBC_RAW;
- ctx->signalg = 3;
- ctx->cksum_size = 16;
- ctx->sealalg = 1;
- break;
+ case ENCTYPE_DES3_CBC_MD5:
+ enctype = ENCTYPE_DES3_CBC_RAW;
+ ctx->signalg = 3;
+ ctx->cksum_size = 16;
+ ctx->sealalg = 1;
+ break;
#endif
- default:
- code = KRB5_BAD_ENCTYPE;
- goto fail;
- }
-
- /* fill in the encryption descriptors */
+ default:
+ code = KRB5_BAD_ENCTYPE;
+ goto fail;
+ }
- krb5_use_enctype(context, &ctx->enc.eblock, enctype);
- ctx->enc.processed = 0;
+ /* fill in the encryption descriptors */
- if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
+ if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc))) {
+ major_status = GSS_S_FAILURE;
goto fail;
+ }
- for (i=0; i<ctx->enc.key->length; i++)
- /*SUPPRESS 113*/
- ctx->enc.key->contents[i] ^= 0xf0;
+ for (i=0; i<ctx->enc->length; i++)
+ /*SUPPRESS 113*/
+ ctx->enc->contents[i] ^= 0xf0;
- krb5_use_enctype(context, &ctx->seq.eblock, enctype);
- ctx->seq.processed = 0;
- if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
+ if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq))) {
+ major_status = GSS_S_FAILURE;
goto fail;
+ }
+ }
ctx->endtime = ticket->enc_part2->times.endtime;
ctx->krb_flags = ticket->enc_part2->flags;
@@ -554,13 +735,15 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
krb5_auth_con_getremoteseqnumber(context, auth_context, &ctx->seq_recv);
- if ((code = krb5_timeofday(context, &now)))
- goto fail;
+ if ((code = krb5_timeofday(context, &now))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
if (ctx->endtime < now) {
- code = 0;
- major_status = GSS_S_CREDENTIALS_EXPIRED;
- goto fail;
+ code = 0;
+ major_status = GSS_S_CREDENTIALS_EXPIRED;
+ goto fail;
}
g_order_init(&(ctx->seqstate), ctx->seq_recv,
@@ -573,40 +756,156 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
/* generate an AP_REP if necessary */
if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
- krb5_data ap_rep;
- unsigned char * ptr;
- if ((code = krb5_mk_rep(context, auth_context, &ap_rep)))
- goto fail;
-
- krb5_auth_con_getlocalseqnumber(context, auth_context, &ctx->seq_send);
- token.length = g_token_size((gss_OID) mech_used, ap_rep.length);
-
- if ((token.value = (unsigned char *) xmalloc(token.length)) == NULL) {
- code = ENOMEM;
- goto fail;
- }
- ptr = token.value;
- g_make_token_header((gss_OID) mech_used, ap_rep.length,
- &ptr, KG_TOK_CTX_AP_REP);
-
- TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
- xfree(ap_rep.data);
+ unsigned char * ptr;
+ if ((code = krb5_mk_rep(context, auth_context, &ap_rep))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
+ krb5_auth_con_getlocalseqnumber(context, auth_context,
+ &ctx->seq_send);
+
+ /* the reply token hasn't been sent yet, but that's ok. */
+ ctx->established = 1;
+
+ if (ctx->gsskrb5_version == 2000) {
+ krb5_ui_4 tok_flags;
+
+ tok_flags =
+ (ctx->gss_flags & GSS_C_DELEG_FLAG)?KG2_RESP_FLAG_DELEG_OK:0;
+
+ cksumdata.length = 8 + 4*ctx->nctypes + 4;
+
+ if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL) {
+ code = ENOMEM;
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+
+ /* construct the token fields */
+
+ ptr = cksumdata.data;
+
+ ptr[0] = (KG2_TOK_RESPONSE >> 8) & 0xff;
+ ptr[1] = KG2_TOK_RESPONSE & 0xff;
+
+ ptr[2] = (tok_flags >> 24) & 0xff;
+ ptr[3] = (tok_flags >> 16) & 0xff;
+ ptr[4] = (tok_flags >> 8) & 0xff;
+ ptr[5] = tok_flags & 0xff;
+
+ ptr[6] = (ctx->nctypes >> 8) & 0xff;
+ ptr[7] = ctx->nctypes & 0xff;
+
+ ptr += 8;
+
+ for (i=0; i<ctx->nctypes; i++) {
+ ptr[i] = (ctx->ctypes[i] >> 24) & 0xff;
+ ptr[i+1] = (ctx->ctypes[i] >> 16) & 0xff;
+ ptr[i+2] = (ctx->ctypes[i] >> 8) & 0xff;
+ ptr[i+3] = ctx->ctypes[i] & 0xff;
+
+ ptr += 4;
+ }
+
+ memset(ptr, 0, 4);
+
+ /* make the MIC token */
+
+ {
+ gss_buffer_desc text, token;
+
+ text.length = cksumdata.length;
+ text.value = cksumdata.data;
+
+ /* ctx->seq_send must be set before this call */
+
+ if (GSS_ERROR(major_status =
+ krb5_gss_get_mic(&code, ctx,
+ GSS_C_QOP_DEFAULT,
+ &text, &token)))
+ goto fail;
+
+ mic.length = token.length;
+ mic.data = token.value;
+ }
+
+ token.length = g_token_size((gss_OID) mech_used,
+ (cksumdata.length-2)+4+ap_rep.length+
+ mic.length);
+
+ if ((token.value = (unsigned char *) xmalloc(token.length))
+ == NULL) {
+ code = ENOMEM;
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+ ptr = token.value;
+ g_make_token_header((gss_OID) mech_used,
+ (cksumdata.length-2)+4+ap_rep.length+mic.length,
+ &ptr, KG2_TOK_RESPONSE);
+
+ memcpy(ptr, cksumdata.data+2, cksumdata.length-2);
+ ptr += cksumdata.length-2;
+
+ ptr[0] = (ap_rep.length >> 8) & 0xff;
+ ptr[1] = ap_rep.length & 0xff;
+ memcpy(ptr+2, ap_rep.data, ap_rep.length);
+
+ ptr += (2+ap_rep.length);
+
+ ptr[0] = (mic.length >> 8) & 0xff;
+ ptr[1] = mic.length & 0xff;
+ memcpy(ptr+2, mic.data, mic.length);
+
+ ptr += (2+mic.length);
+
+ free(cksumdata.data);
+ cksumdata.data = 0;
+
+ /* gss krb5 v2 */
+ } else {
+ /* gss krb5 v1 */
+
+ token.length = g_token_size((gss_OID) mech_used, ap_rep.length);
+
+ if ((token.value = (unsigned char *) xmalloc(token.length))
+ == NULL) {
+ major_status = GSS_S_FAILURE;
+ code = ENOMEM;
+ goto fail;
+ }
+ ptr = token.value;
+ g_make_token_header((gss_OID) mech_used, ap_rep.length,
+ &ptr, KG_TOK_CTX_AP_REP);
+
+ TWRITE_STR(ptr, ap_rep.data, ap_rep.length);
+ xfree(ap_rep.data);
+
+ ctx->established = 1;
+
+ }
} else {
- token.length = 0;
- token.value = NULL;
- ctx->seq_send = ctx->seq_recv;
+ token.length = 0;
+ token.value = NULL;
+ ctx->seq_send = ctx->seq_recv;
+
+ ctx->established = 1;
}
/* set the return arguments */
if (src_name) {
- if ((code = krb5_copy_principal(context, ctx->there, &name)))
- goto fail;
- /* intern the src_name */
- if (! kg_save_name((gss_name_t) name)) {
- code = G_VALIDATE_FAILED;
- goto fail;
- }
+ if ((code = krb5_copy_principal(context, ctx->there, &name))) {
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
+ /* intern the src_name */
+ if (! kg_save_name((gss_name_t) name)) {
+ code = G_VALIDATE_FAILED;
+ major_status = GSS_S_FAILURE;
+ goto fail;
+ }
}
if (mech_type)
@@ -618,7 +917,6 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
if (ret_flags)
*ret_flags = ctx->gss_flags;
- ctx->established = 1;
*context_handle = ctx;
*output_token = token;
@@ -626,39 +924,54 @@ krb5_gss_accept_sec_context(minor_status, context_handle,
*src_name = (gss_name_t) name;
if (delegated_cred_handle && deleg_cred) {
- if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
- code = G_VALIDATE_FAILED;
- goto fail;
- }
+ if (!kg_save_cred_id((gss_cred_id_t) deleg_cred)) {
+ major_status = GSS_S_FAILURE;
+ code = G_VALIDATE_FAILED;
+ goto fail;
+ }
- *delegated_cred_handle = (gss_cred_id_t) deleg_cred;
+ *delegated_cred_handle = (gss_cred_id_t) deleg_cred;
}
/* finally! */
*minor_status = 0;
- return(GSS_S_COMPLETE);
+ major_status = GSS_S_COMPLETE;
-fail:
+ fail:
+ if (ctypes)
+ free(ctypes);
if (authdat)
- krb5_free_authenticator(context, authdat);
+ krb5_free_authenticator(context, authdat);
+ if (reqcksum.contents)
+ xfree(reqcksum.contents);
+ if (ap_rep.data)
+ xfree(ap_rep.data);
+ if (mic.data)
+ xfree(mic.data);
+ if (cksumdata.data)
+ xfree(cksumdata.data);
+
+ if (!GSS_ERROR(major_status))
+ return(major_status);
+
+ /* from here on is the real "fail" code */
+
if (ctx)
- (void) krb5_gss_delete_sec_context(minor_status,
- (gss_ctx_id_t *) &ctx, NULL);
+ (void) krb5_gss_delete_sec_context(minor_status,
+ (gss_ctx_id_t *) &ctx, NULL);
+ if (deleg_cred) { /* free memory associated with the deleg credential */
+ if (deleg_cred->ccache)
+ (void)krb5_cc_close(context, deleg_cred->ccache);
+ if (deleg_cred->princ)
+ krb5_free_principal(context, deleg_cred->princ);
+ xfree(deleg_cred);
+ }
if (token.value)
- xfree(token.value);
+ xfree(token.value);
if (name) {
- (void) kg_delete_name((gss_name_t) name);
- krb5_free_principal(context, name);
- }
- if (md5.contents)
- xfree(md5.contents);
- if (deleg_cred) { /* free memory associated with the deleg credential */
- if (deleg_cred->ccache)
- (void)krb5_cc_close(context, deleg_cred->ccache);
- if (deleg_cred->princ)
- krb5_free_principal(context, deleg_cred->princ);
- xfree(deleg_cred);
+ (void) kg_delete_name((gss_name_t) name);
+ krb5_free_principal(context, name);
}
*minor_status = code;
@@ -670,48 +983,75 @@ fail:
* decode the authenticator to read out the gss_flags field.
*/
if (decode_req_message) {
- krb5_ap_req * request;
+ krb5_ap_req * request;
- if (decode_krb5_ap_req(&ap_req, &request))
- return (major_status);
- if (request->ap_options & AP_OPTS_MUTUAL_REQUIRED)
- gss_flags |= GSS_C_MUTUAL_FLAG;
- krb5_free_ap_req(context, request);
+ if (decode_krb5_ap_req(&ap_req, &request))
+ return (major_status);
+ if (request->ap_options & AP_OPTS_MUTUAL_REQUIRED)
+ gss_flags |= GSS_C_MUTUAL_FLAG;
+ krb5_free_ap_req(context, request);
}
if (cred && (gss_flags & GSS_C_MUTUAL_FLAG)) {
- /*
- * The client is expecting a response, so we can send an
- * error token back
- */
- memset(&krb_error_data, 0, sizeof(krb_error_data));
-
- code -= ERROR_TABLE_BASE_krb5;
- if (code < 0 || code > 128)
- code = 60 /* KRB_ERR_GENERIC */;
-
- krb_error_data.error = code;
- (void) krb5_us_timeofday(context, &krb_error_data.stime,
- &krb_error_data.susec);
- krb_error_data.server = cred->princ;
+ int tmsglen, toktype;
+
+ /*
+ * The client is expecting a response, so we can send an
+ * error token back
+ */
+ memset(&krb_error_data, 0, sizeof(krb_error_data));
+
+ code -= ERROR_TABLE_BASE_krb5;
+ if (code < 0 || code > 128)
+ code = 60 /* KRB_ERR_GENERIC */;
+
+ krb_error_data.error = code;
+ (void) krb5_us_timeofday(context, &krb_error_data.stime,
+ &krb_error_data.susec);
+ krb_error_data.server = cred->princ;
- code = krb5_mk_error(context, &krb_error_data, &scratch);
- if (code)
- return (major_status);
+ code = krb5_mk_error(context, &krb_error_data, &scratch);
+ if (code)
+ return (major_status);
+
+ if (gsskrb5_vers == 2000) {
+ tmsglen = 12+scratch.length;
+ toktype = KG2_TOK_RESPONSE;
+ } else {
+ tmsglen = scratch.length;
+ toktype = KG_TOK_CTX_ERROR;
+ }
- token.length = g_token_size((gss_OID) mech_used, scratch.length);
- token.value = (unsigned char *) xmalloc(token.length);
- if (!token.value)
- return (major_status);
+ token.length = g_token_size((gss_OID) mech_used, tmsglen);
+ token.value = (unsigned char *) xmalloc(token.length);
+ if (!token.value)
+ return (major_status);
- ptr = token.value;
- g_make_token_header((gss_OID) mech_used, scratch.length,
- &ptr, KG_TOK_CTX_ERROR);
+ ptr = token.value;
+ g_make_token_header((gss_OID) mech_used, tmsglen, &ptr, toktype);
+
+ if (gsskrb5_vers == 2000) {
+ krb5_ui_4 flags;
+
+ flags = KG2_RESP_FLAG_ERROR;
+
+ ptr[0] = (flags << 24) & 0xff;
+ ptr[1] = (flags << 16) & 0xff;
+ ptr[2] = (flags << 8) & 0xff;
+ ptr[3] = flags & 0xff;
+
+ memset(ptr+4, 0, 6);
+
+ ptr[10] = (scratch.length << 8) & 0xff;
+ ptr[11] = scratch.length & 0xff;
+
+ ptr += 12;
+ }
- TWRITE_STR(ptr, scratch.data, scratch.length);
- xfree(scratch.data);
+ TWRITE_STR(ptr, scratch.data, scratch.length);
+ xfree(scratch.data);
- *output_token = token;
+ *output_token = token;
}
if (!verifier_cred_handle && cred_handle) {
krb5_gss_release_cred(&code, cred_handle);
diff --git a/src/lib/gssapi/krb5/acquire_cred.c b/src/lib/gssapi/krb5/acquire_cred.c
index 1ca1bf31a..f968b7d4f 100644
--- a/src/lib/gssapi/krb5/acquire_cred.c
+++ b/src/lib/gssapi/krb5/acquire_cred.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "gssapiP_krb5.h"
#ifdef HAVE_STRING_H
#include <string.h>
@@ -248,8 +274,7 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
size_t i;
krb5_gss_cred_id_t cred;
gss_OID_set ret_mechs;
- const gss_OID_set_desc FAR * valid_mechs;
- int req_old, req_new;
+ int req_old, req_new, req_v2;
OM_uint32 ret;
krb5_error_code code;
@@ -277,27 +302,24 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
contains krb5 */
if (desired_mechs == GSS_C_NULL_OID_SET) {
- valid_mechs = gss_mech_set_krb5_both;
req_old = 1;
req_new = 1;
+ req_v2 = 1;
} else {
req_old = 0;
req_new = 0;
+ req_v2 = 0;
for (i=0; i<desired_mechs->count; i++) {
if (g_OID_equal(gss_mech_krb5_old, &(desired_mechs->elements[i])))
req_old++;
if (g_OID_equal(gss_mech_krb5, &(desired_mechs->elements[i])))
req_new++;
+ if (g_OID_equal(gss_mech_krb5_v2, &(desired_mechs->elements[i])))
+ req_v2++;
}
- if (req_old && req_new) {
- valid_mechs = gss_mech_set_krb5_both;
- } else if (req_old) {
- valid_mechs = gss_mech_set_krb5_old;
- } else if (req_new) {
- valid_mechs = gss_mech_set_krb5;
- } else {
+ if (!req_old && !req_new && !req_v2) {
*minor_status = 0;
return(GSS_S_BAD_MECH);
}
@@ -314,9 +336,9 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
cred->usage = cred_usage;
cred->princ = NULL;
- cred->actual_mechs = valid_mechs;
cred->prerfc_mech = req_old;
cred->rfc_mech = req_new;
+ cred->rfcv2_mech = req_v2;
cred->keytab = NULL;
cred->ccache = NULL;
@@ -407,17 +429,30 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
/* create mechs */
if (actual_mechs) {
- if (! g_copy_OID_set(cred->actual_mechs, &ret_mechs)) {
- if (cred->ccache)
- (void)krb5_cc_close(context, cred->ccache);
- if (cred->keytab)
- (void)krb5_kt_close(context, cred->keytab);
- if (cred->princ)
- krb5_free_principal(context, cred->princ);
- xfree(cred);
- *minor_status = ENOMEM;
- return(GSS_S_FAILURE);
- }
+ if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status,
+ &ret_mechs)) ||
+ (cred->prerfc_mech &&
+ GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+ gss_mech_krb5_old,
+ &ret_mechs))) ||
+ (cred->rfc_mech &&
+ GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+ gss_mech_krb5,
+ &ret_mechs))) ||
+ (cred->rfcv2_mech &&
+ GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+ gss_mech_krb5_v2,
+ &ret_mechs)))) {
+ if (cred->ccache)
+ (void)krb5_cc_close(context, cred->ccache);
+ if (cred->keytab)
+ (void)krb5_kt_close(context, cred->keytab);
+ if (cred->princ)
+ krb5_free_principal(context, cred->princ);
+ xfree(cred);
+ /* *minor_status set above */
+ return(ret);
+ }
}
/* intern the credential handle */
@@ -445,39 +480,3 @@ krb5_gss_acquire_cred(minor_status, desired_name, time_req,
return(GSS_S_COMPLETE);
}
-
-/* V2 interface */
-OM_uint32
-krb5_gss_add_cred(minor_status, input_cred_handle,
- desired_name, desired_mech, cred_usage,
- initiator_time_req, acceptor_time_req,
- output_cred_handle, actual_mechs,
- initiator_time_rec, acceptor_time_rec)
- OM_uint32 *minor_status;
- gss_cred_id_t input_cred_handle;
- gss_name_t desired_name;
- gss_OID desired_mech;
- gss_cred_usage_t cred_usage;
- OM_uint32 initiator_time_req;
- OM_uint32 acceptor_time_req;
- gss_cred_id_t *output_cred_handle;
- gss_OID_set *actual_mechs;
- OM_uint32 *initiator_time_rec;
- OM_uint32 *acceptor_time_rec;
-{
- /*
- * This does not apply to our single-mechanism implementation. Decide
- * if the correct error is BAD_MECH or DUPLICATE_ELEMENT.
- */
-
- /* verify that the requested mechanism is the default, or
- is krb5 */
-
- if ((desired_mech != GSS_C_NULL_OID) &&
- (g_OID_equal(desired_mech, gss_mech_krb5)))
- return(GSS_S_BAD_MECH);
-
- *minor_status = 0;
- return(GSS_S_DUPLICATE_ELEMENT);
-}
-
diff --git a/src/lib/gssapi/krb5/add_cred.c b/src/lib/gssapi/krb5/add_cred.c
new file mode 100644
index 000000000..2a6fdb47b
--- /dev/null
+++ b/src/lib/gssapi/krb5/add_cred.c
@@ -0,0 +1,309 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "gssapiP_krb5.h"
+#ifdef HAVE_STRING_H
+#include <string.h>
+#else
+#include <strings.h>
+#endif
+
+/*
+ * $Id$
+ */
+
+/* V2 interface */
+OM_uint32
+krb5_gss_add_cred(minor_status, input_cred_handle,
+ desired_name, desired_mech, cred_usage,
+ initiator_time_req, acceptor_time_req,
+ output_cred_handle, actual_mechs,
+ initiator_time_rec, acceptor_time_rec)
+ OM_uint32 *minor_status;
+ gss_cred_id_t input_cred_handle;
+ gss_name_t desired_name;
+ gss_OID desired_mech;
+ gss_cred_usage_t cred_usage;
+ OM_uint32 initiator_time_req;
+ OM_uint32 acceptor_time_req;
+ gss_cred_id_t *output_cred_handle;
+ gss_OID_set *actual_mechs;
+ OM_uint32 *initiator_time_rec;
+ OM_uint32 *acceptor_time_rec;
+{
+ krb5_context context;
+ OM_uint32 major_status, lifetime;
+ krb5_gss_cred_id_t cred;
+ krb5_error_code code;
+
+ /* this is pretty simple, since there's not really any difference
+ between the underlying mechanisms. The main hair is in copying
+ a mechanism if requested. */
+
+ /* check if the desired_mech is bogus */
+
+ if (!g_OID_equal(desired_mech, gss_mech_krb5_v2) &&
+ !g_OID_equal(desired_mech, gss_mech_krb5) &&
+ !g_OID_equal(desired_mech, gss_mech_krb5_old)) {
+ *minor_status = 0;
+ return(GSS_S_BAD_MECH);
+ }
+
+ /* check if the desired_mech is bogus */
+
+ if ((cred_usage != GSS_C_INITIATE) &&
+ (cred_usage != GSS_C_ACCEPT) &&
+ (cred_usage != GSS_C_BOTH)) {
+ *minor_status = (OM_uint32) G_BAD_USAGE;
+ return(GSS_S_FAILURE);
+ }
+
+ /* since the default credential includes all the mechanisms,
+ return an error for that case. */
+
+ /*SUPPRESS 29*/
+ if (input_cred_handle == GSS_C_NO_CREDENTIAL) {
+ *minor_status = 0;
+ return(GSS_S_DUPLICATE_ELEMENT);
+ }
+
+ /* verify the credential */
+ if (GSS_ERROR(major_status =
+ krb5_gss_validate_cred(minor_status, input_cred_handle)))
+ return(major_status);
+
+ cred = (krb5_gss_cred_id_t) input_cred_handle;
+
+ /* check if the cred_usage is equal or "less" than the passed-in cred
+ if copying */
+
+ if (!((cred->usage == cred_usage) ||
+ ((cred->usage == GSS_C_BOTH) &&
+ (output_cred_handle != NULL)))) {
+ *minor_status = (OM_uint32) G_BAD_USAGE;
+ return(GSS_S_FAILURE);
+ }
+
+ /* check that desired_mech isn't already in the credential */
+
+ if ((g_OID_equal(desired_mech, gss_mech_krb5_old) && cred->prerfc_mech) ||
+ (g_OID_equal(desired_mech, gss_mech_krb5) && cred->rfc_mech) ||
+ (g_OID_equal(desired_mech, gss_mech_krb5_v2) && cred->rfcv2_mech)) {
+ *minor_status = 0;
+ return(GSS_S_DUPLICATE_ELEMENT);
+ }
+
+ if (GSS_ERROR(kg_get_context(minor_status, &context)))
+ return(GSS_S_FAILURE);
+
+ /* verify the desired_name */
+
+ /*SUPPRESS 29*/
+ if ((desired_name != (gss_name_t) NULL) &&
+ (! kg_validate_name(desired_name))) {
+ *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ return(GSS_S_CALL_BAD_STRUCTURE|GSS_S_BAD_NAME);
+ }
+
+ /* make sure the desired_name is the same as the existing one */
+
+ if (desired_name &&
+ !krb5_principal_compare(context, (krb5_principal) desired_name,
+ cred->princ)) {
+ *minor_status = 0;
+ return(GSS_S_BAD_NAME);
+ }
+
+ /* copy the cred if necessary */
+
+ if (output_cred_handle) {
+ /* make a copy */
+ krb5_gss_cred_id_t new_cred;
+ char *kttype, ktboth[1024];
+ char *cctype, *ccname, ccboth[1024];
+
+ if ((new_cred =
+ (krb5_gss_cred_id_t) xmalloc(sizeof(krb5_gss_cred_id_rec)))
+ == NULL) {
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+ memset(new_cred, 0, sizeof(krb5_gss_cred_id_rec));
+
+ new_cred->usage = cred_usage;
+ new_cred->prerfc_mech = cred->prerfc_mech;
+ new_cred->rfc_mech = cred->rfc_mech;
+ new_cred->rfcv2_mech = cred->rfcv2_mech;
+ new_cred->tgt_expire = cred->tgt_expire;
+
+ if (code = krb5_copy_principal(context, cred->princ,
+ &new_cred->princ)) {
+ free(new_cred);
+
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (cred->keytab) {
+ kttype = krb5_kt_get_type(context, cred->keytab);
+ if ((strlen(kttype)+2) > sizeof(ktboth)) {
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ strcpy(ktboth, kttype);
+ strcat(ktboth, ":");
+
+ if (code = krb5_kt_get_name(context, cred->keytab,
+ ktboth+strlen(ktboth),
+ sizeof(ktboth)-strlen(ktboth))) {
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (code = krb5_kt_resolve(context, ktboth, &new_cred->keytab)) {
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+ } else {
+ new_cred->keytab = NULL;
+ }
+
+ if (cred->rcache) {
+ /* Open the replay cache for this principal. */
+ if ((code = krb5_get_server_rcache(context,
+ krb5_princ_component(context, cred->princ, 0),
+ &new_cred->rcache))) {
+ if (new_cred->keytab)
+ krb5_kt_close(context, new_cred->keytab);
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+ } else {
+ new_cred->rcache = NULL;
+ }
+
+ if (cred->ccache) {
+ cctype = krb5_cc_get_type(context, cred->ccache);
+ ccname = krb5_cc_get_name(context, cred->ccache);
+
+ if ((strlen(cctype)+strlen(ccname)+2) > sizeof(ccboth)) {
+ if (new_cred->rcache)
+ krb5_rc_close(context, new_cred->rcache);
+ if (new_cred->keytab)
+ krb5_kt_close(context, new_cred->keytab);
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ strcpy(ccboth, cctype);
+ strcat(ccboth, ":");
+ strcat(ccboth, ccname);
+
+ if (code = krb5_cc_resolve(context, ccboth, &new_cred->ccache)) {
+ if (new_cred->rcache)
+ krb5_rc_close(context, new_cred->rcache);
+ if (new_cred->keytab)
+ krb5_kt_close(context, new_cred->keytab);
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+ } else {
+ new_cred->ccache = NULL;
+ }
+
+ /* intern the credential handle */
+
+ if (! kg_save_cred_id((gss_cred_id_t) new_cred)) {
+ if (new_cred->ccache)
+ krb5_cc_close(context, new_cred->ccache);
+ if (new_cred->rcache)
+ krb5_rc_close(context, new_cred->rcache);
+ if (new_cred->keytab)
+ krb5_kt_close(context, new_cred->keytab);
+ krb5_free_principal(context, new_cred->princ);
+ free(new_cred);
+
+ *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ return(GSS_S_FAILURE);
+ }
+
+ /* modify new_cred */
+
+ cred = new_cred;
+ }
+
+ /* set the flag for the new mechanism */
+
+ if (g_OID_equal(desired_mech, gss_mech_krb5_old))
+ cred->prerfc_mech = 1;
+ else if (g_OID_equal(desired_mech, gss_mech_krb5))
+ cred->rfc_mech = 1;
+ else if (g_OID_equal(desired_mech, gss_mech_krb5_v2))
+ cred->rfcv2_mech = 1;
+
+ /* set the outputs */
+
+ if (GSS_ERROR(major_status = krb5_gss_inquire_cred(minor_status, cred,
+ NULL, &lifetime,
+ NULL, actual_mechs))) {
+ OM_uint32 dummy;
+
+ if (output_cred_handle)
+ (void) krb5_gss_release_cred(&dummy, (gss_cred_id_t *) &cred);
+
+ return(major_status);
+ }
+
+ if (initiator_time_rec)
+ *initiator_time_rec = lifetime;
+ if (acceptor_time_rec)
+ *acceptor_time_rec = lifetime;
+
+ if (output_cred_handle)
+ *output_cred_handle = cred;
+
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+}
diff --git a/src/lib/gssapi/krb5/canon_name.c b/src/lib/gssapi/krb5/canon_name.c
index 652745c7b..688366e1f 100644
--- a/src/lib/gssapi/krb5/canon_name.c
+++ b/src/lib/gssapi/krb5/canon_name.c
@@ -31,13 +31,12 @@ OM_uint32 krb5_gss_canonicalize_name(OM_uint32 *minor_status,
const gss_OID mech_type,
gss_name_t *output_name)
{
- if ((mech_type == GSS_C_NULL_OID) ||
- !g_OID_equal(mech_type, gss_mech_krb5)) {
- if (minor_status)
- *minor_status = 0;
- return(GSS_S_BAD_MECH);
- }
-
- return gss_duplicate_name(minor_status, input_name,
- output_name);
+ if (!g_OID_equal(gss_mech_krb5_v2, mech_type) &&
+ !g_OID_equal(gss_mech_krb5, mech_type) &&
+ !g_OID_equal(gss_mech_krb5_old, mech_type)) {
+ *minor_status = 0;
+ return(GSS_S_BAD_MECH);
+ }
+
+ return(gss_duplicate_name(minor_status, input_name, output_name));
}
diff --git a/src/lib/gssapi/krb5/delete_sec_context.c b/src/lib/gssapi/krb5/delete_sec_context.c
index 16964995a..28c235890 100644
--- a/src/lib/gssapi/krb5/delete_sec_context.c
+++ b/src/lib/gssapi/krb5/delete_sec_context.c
@@ -80,15 +80,11 @@ krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
if (ctx->seqstate)
g_order_free(&(ctx->seqstate));
- if (ctx->enc.processed)
- krb5_finish_key(context, &ctx->enc.eblock);
- if (ctx->enc.key)
- krb5_free_keyblock(context, ctx->enc.key);
+ if (ctx->enc)
+ krb5_free_keyblock(context, ctx->enc);
- if (ctx->seq.processed)
- krb5_finish_key(context, &ctx->seq.eblock);
- if (ctx->seq.key)
- krb5_free_keyblock(context, ctx->seq.key);
+ if (ctx->seq)
+ krb5_free_keyblock(context, ctx->seq);
if (ctx->here)
krb5_free_principal(context, ctx->here);
@@ -105,6 +101,9 @@ krb5_gss_delete_sec_context(minor_status, context_handle, output_token)
if (ctx->mech_used)
gss_release_oid(minor_status, &ctx->mech_used);
+ if (ctx->ctypes)
+ xfree(ctx->ctypes);
+
/* Zero out context */
memset(ctx, 0, sizeof(*ctx));
xfree(ctx);
diff --git a/src/lib/gssapi/krb5/disp_status.c b/src/lib/gssapi/krb5/disp_status.c
index 4dc13843c..3a6ba7b1a 100644
--- a/src/lib/gssapi/krb5/disp_status.c
+++ b/src/lib/gssapi/krb5/disp_status.c
@@ -49,10 +49,12 @@ krb5_gss_display_status(minor_status, status_value, status_type,
return(GSS_S_FAILURE);
if ((mech_type != GSS_C_NULL_OID) &&
- (! g_OID_equal(gss_mech_krb5, mech_type))) {
- *minor_status = 0;
- return(GSS_S_BAD_MECH);
- }
+ !g_OID_equal(gss_mech_krb5_v2, mech_type) &&
+ !g_OID_equal(gss_mech_krb5, mech_type) &&
+ !g_OID_equal(gss_mech_krb5_old, mech_type)) {
+ *minor_status = 0;
+ return(GSS_S_BAD_MECH);
+ }
if (status_type == GSS_C_GSS_CODE) {
return(g_display_major_status(minor_status, status_value,
diff --git a/src/lib/gssapi/krb5/gssapiP_krb5.h b/src/lib/gssapi/krb5/gssapiP_krb5.h
index 11b7c50f4..bcbde3894 100644
--- a/src/lib/gssapi/krb5/gssapiP_krb5.h
+++ b/src/lib/gssapi/krb5/gssapiP_krb5.h
@@ -68,8 +68,17 @@
((x) & (GSS_C_MUTUAL_FLAG | GSS_C_REPLAY_FLAG | \
GSS_C_SEQUENCE_FLAG | GSS_C_DELEG_FLAG)))
+#define KG2_TOK_INITIAL 0x0101
+#define KG2_TOK_RESPONSE 0x0202
+#define KG2_TOK_MIC 0x0303
+#define KG2_TOK_WRAP_INTEG 0x0404
+#define KG2_TOK_WRAP_PRIV 0x0505
+
#define KRB5_GSS_FOR_CREDS_OPTION 1
+#define KG2_RESP_FLAG_ERROR 0x0001
+#define KG2_RESP_FLAG_DELEG_OK 0x0002
+
/** internal types **/
typedef krb5_principal krb5_gss_name_t;
@@ -78,25 +87,19 @@ typedef struct _krb5_gss_cred_id_rec {
/* name/type of credential */
gss_cred_usage_t usage;
krb5_principal princ; /* this is not interned as a gss_name_t */
- const gss_OID_set_desc *actual_mechs;
- int prerfc_mech; /* these are a cache of the set above */
+ int prerfc_mech;
int rfc_mech;
+ int rfcv2_mech;
/* keytab (accept) data */
krb5_keytab keytab;
+ krb5_rcache rcache;
/* ccache (init) data */
krb5_ccache ccache;
krb5_timestamp tgt_expire;
- krb5_rcache rcache;
} krb5_gss_cred_id_rec, *krb5_gss_cred_id_t;
-typedef struct _krb5_gss_enc_desc {
- int processed;
- krb5_keyblock *key;
- krb5_encrypt_block eblock;
-} krb5_gss_enc_desc;
-
typedef struct _krb5_gss_ctx_id_rec {
int initiate; /* nonzero if initiating, zero if accepting */
OM_uint32 gss_flags;
@@ -108,21 +111,35 @@ typedef struct _krb5_gss_ctx_id_rec {
int signalg;
int cksum_size;
int sealalg;
- krb5_gss_enc_desc enc;
- krb5_gss_enc_desc seq;
+ krb5_keyblock *enc;
+ krb5_keyblock *seq;
krb5_timestamp endtime;
krb5_flags krb_flags;
- krb5_int32 seq_send;
- krb5_int32 seq_recv;
+ /* XXX these used to be signed. the old spec is inspecific, and
+ the new spec specifies unsigned. I don't believe that the change
+ affects the wire encoding. */
+ krb5_ui_4 seq_send;
+ krb5_ui_4 seq_recv;
void *seqstate;
int established;
int big_endian;
krb5_auth_context auth_context;
gss_OID_desc *mech_used;
+ int gsskrb5_version;
+ int nctypes;
+ krb5_cksumtype *ctypes;
} krb5_gss_ctx_id_rec, *krb5_gss_ctx_id_t;
extern void *kg_vdb;
+struct kg2_option {
+ int option_id; /* set by caller */
+ int length; /* filled in by parser */
+ unsigned char *data; /* filled in by parser. points inside
+ passed-in token, so nothing needs to
+ be freed */
+};
+
/* helper macros */
#define kg_save_name(name) g_save_name(&kg_vdb,name)
@@ -151,12 +168,12 @@ krb5_error_code kg_checksum_channel_bindings
int bigend));
krb5_error_code kg_make_seq_num PROTOTYPE((krb5_context context,
- krb5_gss_enc_desc *ed,
+ krb5_keyblock *key,
int direction, krb5_int32 seqnum, unsigned char *cksum,
unsigned char *buf));
krb5_error_code kg_get_seq_num PROTOTYPE((krb5_context context,
- krb5_gss_enc_desc *ed,
+ krb5_keyblock *key,
unsigned char *cksum, unsigned char *buf, int *direction,
krb5_int32 *seqnum));
@@ -164,19 +181,20 @@ krb5_error_code kg_make_seed PROTOTYPE((krb5_context context,
krb5_keyblock *key,
unsigned char *seed));
-int kg_confounder_size PROTOTYPE((krb5_gss_enc_desc *ed));
+int kg_confounder_size PROTOTYPE((krb5_context context, krb5_keyblock *key));
-krb5_error_code kg_make_confounder PROTOTYPE((krb5_gss_enc_desc *ed,
- unsigned char *buf));
+krb5_error_code kg_make_confounder PROTOTYPE((krb5_context context,
+ krb5_keyblock *key, unsigned char *buf));
-int kg_encrypt_size PROTOTYPE((krb5_gss_enc_desc *ed, int n));
+int kg_encrypt_size PROTOTYPE((krb5_context context,
+ krb5_keyblock *key, int n));
krb5_error_code kg_encrypt PROTOTYPE((krb5_context context,
- krb5_gss_enc_desc *ed,
+ krb5_keyblock *key,
krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length));
krb5_error_code kg_decrypt PROTOTYPE((krb5_context context,
- krb5_gss_enc_desc *ed,
+ krb5_keyblock *key,
krb5_pointer iv, krb5_pointer in, krb5_pointer out, int length));
OM_uint32 kg_seal PROTOTYPE((krb5_context context,
@@ -223,6 +241,23 @@ krb5_error_code kg_ctx_internalize PROTOTYPE((krb5_context kcontext,
OM_uint32 kg_get_context PROTOTYPE((OM_uint32 *minor_status,
krb5_context *context));
+OM_uint32
+kg2_parse_token PROTOTYPE((OM_uint32 *minor_status,
+ unsigned char *ptr,
+ int length,
+ krb5_ui_4 *flags,
+ int *nctypes, /* OUT */
+ krb5_cksumtype **ctypes, /* OUT */
+ int noptions,
+ struct kg2_option *options, /* INOUT */
+ krb5_data *kmsg,
+ krb5_data *mic));
+
+void kg2_intersect_ctypes PROTOTYPE((int *nc1,
+ krb5_cksumtype *c1,
+ int nc2,
+ const krb5_cksumtype *c2));
+
/** declarations of internal name mechanism functions **/
OM_uint32 krb5_gss_acquire_cred
diff --git a/src/lib/gssapi/krb5/gssapi_err_krb5.et b/src/lib/gssapi/krb5/gssapi_err_krb5.et
index 54a126518..3c9be6351 100644
--- a/src/lib/gssapi/krb5/gssapi_err_krb5.et
+++ b/src/lib/gssapi/krb5/gssapi_err_krb5.et
@@ -35,4 +35,5 @@ error_code KG_CRED, "Bad magic number for krb5_gss_cred_id_t"
error_code KG_ENC_DESC, "Bad magic number for krb5_gss_enc_desc"
error_code KG_BAD_SEQ, "Sequence number in token is corrupt"
error_code KG_EMPTY_CCACHE, "Credential cache is empty"
+error_code KG_NO_CTYPES, "Acceptor and Initiator share no checksum types"
end
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.c b/src/lib/gssapi/krb5/gssapi_krb5.c
index c0942c39a..aaa47ea06 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.c
+++ b/src/lib/gssapi/krb5/gssapi_krb5.c
@@ -21,6 +21,32 @@
*/
/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+/*
* $Id$
*/
@@ -43,6 +69,9 @@
* The OID of the proposed standard krb5 mechanism is:
* iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
* krb5(2) = 1.2.840.113554.1.2.2
+ * The OID of the proposed standard krb5 v2 mechanism is:
+ * iso(1) member-body(2) US(840) mit(113554) infosys(1) gssapi(2)
+ * krb5v2(3) = 1.2.840.113554.1.2.3
*
*/
@@ -58,8 +87,13 @@ const gss_OID_desc krb5_gss_oid_array[] = {
{5, "\053\005\001\005\002"},
/* this is the official, rfc-specified OID */
{9, "\052\206\110\206\367\022\001\002\002"},
+ /* these two are name type OID's */
{10, "\052\206\110\206\367\022\001\002\002\001"},
{10, "\052\206\110\206\367\022\001\002\002\002"},
+ /* this is the v2 assigned OID */
+ {9, "\052\206\110\206\367\022\001\002\003"},
+ /* this is the official, rfc-specified OID again */
+ {9, "\052\206\110\206\367\022\001\002\002"},
{ 0, 0 }
};
@@ -67,16 +101,21 @@ const gss_OID_desc * const gss_mech_krb5_old = krb5_gss_oid_array+0;
const gss_OID_desc * const gss_mech_krb5 = krb5_gss_oid_array+1;
const gss_OID_desc * const gss_nt_krb5_name = krb5_gss_oid_array+2;
const gss_OID_desc * const gss_nt_krb5_principal = krb5_gss_oid_array+3;
+const gss_OID_desc * const gss_mech_krb5_v2 = krb5_gss_oid_array+4;
static const gss_OID_set_desc oidsets[] = {
{1, (gss_OID) krb5_gss_oid_array+0},
{1, (gss_OID) krb5_gss_oid_array+1},
{2, (gss_OID) krb5_gss_oid_array+0},
+ {1, (gss_OID) krb5_gss_oid_array+4},
+ {2, (gss_OID) krb5_gss_oid_array+4},
};
const gss_OID_set_desc * const gss_mech_set_krb5_old = oidsets+0;
const gss_OID_set_desc * const gss_mech_set_krb5 = oidsets+1;
const gss_OID_set_desc * const gss_mech_set_krb5_both = oidsets+2;
+const gss_OID_set_desc * const gss_mech_set_krb5_v2 = oidsets+3;
+const gss_OID_set_desc * const gss_mech_set_krb5_v1v2 = oidsets+4;
void *kg_vdb = NULL;
diff --git a/src/lib/gssapi/krb5/gssapi_krb5.h b/src/lib/gssapi/krb5/gssapi_krb5.h
index 63ac530f3..e4eccbb42 100644
--- a/src/lib/gssapi/krb5/gssapi_krb5.h
+++ b/src/lib/gssapi/krb5/gssapi_krb5.h
@@ -32,9 +32,12 @@
extern const gss_OID_desc * const gss_mech_krb5;
extern const gss_OID_desc * const gss_mech_krb5_old;
+extern const gss_OID_desc * const gss_mech_krb5_v2;
extern const gss_OID_set_desc * const gss_mech_set_krb5;
extern const gss_OID_set_desc * const gss_mech_set_krb5_old;
extern const gss_OID_set_desc * const gss_mech_set_krb5_both;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_v2;
+extern const gss_OID_set_desc * const gss_mech_set_krb5_v1v2;
extern const gss_OID_desc * const gss_nt_krb5_name;
extern const gss_OID_desc * const gss_nt_krb5_principal;
diff --git a/src/lib/gssapi/krb5/init_sec_context.c b/src/lib/gssapi/krb5/init_sec_context.c
index 50855b58c..4ff2085b4 100644
--- a/src/lib/gssapi/krb5/init_sec_context.c
+++ b/src/lib/gssapi/krb5/init_sec_context.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "gssapiP_krb5.h"
#include <memory.h>
#include <stdlib.h>
@@ -33,8 +59,257 @@
int krb5_gss_dbg_client_expcreds = 0;
static krb5_error_code
-make_ap_req(context, auth_context, cred, server, now, endtime, chan_bindings,
- req_flags, krb_flags, mech_type, token)
+make_ap_req_v2(context, auth_context, cred, server, now, endtime,
+ chan_bindings, req_flags, krb_flags, mech_type,
+ ret_nctypes, ret_ctypes, token)
+ krb5_context context;
+ krb5_auth_context * auth_context;
+ krb5_gss_cred_id_t cred;
+ krb5_principal server;
+ krb5_timestamp now;
+ krb5_timestamp *endtime;
+ gss_channel_bindings_t chan_bindings;
+ OM_uint32 *req_flags;
+ krb5_flags *krb_flags;
+ gss_OID mech_type;
+ int *ret_nctypes;
+ krb5_cksumtype **ret_ctypes;
+ gss_buffer_t token;
+{
+ krb5_flags mk_req_flags = 0;
+ krb5_int32 con_flags;
+ krb5_error_code code;
+ krb5_creds in_creds, *out_creds = 0;
+ krb5_data credmsg, cksumdata, ap_req;
+ int i, tlen, cblen, nctypes;
+ krb5_cksumtype *ctypes;
+ unsigned char *t, *ptr;
+
+ credmsg.data = 0;
+ cksumdata.data = 0;
+ ap_req.data = 0;
+ ctypes = 0;
+
+ /* this probably isn't necessary */
+ if (*auth_context)
+ krb5_auth_con_free(context, *auth_context);
+
+ *auth_context = 0;
+
+ /* create the option data if necessary */
+
+ if (*req_flags & GSS_C_DELEG_FLAG) {
+ /* first get KRB_CRED message, so we know its length */
+
+ /* clear the time check flag that was set in krb5_auth_con_init() */
+ krb5_auth_con_getflags(context, *auth_context, &con_flags);
+ krb5_auth_con_setflags(context, *auth_context,
+ con_flags & ~KRB5_AUTH_CONTEXT_DO_TIME);
+
+ code = krb5_fwd_tgt_creds(context, *auth_context, 0,
+ cred->princ, server, cred->ccache, 1,
+ &credmsg);
+
+ /* turn KRB5_AUTH_CONTEXT_DO_TIME back on */
+ krb5_auth_con_setflags(context, *auth_context, con_flags);
+
+ if (code) {
+ /* don't fail here; just don't accept/do the delegation
+ request */
+ *req_flags &= ~GSS_C_DELEG_FLAG;
+ } else {
+ if (credmsg.length > KRB5_INT16_MAX) {
+ krb5_free_data_contents(context, &credmsg);
+ return(KRB5KRB_ERR_FIELD_TOOLONG);
+ }
+ }
+ } else {
+ credmsg.length = 0;
+ }
+
+ /*
+ * Get the credential, for the session key etype
+ */
+
+ memset((char *) &in_creds, 0, sizeof(krb5_creds));
+
+ if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client)))
+ goto cleanup;
+ if ((code = krb5_copy_principal(context, server, &in_creds.server)))
+ goto cleanup;
+ in_creds.times.endtime = *endtime;
+
+ if ((code = krb5_get_credentials(context, 0, cred->ccache,
+ &in_creds, &out_creds)))
+ goto cleanup;
+
+ /*
+ * Enforce a stricter limit (without timeskew forgiveness at the
+ * boundaries) because accept_sec_context code is also similarly
+ * non-forgiving.
+ */
+ if (!krb5_gss_dbg_client_expcreds && out_creds->times.endtime < now) {
+ code = KRB5KRB_AP_ERR_TKT_EXPIRED;
+ goto cleanup;
+ }
+
+ /* construct the list of compatible cksum types */
+
+ if (code = krb5_c_keyed_checksum_types(context,
+ out_creds->keyblock.enctype,
+ &nctypes, &ctypes))
+ goto cleanup;
+
+ if (nctypes == 0) {
+ code = KRB5_CRYPTO_INTERNAL;
+ goto cleanup;
+ }
+
+ /* construct the checksum fields */
+
+ cblen = 4*5;
+ if (chan_bindings)
+ cblen += (chan_bindings->initiator_address.length+
+ chan_bindings->acceptor_address.length+
+ chan_bindings->application_data.length);
+
+ cksumdata.length = cblen + 8 + 4*nctypes + 4;
+ if (credmsg.length)
+ cksumdata.length += 4 + credmsg.length;
+
+ if ((cksumdata.data = (char *) malloc(cksumdata.length)) == NULL)
+ goto cleanup;
+
+ /* helper macros. This code currently depends on a long being 32
+ bits, and htonl dtrt. */
+
+ ptr = cksumdata.data;
+
+ if (chan_bindings) {
+ TWRITE_INT(ptr, chan_bindings->initiator_addrtype, 1);
+ TWRITE_BUF(ptr, chan_bindings->initiator_address, 1);
+ TWRITE_INT(ptr, chan_bindings->acceptor_addrtype, 1);
+ TWRITE_BUF(ptr, chan_bindings->acceptor_address, 1);
+ TWRITE_BUF(ptr, chan_bindings->application_data, 1);
+ } else {
+ memset(ptr, 0, cblen);
+ ptr += cblen;
+ }
+
+ /* construct the token fields */
+
+ ptr[0] = (KG2_TOK_INITIAL >> 8) & 0xff;
+ ptr[1] = KG2_TOK_INITIAL & 0xff;
+
+ ptr[2] = (*req_flags >> 24) & 0xff;
+ ptr[3] = (*req_flags >> 16) & 0xff;
+ ptr[4] = (*req_flags >> 8) & 0xff;
+ ptr[5] = *req_flags & 0xff;
+
+ ptr[6] = (nctypes >> 8) & 0xff;
+ ptr[7] = nctypes & 0xff;
+
+ ptr += 8;
+
+ for (i=0; i<nctypes; i++) {
+ ptr[0] = (ctypes[i] >> 24) & 0xff;
+ ptr[1] = (ctypes[i] >> 16) & 0xff;
+ ptr[2] = (ctypes[i] >> 8) & 0xff;
+ ptr[3] = ctypes[i] & 0xff;
+
+ ptr += 4;
+ }
+
+ if (credmsg.length) {
+ ptr[0] = (KRB5_GSS_FOR_CREDS_OPTION >> 8) & 0xff;
+ ptr[1] = KRB5_GSS_FOR_CREDS_OPTION & 0xff;
+
+ ptr[2] = (credmsg.length >> 8) & 0xff;
+ ptr[3] = credmsg.length & 0xff;
+
+ ptr += 4;
+
+ memcpy(ptr, credmsg.data, credmsg.length);
+
+ ptr += credmsg.length;
+ }
+
+ memset(ptr, 0, 4);
+
+ /* call mk_req. subkey and ap_req need to be used or destroyed */
+
+ mk_req_flags = AP_OPTS_USE_SUBKEY;
+
+ if (*req_flags & GSS_C_MUTUAL_FLAG)
+ mk_req_flags |= AP_OPTS_MUTUAL_REQUIRED;
+
+ if ((code = krb5_mk_req_extended(context, auth_context, mk_req_flags,
+ &cksumdata, out_creds, &ap_req)))
+ goto cleanup;
+
+ /* store the interesting stuff from creds and authent */
+ *endtime = out_creds->times.endtime;
+ *krb_flags = out_creds->ticket_flags;
+
+ /* build up the token */
+
+ /* allocate space for the token */
+ tlen = g_token_size((gss_OID) mech_type,
+ (cksumdata.length-(2+cblen))+2+ap_req.length);
+
+ if ((t = (unsigned char *) xmalloc(tlen)) == NULL) {
+ code = ENOMEM;
+ goto cleanup;
+ }
+
+ ptr = t;
+
+ g_make_token_header((gss_OID) mech_type,
+ (cksumdata.length-(2+cblen))+2+ap_req.length,
+ &ptr, KG2_TOK_INITIAL);
+
+ /* skip over the channel bindings and the token id */
+ memcpy(ptr, cksumdata.data+cblen+2, cksumdata.length-(cblen+2));
+ ptr += cksumdata.length-(cblen+2);
+ ptr[0] = (ap_req.length >> 8) & 0xff;
+ ptr[1] = ap_req.length & 0xff;
+ ptr += 2;
+ memcpy(ptr, ap_req.data, ap_req.length);
+
+ /* pass allocated data back */
+
+ *ret_nctypes = nctypes;
+ *ret_ctypes = ctypes;
+
+ token->length = tlen;
+ token->value = (void *) t;
+
+ code = 0;
+
+cleanup:
+ if (code) {
+ if (*auth_context)
+ krb5_auth_con_free(context, *auth_context);
+ if (ctypes)
+ krb5_free_cksumtypes(context, ctypes);
+ }
+
+ if (out_creds)
+ krb5_free_creds(context, out_creds);
+ krb5_free_cred_contents(context, &in_creds);
+ if (credmsg.data)
+ free(credmsg.data);
+ if (ap_req.data)
+ free(ap_req.data);
+ if (cksumdata.data)
+ free(cksumdata.data);
+
+ return(code);
+}
+
+static krb5_error_code
+make_ap_req_v1(context, auth_context, cred, server, now, endtime,
+ chan_bindings, req_flags, krb_flags, mech_type, token)
krb5_context context;
krb5_auth_context * auth_context;
krb5_gss_cred_id_t cred;
@@ -142,15 +417,16 @@ make_ap_req(context, auth_context, cred, server, now, endtime, chan_bindings,
/* fill in the necessary fields in creds */
memset((char *) &in_creds, 0, sizeof(krb5_creds));
+
if ((code = krb5_copy_principal(context, cred->princ, &in_creds.client)))
goto cleanup;
if ((code = krb5_copy_principal(context, server, &in_creds.server)))
goto cleanup;
- in_creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
in_creds.times.endtime = *endtime;
+ in_creds.keyblock.enctype = ENCTYPE_DES_CBC_CRC;
/*
- * Get the credential..., I don't know in 0 is a good value for the
+ * Get the credential..., I don't know if 0 is a good value for the
* kdcoptions
*/
if ((code = krb5_get_credentials(context, 0, cred->ccache,
@@ -222,10 +498,6 @@ cleanup:
return (code);
}
-#define IS_KRB_ERROR(dat)\
- ((dat) && (dat)->length && ((dat)->data[0] == 0x7e ||\
- (dat)->data[0] == 0x5e))
-
OM_uint32
krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
context_handle, target_name, mech_type,
@@ -251,10 +523,11 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
krb5_error_code code;
krb5_gss_ctx_id_rec *ctx;
krb5_timestamp now;
- krb5_enctype enctype;
gss_buffer_desc token;
- int i;
- int err;
+ int gsskrb5_vers;
+ int i, err;
+ krb5_ui_4 resp_flags, field_length, opt_id;
+ OM_uint32 major_status, dummy;
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
@@ -289,15 +562,33 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
err = 0;
if (mech_type == GSS_C_NULL_OID) {
- mech_type = cred->rfc_mech?gss_mech_krb5:gss_mech_krb5_old;
+ if (cred->rfcv2_mech) {
+ mech_type = gss_mech_krb5_v2;
+ gsskrb5_vers = 2000;
+ } else if (cred->rfc_mech) {
+ mech_type = gss_mech_krb5;
+ gsskrb5_vers = 1000;
+ } else if (cred->prerfc_mech) {
+ mech_type = gss_mech_krb5_old;
+ gsskrb5_vers = 1000;
+ } else {
+ err = 1;
+ }
+ } else if (g_OID_equal(mech_type, gss_mech_krb5_v2)) {
+ if (!cred->rfcv2_mech)
+ err = 1;
+ gsskrb5_vers = 2000;
} else if (g_OID_equal(mech_type, gss_mech_krb5)) {
if (!cred->rfc_mech)
err = 1;
+ gsskrb5_vers = 1000;
} else if (g_OID_equal(mech_type, gss_mech_krb5_old)) {
if (!cred->prerfc_mech)
err = 1;
- } else
+ gsskrb5_vers = 1000;
+ } else {
err = 1;
+ }
if (err) {
*minor_status = 0;
@@ -351,6 +642,9 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
ctx->seed_init = 0;
ctx->big_endian = 0; /* all initiators do little-endian, as per spec */
ctx->seqstate = 0;
+ ctx->gsskrb5_version = gsskrb5_vers;
+ ctx->nctypes = 0;
+ ctx->ctypes = 0;
if ((code = krb5_timeofday(context, &now))) {
free(ctx);
@@ -377,63 +671,94 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
return(GSS_S_FAILURE);
}
- if ((code = make_ap_req(context, &(ctx->auth_context), cred,
- ctx->there, now, &ctx->endtime,
- input_chan_bindings,
- &ctx->gss_flags, &ctx->krb_flags, mech_type,
- &token))) {
- krb5_free_principal(context, ctx->here);
- krb5_free_principal(context, ctx->there);
- xfree(ctx);
- *minor_status = code;
-
- if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
- (code == KG_EMPTY_CCACHE))
- return GSS_S_NO_CRED;
- if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
- return GSS_S_CREDENTIALS_EXPIRED;
- return(GSS_S_FAILURE);
- }
-
- krb5_auth_con_getlocalseqnumber(context, ctx->auth_context, &ctx->seq_send);
- krb5_auth_con_getlocalsubkey(context, ctx->auth_context, &ctx->subkey);
-
- /* fill in the encryption descriptors */
-
- switch(ctx->subkey->enctype) {
- case ENCTYPE_DES_CBC_MD5:
- case ENCTYPE_DES_CBC_CRC:
- enctype = ENCTYPE_DES_CBC_RAW;
- ctx->signalg = 0;
- ctx->cksum_size = 8;
- ctx->sealalg = 0;
- break;
+ if (ctx->gsskrb5_version == 2000) {
+ /* gsskrb5 v2 */
+
+ ctx->gss_flags & ~GSS_C_DELEG_FLAG;
+
+ if ((code = make_ap_req_v2(context, &(ctx->auth_context), cred,
+ ctx->there, now, &ctx->endtime,
+ input_chan_bindings,
+ &ctx->gss_flags, &ctx->krb_flags,
+ mech_type, &ctx->nctypes, &ctx->ctypes,
+ &token))) {
+ krb5_free_principal(context, ctx->here);
+ krb5_free_principal(context, ctx->there);
+ xfree(ctx);
+ *minor_status = code;
+
+ if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
+ (code == KG_EMPTY_CCACHE))
+ return GSS_S_NO_CRED;
+ if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
+ return GSS_S_CREDENTIALS_EXPIRED;
+ return(GSS_S_FAILURE);
+ }
+
+ krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
+ &ctx->seq_send);
+ krb5_auth_con_getlocalsubkey(context, ctx->auth_context,
+ &ctx->subkey);
+ } else {
+ /* gsskrb5 v1 */
+
+ if ((code = make_ap_req_v1(context, &(ctx->auth_context), cred,
+ ctx->there, now, &ctx->endtime,
+ input_chan_bindings,
+ &ctx->gss_flags, &ctx->krb_flags,
+ mech_type,
+ &token))) {
+ krb5_free_principal(context, ctx->here);
+ krb5_free_principal(context, ctx->there);
+ xfree(ctx);
+ *minor_status = code;
+
+ if ((code == KRB5_FCC_NOFILE) || (code == KRB5_CC_NOTFOUND) ||
+ (code == KG_EMPTY_CCACHE))
+ return GSS_S_NO_CRED;
+ if (code == KRB5KRB_AP_ERR_TKT_EXPIRED)
+ return GSS_S_CREDENTIALS_EXPIRED;
+ return(GSS_S_FAILURE);
+ }
+
+ krb5_auth_con_getlocalseqnumber(context, ctx->auth_context,
+ &ctx->seq_send);
+ krb5_auth_con_getlocalsubkey(context, ctx->auth_context,
+ &ctx->subkey);
+
+ /* fill in the encryption descriptors */
+
+ switch(ctx->subkey->enctype) {
+ case ENCTYPE_DES_CBC_MD5:
+ case ENCTYPE_DES_CBC_CRC:
+ ctx->subkey->enctype = ENCTYPE_DES_CBC_RAW;
+ ctx->signalg = 0;
+ ctx->cksum_size = 8;
+ ctx->sealalg = 0;
+ break;
#if 0
- case ENCTYPE_DES3_CBC_MD5:
- enctype = ENCTYPE_DES3_CBC_RAW;
- ctx->signalg = 3;
- ctx->cksum_size = 16;
- ctx->sealalg = 1;
- break;
+ case ENCTYPE_DES3_CBC_MD5:
+ enctype = ENCTYPE_DES3_CBC_RAW;
+ ctx->signalg = 3;
+ ctx->cksum_size = 16;
+ ctx->sealalg = 1;
+ break;
#endif
- default:
- return GSS_S_FAILURE;
- }
+ default:
+ return GSS_S_FAILURE;
+ }
- /* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */
+ /* the encryption key is the session key XOR 0xf0f0f0f0f0f0f0f0 */
- krb5_use_enctype(context, &ctx->enc.eblock, enctype);
- ctx->enc.processed = 0;
- if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc.key)))
- return(code);
- for (i=0; i<ctx->enc.key->length; i++)
- /*SUPPRESS 113*/
- ctx->enc.key->contents[i] ^= 0xf0;
+ if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->enc)))
+ return(code);
+ for (i=0; i<ctx->enc->length; i++)
+ /*SUPPRESS 113*/
+ ctx->enc->contents[i] ^= 0xf0;
- krb5_use_enctype(context, &ctx->seq.eblock, enctype);
- ctx->seq.processed = 0;
- if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq.key)))
- return(code);
+ if ((code = krb5_copy_keyblock(context, ctx->subkey, &ctx->seq)))
+ return(code);
+ }
/* at this point, the context is constructed and valid,
hence, releaseable */
@@ -493,7 +818,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
} else {
unsigned char *ptr;
char *sptr;
- krb5_data ap_rep;
+ krb5_data ap_rep, mic;
krb5_ap_rep_enc_part *ap_rep_data;
krb5_error *krb_error;
@@ -512,11 +837,8 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
if ((ctx->established) ||
(((gss_cred_id_t) cred) != claimant_cred_handle) ||
((ctx->gss_flags & GSS_C_MUTUAL_FLAG) == 0)) {
- (void)krb5_gss_delete_sec_context(minor_status,
- context_handle, NULL);
- /* XXX this minor status is wrong if an arg was changed */
- *minor_status = KG_CONTEXT_ESTABLISHED;
- return(GSS_S_FAILURE);
+ code = KG_CONTEXT_ESTABLISHED;
+ goto fail;
}
if (! krb5_principal_compare(context, ctx->there,
@@ -538,47 +860,106 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
ptr = (unsigned char *) input_token->value;
- if ((err = g_verify_token_header((gss_OID) mech_type, &(ap_rep.length),
- &ptr, KG_TOK_CTX_AP_REP,
- input_token->length))) {
+ if (ctx->gsskrb5_version == 2000) {
+ int token_length;
+ int nctypes;
+ krb5_cksumtype *ctypes;
+
+ /* gsskrb5 v2 */
+
+ if ((err = g_verify_token_header((gss_OID) mech_type,
+ &token_length,
+ &ptr, KG2_TOK_RESPONSE,
+ input_token->length))) {
+ (void)krb5_gss_delete_sec_context(minor_status,
+ context_handle, NULL);
+ *minor_status = err;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ if (GSS_ERROR(major_status =
+ kg2_parse_token(minor_status, ptr, token_length,
+ &resp_flags, &nctypes, &ctypes,
+ 0, NULL, &ap_rep, &mic))) {
+ free(ctypes);
+ (void)krb5_gss_delete_sec_context(&dummy, context_handle, NULL);
+ return(major_status);
+ }
+
+ kg2_intersect_ctypes(&ctx->nctypes, ctx->ctypes, nctypes, ctypes);
+
+ free(ctypes);
+
+ if (ctx->nctypes == 0) {
+ code = KG_NO_CTYPES;
+ goto fail;
+ }
+
+ if (resp_flags & KG2_RESP_FLAG_ERROR) {
+ if (code = krb5_rd_error(context, &ap_rep, &krb_error))
+ goto fail;
+
+ if (krb_error->error)
+ code = krb_error->error + ERROR_TABLE_BASE_krb5;
+ else
+ code = 0;
+
+ krb5_free_error(context, krb_error);
+
+ goto fail;
+ }
+
+ if (resp_flags & KG2_RESP_FLAG_DELEG_OK)
+ ctx->gss_flags |= GSS_C_DELEG_FLAG;
+
+ /* drop through to ap_rep handling */
+ } else {
+ /* gsskrb5 v1 */
+
+ if ((err = g_verify_token_header((gss_OID) mech_type,
+ &(ap_rep.length),
+ &ptr, KG_TOK_CTX_AP_REP,
+ input_token->length))) {
if (g_verify_token_header((gss_OID) mech_type, &(ap_rep.length),
&ptr, KG_TOK_CTX_ERROR,
input_token->length) == 0) {
- /* Handle a KRB_ERROR message from the server */
+ /* Handle a KRB_ERROR message from the server */
- sptr = (char *) ptr; /* PC compiler bug */
- TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+ sptr = (char *) ptr; /* PC compiler bug */
+ TREAD_STR(sptr, ap_rep.data, ap_rep.length);
- code = krb5_rd_error(context, &ap_rep, &krb_error);
- if (code)
- goto fail;
- if (krb_error->error)
- code = krb_error->error + ERROR_TABLE_BASE_krb5;
- else
- code = 0;
- krb5_free_error(context, krb_error);
+ code = krb5_rd_error(context, &ap_rep, &krb_error);
+ if (code)
goto fail;
+ if (krb_error->error)
+ code = krb_error->error + ERROR_TABLE_BASE_krb5;
+ else
+ code = 0;
+ krb5_free_error(context, krb_error);
+ goto fail;
} else {
- *minor_status = err;
- return(GSS_S_DEFECTIVE_TOKEN);
+ *minor_status = 0;
+ return(GSS_S_DEFECTIVE_TOKEN);
}
- }
+ }
- sptr = (char *) ptr; /* PC compiler bug */
- TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+ sptr = (char *) ptr; /* PC compiler bug */
+ TREAD_STR(sptr, ap_rep.data, ap_rep.length);
+ }
/* decode the ap_rep */
- if ((code = krb5_rd_rep(context,ctx->auth_context,&ap_rep,
+ if ((code = krb5_rd_rep(context, ctx->auth_context, &ap_rep,
&ap_rep_data))) {
- /*
- * XXX A hack for backwards compatiblity.
- * To be removed in 1999 -- proven
- */
- krb5_auth_con_setuseruserkey(context,ctx->auth_context,ctx->subkey);
- if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
- &ap_rep_data)))
- goto fail;
+ /*
+ * XXX A hack for backwards compatiblity.
+ * To be removed in 1999 -- proven
+ */
+ krb5_auth_con_setuseruserkey(context, ctx->auth_context,
+ ctx->subkey);
+ if ((krb5_rd_rep(context, ctx->auth_context, &ap_rep,
+ &ap_rep_data)))
+ goto fail;
}
/* store away the sequence number */
@@ -593,6 +974,25 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
/* set established */
ctx->established = 1;
+ if (ctx->gsskrb5_version == 2000) {
+ gss_buffer_desc mic_data, mic_token;
+
+ /* start with the token id */
+ mic_data.value = ptr-2;
+ /* end before the ap-rep length */
+ mic_data.length = ((char*)(ap_rep.data-2)-(char*)(ptr-2));
+
+ mic_token.length = mic.length;
+ mic_token.value = mic.data;
+
+ if (GSS_ERROR(major_status =
+ krb5_gss_verify_mic(minor_status, *context_handle,
+ &mic_data, &mic_token, NULL))) {
+ (void)krb5_gss_delete_sec_context(&dummy, context_handle, NULL);
+ return(major_status);
+ }
+ }
+
/* set returns */
if (time_rec) {
@@ -602,7 +1002,7 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
}
if (ret_flags)
- *ret_flags = KG_IMPLFLAGS(req_flags);
+ *ret_flags = ctx->gss_flags;
if (actual_mech_type)
*actual_mech_type = mech_type;
@@ -616,8 +1016,8 @@ krb5_gss_init_sec_context(minor_status, claimant_cred_handle,
return(GSS_S_COMPLETE);
fail:
- (void)krb5_gss_delete_sec_context(minor_status,
- (gss_ctx_id_t) ctx, NULL);
+ (void)krb5_gss_delete_sec_context(minor_status, context_handle, NULL);
+
*minor_status = code;
return(GSS_S_FAILURE);
}
diff --git a/src/lib/gssapi/krb5/inq_cred.c b/src/lib/gssapi/krb5/inq_cred.c
index ee5d436c1..c800012c8 100644
--- a/src/lib/gssapi/krb5/inq_cred.c
+++ b/src/lib/gssapi/krb5/inq_cred.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "gssapiP_krb5.h"
OM_uint32
@@ -39,6 +65,7 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
krb5_deltat lifetime;
krb5_principal ret_name;
gss_OID_set mechs;
+ OM_uint32 ret;
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
@@ -84,12 +111,26 @@ krb5_gss_inquire_cred(minor_status, cred_handle, name, lifetime_ret,
}
}
- if (mechanisms)
- if (! g_copy_OID_set(cred->actual_mechs, &mechs)) {
- krb5_free_principal(context, ret_name);
- *minor_status = ENOMEM;
- return(GSS_S_FAILURE);
- }
+ if (mechanisms) {
+ if (GSS_ERROR(ret = generic_gss_create_empty_oid_set(minor_status,
+ &mechs)) ||
+ (cred->prerfc_mech &&
+ GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+ gss_mech_krb5_old,
+ &mechs))) ||
+ (cred->rfc_mech &&
+ GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+ gss_mech_krb5,
+ &mechs))) ||
+ (cred->rfcv2_mech &&
+ GSS_ERROR(ret = generic_gss_add_oid_set_member(minor_status,
+ gss_mech_krb5_v2,
+ &mechs)))) {
+ krb5_free_principal(context, ret_name);
+ /* *minor_status set above */
+ return(ret);
+ }
+ }
if (name) {
if (! kg_save_name((gss_name_t) ret_name)) {
@@ -139,7 +180,9 @@ krb5_gss_inquire_cred_by_mech(minor_status, cred_handle,
* We only know how to handle our own creds.
*/
if ((mech_type != GSS_C_NULL_OID) &&
- !g_OID_equal(gss_mech_krb5, mech_type)) {
+ !g_OID_equal(gss_mech_krb5_old, mech_type) &&
+ !g_OID_equal(gss_mech_krb5, mech_type) &&
+ !g_OID_equal(gss_mech_krb5_v2, mech_type)) {
*minor_status = 0;
return(GSS_S_NO_CRED);
}
diff --git a/src/lib/gssapi/krb5/inq_names.c b/src/lib/gssapi/krb5/inq_names.c
index 9c5f47450..01a199430 100644
--- a/src/lib/gssapi/krb5/inq_names.c
+++ b/src/lib/gssapi/krb5/inq_names.c
@@ -43,10 +43,11 @@ krb5_gss_inquire_names_for_mech(minor_status, mechanism, name_types)
* We only know how to handle our own mechanism.
*/
if ((mechanism != GSS_C_NULL_OID) &&
+ !g_OID_equal(gss_mech_krb5_v2, mechanism) &&
!g_OID_equal(gss_mech_krb5, mechanism) &&
!g_OID_equal(gss_mech_krb5_old, mechanism)) {
*minor_status = 0;
- return(GSS_S_FAILURE);
+ return(GSS_S_BAD_MECH);
}
/* We're okay. Create an empty OID set */
diff --git a/src/lib/gssapi/krb5/k5seal.c b/src/lib/gssapi/krb5/k5seal.c
index c174bb7cb..e1877b71f 100644
--- a/src/lib/gssapi/krb5/k5seal.c
+++ b/src/lib/gssapi/krb5/k5seal.c
@@ -20,15 +20,269 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "gssapiP_krb5.h"
static krb5_error_code
-make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
- signalg, cksum_size, sealalg, encrypt, toktype,
- bigend, oid)
+make_priv_token_v2 PROTOTYPE((krb5_context context,
+ krb5_keyblock *subkey,
+ krb5_int32 *seqnum,
+ int direction,
+ gss_buffer_t text,
+ gss_buffer_t token,
+ gss_OID oid));
+
+static krb5_error_code
+make_priv_token_v2(context, subkey, seqnum, direction, text, token, oid)
krb5_context context;
- krb5_gss_enc_desc *enc_ed;
- krb5_gss_enc_desc *seq_ed;
+ krb5_keyblock *subkey;
+ krb5_int32 *seqnum;
+ int direction;
+ gss_buffer_t text;
+ gss_buffer_t token;
+ gss_OID oid;
+{
+ krb5_data plain;
+ krb5_enc_data cipher;
+ krb5_error_code code;
+ size_t enclen;
+ int tlen;
+ unsigned char *t, *ptr;
+
+ plain.data = 0;
+ cipher.ciphertext.data = 0;
+ t = 0;
+
+ plain.length = 7+text->length;
+ if ((plain.data = (void *) malloc(plain.length)) == NULL) {
+ code = ENOMEM;
+ goto cleanup;
+ }
+
+ plain.data[0] = (*seqnum >> 24) & 0xff;
+ plain.data[1] = (*seqnum >> 16) & 0xff;
+ plain.data[2] = (*seqnum >> 8) & 0xff;
+ plain.data[3] = *seqnum & 0xff;
+
+ plain.data[4] = direction?0:0xff;
+
+ plain.data[5] = (text->length >> 8) & 0xff;
+ plain.data[6] = text->length & 0xff;
+
+ memcpy(plain.data+7, text->value, text->length);
+
+ if (code = krb5_c_encrypt_length(context, subkey->enctype,
+ plain.length, &enclen))
+ goto cleanup;
+
+ tlen = g_token_size((gss_OID) oid, 2+enclen);
+
+ if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
+ return(ENOMEM);
+
+ ptr = t;
+
+ g_make_token_header((gss_OID) oid, 2+enclen, &ptr,
+ KG2_TOK_WRAP_PRIV);
+
+ ptr[0] = (enclen >> 8) & 0xff;
+ ptr[1] = enclen & 0xff;
+
+ cipher.ciphertext.length = enclen;
+ cipher.ciphertext.data = ptr+2;
+
+ if (code = krb5_c_encrypt(context, subkey,
+ KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV,
+ 0, &plain, &cipher))
+ goto cleanup;
+
+ /* that's it. return the token */
+
+ (*seqnum)++;
+
+ token->length = tlen;
+ token->value = (void *) t;
+
+ code = 0;
+
+cleanup:
+ if (plain.data)
+ free(plain.data);
+ if (code) {
+ if (t)
+ free(t);
+ }
+
+ return(code);
+}
+
+static krb5_error_code
+make_integ_token_v2 PROTOTYPE((krb5_context context,
+ krb5_keyblock *subkey,
+ krb5_cksumtype ctype,
+ krb5_int32 *seqnum,
+ int direction,
+ gss_buffer_t text,
+ gss_buffer_t token,
+ int toktype,
+ gss_OID oid));
+
+static krb5_error_code
+make_integ_token_v2(context, subkey, ctype, seqnum, direction, text, token,
+ toktype, oid)
+ krb5_context context;
+ krb5_keyblock *subkey;
+ krb5_cksumtype ctype;
+ krb5_int32 *seqnum;
+ int direction;
+ gss_buffer_t text;
+ gss_buffer_t token;
+ int toktype;
+ gss_OID oid;
+{
+ krb5_error_code code;
+ int tmp, tlen;
+ unsigned char *t, *ptr;
+ krb5_data plain;
+ krb5_checksum cksum;
+
+ plain.data = 0;
+ t = 0;
+ cksum.contents = 0;
+
+ /* assemble the checksum buffer and compute the checksum */
+
+ plain.length = 7+text->length;
+
+ if ((plain.data = (char *) malloc(plain.length)) == NULL)
+ goto cleanup;
+
+ plain.data[0] = (*seqnum >> 24) & 0xff;
+ plain.data[1] = (*seqnum >> 16) & 0xff;
+ plain.data[2] = (*seqnum >> 8) & 0xff;
+ plain.data[3] = *seqnum & 0xff;
+
+ plain.data[4] = direction?0:0xff;
+
+ plain.data[5] = (text->length >> 8) & 0xff;
+ plain.data[6] = text->length & 0xff;
+
+ memcpy(plain.data+7, text->value, text->length);
+
+ if (code = krb5_c_make_checksum(context, ctype, subkey,
+ (toktype == KG2_TOK_WRAP_INTEG)?
+ KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG:
+ KRB5_KEYUSAGE_GSS_TOK_MIC,
+ &plain, &cksum))
+ goto cleanup;
+
+ /* assemble the token itself */
+
+ if (toktype == KG2_TOK_WRAP_INTEG)
+ tmp = 4+(7+text->length)+2+cksum.length;
+ else
+ tmp = 4+(5)+2+cksum.length;
+
+ tlen = g_token_size((gss_OID) oid, tmp);
+
+ if ((t = (unsigned char *) xmalloc(tlen)) == NULL)
+ return(ENOMEM);
+
+ ptr = t;
+
+ g_make_token_header((gss_OID) oid, tmp, &ptr, toktype);
+
+ ptr[0] = (ctype >> 24) & 0xff;
+ ptr[1] = (ctype >> 16) & 0xff;
+ ptr[2] = (ctype >> 8) & 0xff;
+ ptr[3] = ctype & 0xff;
+
+ ptr += 4;
+
+ if (toktype == KG2_TOK_WRAP_INTEG) {
+ memcpy(ptr, plain.data, 7+text->length);
+ ptr += 7+text->length;
+ } else {
+ memcpy(ptr, plain.data, 5);
+ ptr += 5;
+ }
+
+ ptr[0] = (cksum.length >> 8) & 0xff;
+ ptr[1] = cksum.length & 0xff;
+ ptr += 2;
+
+ memcpy(ptr, cksum.contents, cksum.length);
+
+ /* that's it. return the token */
+
+ (*seqnum)++;
+
+ token->length = tlen;
+ token->value = (void *) t;
+
+ code = 0;
+
+cleanup:
+ if (plain.data)
+ free(plain.data);
+ if (cksum.contents)
+ krb5_free_checksum_contents(context, &cksum);
+ if (code) {
+ if (t)
+ free(t);
+ }
+
+ return(code);
+}
+
+static krb5_error_code
+make_seal_token_v1 PROTOTYPE((krb5_context context,
+ krb5_keyblock *enc,
+ krb5_keyblock *seq,
+ krb5_int32 *seqnum,
+ int direction,
+ gss_buffer_t text,
+ gss_buffer_t token,
+ int signalg,
+ int cksum_size,
+ int sealalg,
+ int encrypt,
+ int toktype,
+ int bigend,
+ gss_OID oid));
+
+static krb5_error_code
+make_seal_token_v1(context, enc, seq, seqnum, direction, text, token,
+ signalg, cksum_size, sealalg, encrypt, toktype,
+ bigend, oid)
+ krb5_context context;
+ krb5_keyblock *enc;
+ krb5_keyblock *seq;
krb5_int32 *seqnum;
int direction;
gss_buffer_t text;
@@ -42,7 +296,9 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
gss_OID oid;
{
krb5_error_code code;
+ size_t sumlen;
char *data_ptr;
+ krb5_data plaind;
krb5_checksum md5cksum;
krb5_checksum cksum;
int conflen=0, tmsglen, tlen;
@@ -54,7 +310,7 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
if (bigend && !encrypt) {
tmsglen = text->length;
} else {
- conflen = kg_confounder_size(enc_ed);
+ conflen = kg_confounder_size(context, enc);
/* XXX knows that des block size is 8 */
tmsglen = (conflen+text->length+8)&(~7);
}
@@ -96,27 +352,24 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
/* pad the plaintext, encrypt if needed, and stick it in the token */
- /* initialize the the cksum and allocate the contents buffer */
+ /* initialize the the cksum */
+ if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen))
+ return(code);
+
md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
- md5cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
- if ((md5cksum.contents = (krb5_octet *) xmalloc(md5cksum.length)) == NULL) {
- return(ENOMEM);
- }
-
+ md5cksum.length = sumlen;
if (toktype == KG_TOK_SEAL_MSG) {
unsigned char *plain;
unsigned char pad;
if (!bigend || encrypt) {
if ((plain = (unsigned char *) xmalloc(tmsglen)) == NULL) {
- xfree(md5cksum.contents);
xfree(t);
return(ENOMEM);
}
- if ((code = kg_make_confounder(enc_ed, plain))) {
+ if ((code = kg_make_confounder(context, enc, plain))) {
xfree(plain);
- xfree(md5cksum.contents);
xfree(t);
return(code);
}
@@ -133,12 +386,11 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
}
if (encrypt) {
- if ((code = kg_encrypt(context, enc_ed, NULL, (krb5_pointer) plain,
+ if ((code = kg_encrypt(context, enc, NULL, (krb5_pointer) plain,
(krb5_pointer) (ptr+cksum_size+14),
tmsglen))) {
if (plain)
xfree(plain);
- xfree(md5cksum.contents);
xfree(t);
return(code);
}
@@ -156,7 +408,6 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
(char *) xmalloc(8 + (bigend ? text->length : tmsglen)))) {
if (plain)
xfree(plain);
- xfree(md5cksum.contents);
xfree(t);
return(ENOMEM);
}
@@ -165,15 +416,15 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
(void) memcpy(data_ptr+8, text->value, text->length);
else
(void) memcpy(data_ptr+8, plain, tmsglen);
- code = krb5_calculate_checksum(context, md5cksum.checksum_type, data_ptr,
- 8 + (bigend ? text->length : tmsglen),
- 0, 0, &md5cksum);
+ plaind.length = 8 + (bigend ? text->length : tmsglen);
+ plaind.data = data_ptr;
+ code = krb5_c_make_checksum(context, md5cksum.checksum_type,
+ 0, 0, &plaind, &md5cksum);
xfree(data_ptr);
if (code) {
if (plain)
xfree(plain);
- xfree(md5cksum.contents);
xfree(t);
return(code);
memcpy(ptr+14+cksum_size, plain, tmsglen);
@@ -185,18 +436,17 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
/* compute the checksum */
if (! (data_ptr = (char *) xmalloc(8 + text->length))) {
- xfree(md5cksum.contents);
xfree(t);
return(ENOMEM);
}
(void) memcpy(data_ptr, ptr-2, 8);
(void) memcpy(data_ptr+8, text->value, text->length);
- code = krb5_calculate_checksum(context, md5cksum.checksum_type, data_ptr,
- 8 + text->length,
- 0, 0, &md5cksum);
+ plaind.length = 8 + text->length;
+ plaind.data = data_ptr;
+ code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0,
+ &plaind, &md5cksum);
xfree(data_ptr);
if (code) {
- xfree(md5cksum.contents);
xfree(t);
return(code);
}
@@ -214,16 +464,19 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
DES encryption the long way, and keep the last block
as the MAC */
+ /* XXX not converted to new api since it's inside an #if 0 */
+
/* initialize the the cksum and allocate the contents buffer */
cksum.checksum_type = CKSUMTYPE_DESCBC;
cksum.length = krb5_checksum_size(context, CKSUMTYPE_DESCBC);
if ((cksum.contents = (krb5_octet *) xmalloc(cksum.length)) == NULL)
return(ENOMEM);
+ /* XXX not converted to new api since it's inside an #if 0 */
if (code = krb5_calculate_checksum(context, cksum.checksum_type,
md5cksum.contents, 16,
- seq_ed->key->contents,
- seq_ed->key->length,
+ seq->contents,
+ seq->length,
&cksum)) {
xfree(cksum.contents);
xfree(md5cksum.contents);
@@ -235,9 +488,9 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
xfree(cksum.contents);
#else
- if ((code = kg_encrypt(context, seq_ed,
+ if ((code = kg_encrypt(context, seq,
(g_OID_equal(oid, gss_mech_krb5_old) ?
- seq_ed->key->contents : NULL),
+ seq->contents : NULL),
md5cksum.contents, md5cksum.contents, 16))) {
xfree(md5cksum.contents);
xfree(t);
@@ -257,7 +510,7 @@ make_seal_token(context, enc_ed, seq_ed, seqnum, direction, text, token,
/* create the seq_num */
- if ((code = kg_make_seq_num(context, seq_ed, direction?0:0xff, *seqnum,
+ if ((code = kg_make_seq_num(context, seq, direction?0:0xff, *seqnum,
ptr+14, ptr+6))) {
xfree(t);
return(code);
@@ -320,17 +573,42 @@ kg_seal(context, minor_status, context_handle, conf_req_flag, qop_req,
return(GSS_S_FAILURE);
}
- if ((code = make_seal_token(context, &ctx->enc, &ctx->seq,
- &ctx->seq_send, ctx->initiate,
- input_message_buffer, output_message_buffer,
- ctx->signalg, ctx->cksum_size, ctx->sealalg,
- conf_req_flag, toktype, ctx->big_endian,
- ctx->mech_used))) {
+ if (ctx->gsskrb5_version == 2000) {
+ if (toktype == KG_TOK_WRAP_MSG) {
+ if (conf_req_flag)
+ toktype = KG2_TOK_WRAP_PRIV;
+ else
+ toktype = KG2_TOK_WRAP_INTEG;
+ } else {
+ toktype = KG2_TOK_MIC;
+ }
+
+ if (conf_req_flag) {
+ code = make_priv_token_v2(context, ctx->subkey, &ctx->seq_send,
+ ctx->initiate, input_message_buffer,
+ output_message_buffer, ctx->mech_used);
+ } else {
+ code = make_integ_token_v2(context, ctx->subkey, ctx->ctypes[0],
+ &ctx->seq_send, ctx->initiate,
+ input_message_buffer,
+ output_message_buffer, toktype,
+ ctx->mech_used);
+ }
+ } else {
+ code = make_seal_token_v1(context, ctx->enc, ctx->seq,
+ &ctx->seq_send, ctx->initiate,
+ input_message_buffer, output_message_buffer,
+ ctx->signalg, ctx->cksum_size, ctx->sealalg,
+ conf_req_flag, toktype, ctx->big_endian,
+ ctx->mech_used);
+ }
+
+ if (code) {
*minor_status = code;
return(GSS_S_FAILURE);
}
- if ((toktype == KG_TOK_SEAL_MSG) && conf_state)
+ if (conf_state)
*conf_state = conf_req_flag;
*minor_status = 0;
diff --git a/src/lib/gssapi/krb5/k5unseal.c b/src/lib/gssapi/krb5/k5unseal.c
index 041cae06a..c32e3255d 100644
--- a/src/lib/gssapi/krb5/k5unseal.c
+++ b/src/lib/gssapi/krb5/k5unseal.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "gssapiP_krb5.h"
#include <memory.h>
@@ -27,34 +53,417 @@
* $Id$
*/
+static OM_uint32
+kg2_verify_mic(context, minor_status, ctx, ptr, bodysize,
+ text, qop_state)
+ krb5_context context;
+ OM_uint32 *minor_status;
+ krb5_gss_ctx_id_rec *ctx;
+ unsigned char *ptr;
+ int bodysize;
+ gss_buffer_t text;
+ gss_qop_t *qop_state;
+{
+ size_t cksumlen;
+ krb5_error_code code;
+ krb5_data plain;
+ krb5_cksumtype tctype;
+ krb5_ui_4 tseqnum;
+ int tdirection;
+ krb5_checksum cksum;
+ krb5_boolean ckvalid;
+ krb5_timestamp now;
+ OM_uint32 retval;
+
+ plain.data = 0;
+ cksum.contents = 0;
+
+ /* verify the header */
+
+ if (bodysize < 11) {
+ free(plain.data);
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ /* allocate the checksum buffer */
+
+ plain.length = 7+text->length;
+
+ if ((plain.data = (char *) malloc(plain.length)) == NULL) {
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ /* suck out the body parts from the token */
+
+ tctype = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
+ (ptr[2]<<8) | ptr[3]);
+ ptr += 4;
+
+ memcpy(plain.data, ptr, 5);
+ tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+ ptr += 4;
+ tdirection = ptr[0];
+ ptr += 1;
+
+ cksum.length = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ bodysize -= 11;
+
+ if (cksum.length != bodysize) {
+ free(plain.data);
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ cksum.contents = ptr;
+ cksum.checksum_type = tctype;
+
+ /* finish assembling the checksum buffer and compute the checksum */
+
+ plain.data[5] = (text->length >> 8) & 0xff;
+ plain.data[6] = text->length & 0xff;
+
+ memcpy(plain.data+7, text->value, text->length);
+
+ if (code = krb5_c_verify_checksum(context, ctx->subkey,
+ KRB5_KEYUSAGE_GSS_TOK_MIC,
+ &plain, &cksum, &ckvalid)) {
+ free(plain.data);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (!ckvalid) {
+ free(plain.data);
+ *minor_status = 0;
+ return(GSS_S_BAD_SIG);
+ }
+
+ /* check context expiry */
+
+ if ((code = krb5_timeofday(context, &now))) {
+ free(plain.data);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (now > ctx->endtime) {
+ free(plain.data);
+ *minor_status = 0;
+ return(GSS_S_CONTEXT_EXPIRED);
+ }
+
+ /* do sequencing checks */
+
+ if ((ctx->initiate && tdirection != 0xff) ||
+ (!ctx->initiate && tdirection != 0)) {
+ free(plain.data);
+ *minor_status = G_BAD_DIRECTION;
+ return(GSS_S_BAD_SIG);
+ }
+
+ retval = g_order_check(&(ctx->seqstate), tseqnum);
+
+ free(plain.data);
+
+ if (retval) {
+ *minor_status = 0;
+ return(retval);
+ }
+
+ if (qop_state)
+ *qop_state = GSS_C_QOP_DEFAULT;
+
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+}
+
+static OM_uint32
+kg2_unwrap_integ(context, minor_status, ctx, ptr, bodysize, output, qop_state)
+ krb5_context context;
+ OM_uint32 *minor_status;
+ krb5_gss_ctx_id_rec *ctx;
+ unsigned char *ptr;
+ int bodysize;
+ gss_buffer_t output;
+ gss_qop_t *qop_state;
+{
+ krb5_error_code code;
+ OM_uint32 retval;
+ krb5_ui_4 tseqnum;
+ int tdirection;
+ int tmsglen;
+ unsigned char *tmsg;
+ krb5_data plain;
+ krb5_checksum tcksum;
+ krb5_boolean ckvalid;
+ krb5_timestamp now;
+
+ output->length = 0;
+ output->value = NULL;
+
+ /* read the body parts out of the message */
+
+ if (bodysize < 11) {
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ tcksum.checksum_type = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
+ (ptr[2]<<8) | ptr[3]);
+ ptr += 4;
+
+ plain.data = ptr;
+
+ tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+ ptr += 4;
+ tdirection = ptr[0];
+ ptr += 1;
+
+ tmsglen = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ bodysize -= 11;
+
+ if (bodysize < tmsglen) {
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ tmsg = ptr;
+ ptr += tmsglen;
+ bodysize -= tmsglen;
+
+ plain.length = ((char*)ptr) - ((char *)plain.data);
+
+ tcksum.length = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ bodysize -= 2;
+
+ if (bodysize != tcksum.length) {
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ tcksum.contents = ptr;
+
+ /* verify the MIC */
+
+ if (code = krb5_c_verify_checksum(context, ctx->subkey,
+ KRB5_KEYUSAGE_GSS_TOK_WRAP_INTEG,
+ &plain, &tcksum, &ckvalid)) {
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (!ckvalid) {
+ *minor_status = 0;
+ return(GSS_S_BAD_SIG);
+ }
+
+ /* check context expiry */
+
+ if ((code = krb5_timeofday(context, &now))) {
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (now > ctx->endtime) {
+ *minor_status = 0;
+ return(GSS_S_CONTEXT_EXPIRED);
+ }
+
+ /* do sequencing checks */
+
+ if ((ctx->initiate && tdirection != 0xff) ||
+ (!ctx->initiate && tdirection != 0)) {
+ *minor_status = G_BAD_DIRECTION;
+ return(GSS_S_BAD_SIG);
+ }
+
+ if (retval = g_order_check(&(ctx->seqstate), tseqnum)) {
+ *minor_status = 0;
+ return(retval);
+ }
+
+ if ((output->value = (void *) malloc(tmsglen)) == NULL) {
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ memcpy(output->value, tmsg, tmsglen);
+ output->length = tmsglen;
+
+ if (qop_state)
+ *qop_state = GSS_C_QOP_DEFAULT;
+
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+}
+
+static OM_uint32
+kg2_unwrap_priv(context, minor_status, ctx, ptr, bodysize, output, qop_state)
+ krb5_context context;
+ OM_uint32 *minor_status;
+ krb5_gss_ctx_id_rec *ctx;
+ unsigned char *ptr;
+ int bodysize;
+ gss_buffer_t output;
+ gss_qop_t *qop_state;
+{
+ krb5_error_code code;
+ OM_uint32 retval;
+ krb5_enc_data cipher;
+ krb5_data plain;
+ krb5_ui_4 tseqnum;
+ int tdirection;
+ int tmsglen;
+ unsigned char *tmsg;
+ krb5_timestamp now;
+
+ output->length = 0;
+ output->value = NULL;
+
+ /* read the body parts out of the message */
+
+ if (bodysize < 2) {
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ cipher.ciphertext.length = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ bodysize -= 2;
+
+ if (bodysize != cipher.ciphertext.length) {
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ cipher.ciphertext.data = ptr;
+ cipher.enctype = ENCTYPE_UNKNOWN;
+
+ plain.length = cipher.ciphertext.length;
+ if ((plain.data = (char *) malloc(plain.length)) == NULL) {
+ *minor_status = 0;
+ return(GSS_S_FAILURE);
+ }
+
+ /* decrypt (and implicitly verify) the encrypted data */
+
+ if (code = krb5_c_decrypt(context, ctx->subkey,
+ KRB5_KEYUSAGE_GSS_TOK_WRAP_PRIV,
+ 0, &cipher, &plain)) {
+ free(plain.data);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ /* parse out the encrypted fields */
+
+ ptr = plain.data;
+ bodysize = plain.length;
+
+ if (bodysize < 7) {
+ free(plain.data);
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ tseqnum = ((ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3]);
+ ptr += 4;
+ tdirection = ptr[0];
+ ptr += 1;
+
+ tmsglen = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ bodysize -= 7;
+
+ /* check context expiry */
+
+ if ((code = krb5_timeofday(context, &now))) {
+ free(plain.data);
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ if (now > ctx->endtime) {
+ free(plain.data);
+ *minor_status = 0;
+ return(GSS_S_CONTEXT_EXPIRED);
+ }
+
+ /* do sequencing checks */
+
+ if ((ctx->initiate && tdirection != 0xff) ||
+ (!ctx->initiate && tdirection != 0)) {
+ free(plain.data);
+ *minor_status = G_BAD_DIRECTION;
+ return(GSS_S_BAD_SIG);
+ }
+
+ if (retval = g_order_check(&(ctx->seqstate), tseqnum)) {
+ free(plain.data);
+ *minor_status = 0;
+ return(retval);
+ }
+
+ /* now copy out the data. can't do a strict equality check here,
+ since the output could be padded. */
+
+ if (bodysize < tmsglen) {
+ free(plain.data);
+ *minor_status = G_TOK_TRUNC;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ tmsg = ptr;
+
+ if ((output->value = (void *) malloc(tmsglen)) == NULL) {
+ free(plain.data);
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ memcpy(output->value, tmsg, tmsglen);
+ output->length = tmsglen;
+
+ if (qop_state)
+ *qop_state = GSS_C_QOP_DEFAULT;
+
+ free(plain.data);
+
+ *minor_status = 0;
+ return(GSS_S_COMPLETE);
+}
+
/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
- conf_state is only valid if SEAL.
- */
+ conf_state is only valid if SEAL. */
OM_uint32
-kg_unseal(context, minor_status, context_handle, input_token_buffer,
- message_buffer, conf_state, qop_state, toktype)
+kg_unseal_v1(context, minor_status, ctx, ptr, bodysize, message_buffer,
+ conf_state, qop_state, toktype)
krb5_context context;
OM_uint32 *minor_status;
- gss_ctx_id_t context_handle;
- gss_buffer_t input_token_buffer;
+ krb5_gss_ctx_id_rec *ctx;
+ unsigned char *ptr;
+ int bodysize;
gss_buffer_t message_buffer;
int *conf_state;
int *qop_state;
int toktype;
{
- krb5_gss_ctx_id_rec *ctx;
krb5_error_code code;
- int bodysize;
int tmsglen;
int conflen = 0;
int signalg;
int sealalg;
gss_buffer_desc token;
- unsigned char *ptr;
krb5_checksum cksum;
krb5_checksum desmac;
krb5_checksum md5cksum;
+ krb5_data plaind;
char *data_ptr;
krb5_timestamp now;
unsigned char *plain;
@@ -64,38 +473,13 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
int direction;
krb5_int32 seqnum;
OM_uint32 retval;
+ size_t sumlen;
if (toktype == KG_TOK_SEAL_MSG) {
message_buffer->length = 0;
message_buffer->value = NULL;
}
- /* validate the context handle */
- if (! kg_validate_ctx_id(context_handle)) {
- *minor_status = (OM_uint32) G_VALIDATE_FAILED;
- return(GSS_S_NO_CONTEXT);
- }
-
- ctx = (krb5_gss_ctx_id_rec *) context_handle;
-
- if (! ctx->established) {
- *minor_status = KG_CTX_INCOMPLETE;
- return(GSS_S_NO_CONTEXT);
- }
-
- /* parse the token, leave the data in message_buffer, setting conf_state */
-
- /* verify the header */
-
- ptr = (unsigned char *) input_token_buffer->value;
-
- if ((err = g_verify_token_header((gss_OID) ctx->mech_used, &bodysize,
- &ptr, toktype,
- input_token_buffer->length))) {
- *minor_status = err;
- return(GSS_S_DEFECTIVE_TOKEN);
- }
-
/* get the sign and seal algorithms */
signalg = ptr[0] + (ptr[1]<<8);
@@ -159,7 +543,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
return(GSS_S_FAILURE);
}
- if ((code = kg_decrypt(context, &ctx->enc, NULL,
+ if ((code = kg_decrypt(context, ctx->enc, NULL,
ptr+14+cksum_len, plain, tmsglen))) {
xfree(plain);
*minor_status = code;
@@ -174,7 +558,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
if ((sealalg == 0xffff) && ctx->big_endian) {
token.length = tmsglen;
} else {
- conflen = kg_confounder_size(&ctx->enc);
+ conflen = kg_confounder_size(context, ctx->enc);
token.length = tmsglen - conflen - plain[tmsglen-1];
}
@@ -200,15 +584,12 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
/* compute the checksum of the message */
- /* initialize the the cksum and allocate the contents buffer */
+ /* initialize the the cksum */
+ if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen))
+ return(code);
+
md5cksum.checksum_type = CKSUMTYPE_RSA_MD5;
- md5cksum.length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
- if ((md5cksum.contents = (krb5_octet *) xmalloc(md5cksum.length)) == NULL) {
- if (sealalg != 0xffff)
- xfree(plain);
- *minor_status = ENOMEM;
- return(GSS_S_FAILURE);
- }
+ md5cksum.length = sumlen;
switch (signalg) {
case 0:
@@ -219,7 +600,6 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
if (! (data_ptr = (void *)
xmalloc(8 + (ctx->big_endian ? token.length : plainlen)))) {
- xfree(md5cksum.contents);
if (sealalg != 0xffff)
xfree(plain);
if (toktype == KG_TOK_SEAL_MSG)
@@ -235,14 +615,13 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
else
(void) memcpy(data_ptr+8, plain, plainlen);
- code = krb5_calculate_checksum(context, md5cksum.checksum_type,
- data_ptr, 8 +
- (ctx->big_endian ? token.length :
- plainlen), 0, 0, &md5cksum);
+ plaind.length = 8 + (ctx->big_endian ? token.length : plainlen);
+ plaind.data = data_ptr;
+ code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0,
+ &plaind, &md5cksum);
xfree(data_ptr);
if (code) {
- xfree(md5cksum.contents);
if (toktype == KG_TOK_SEAL_MSG)
xfree(token.value);
*minor_status = code;
@@ -264,6 +643,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
return(GSS_S_FAILURE);
}
+ /* XXX not converted to new api since it's inside an #if 0 */
if (code = krb5_calculate_checksum(context, cksum.checksum_type,
md5cksum.contents, 16,
ctx->seq.key->contents,
@@ -281,9 +661,9 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
xfree(cksum.contents);
#else
- if ((code = kg_encrypt(context, &ctx->seq,
+ if ((code = kg_encrypt(context, ctx->seq,
(g_OID_equal(ctx->mech_used, gss_mech_krb5_old) ?
- ctx->seq.key->contents : NULL),
+ ctx->seq->contents : NULL),
md5cksum.contents, md5cksum.contents, 16))) {
xfree(md5cksum.contents);
if (toktype == KG_TOK_SEAL_MSG)
@@ -333,15 +713,15 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
else
(void) memcpy(data_ptr+8+sizeof(ctx->seed),
plain, plainlen);
- code = krb5_calculate_checksum(context, md5cksum.checksum_type,
- data_ptr, 8 + sizeof(ctx->seed) +
- (ctx->big_endian ? token.length :
- plainlen), 0, 0, &md5cksum);
-
+ plaind.length = 8 + sizeof(ctx->seed) +
+ (ctx->big_endian ? token.length : plainlen);
+ plaind.data = data_ptr;
+ xfree(md5cksum.contents);
+ code = krb5_c_make_checksum(context, md5cksum.checksum_type, 0, 0,
+ &plaind, &md5cksum);
xfree(data_ptr);
if (code) {
- xfree(md5cksum.contents);
if (sealalg == 0)
xfree(plain);
if (toktype == KG_TOK_SEAL_MSG)
@@ -394,7 +774,7 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
/* do sequencing checks */
- if ((code = kg_get_seq_num(context, &(ctx->seq), ptr+14, ptr+6, &direction,
+ if ((code = kg_get_seq_num(context, ctx->seq, ptr+14, ptr+6, &direction,
&seqnum))) {
if (toktype == KG_TOK_SEAL_MSG)
xfree(token.value);
@@ -417,3 +797,88 @@ kg_unseal(context, minor_status, context_handle, input_token_buffer,
*minor_status = 0;
return(retval);
}
+
+/* message_buffer is an input if SIGN, output if SEAL, and ignored if DEL_CTX
+ conf_state is only valid if SEAL. */
+
+OM_uint32
+kg_unseal(context, minor_status, context_handle, input_token_buffer,
+ message_buffer, conf_state, qop_state, toktype)
+ krb5_context context;
+ OM_uint32 *minor_status;
+ gss_ctx_id_t context_handle;
+ gss_buffer_t input_token_buffer;
+ gss_buffer_t message_buffer;
+ int *conf_state;
+ int *qop_state;
+ int toktype;
+{
+ krb5_gss_ctx_id_rec *ctx;
+ unsigned char *ptr;
+ int bodysize;
+ int err;
+ OM_uint32 retval;
+
+ /* validate the context handle */
+ if (! kg_validate_ctx_id(context_handle)) {
+ *minor_status = (OM_uint32) G_VALIDATE_FAILED;
+ return(GSS_S_NO_CONTEXT);
+ }
+
+ ctx = (krb5_gss_ctx_id_rec *) context_handle;
+
+ if (! ctx->established) {
+ *minor_status = KG_CTX_INCOMPLETE;
+ return(GSS_S_NO_CONTEXT);
+ }
+
+ /* parse the token, leave the data in message_buffer, setting conf_state */
+
+ /* verify the header */
+
+ ptr = (unsigned char *) input_token_buffer->value;
+
+ if (ctx->gsskrb5_version == 2000) {
+ if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+ &bodysize, &ptr, KG2_TOK_MIC,
+ input_token_buffer->length))) {
+ return(kg2_verify_mic(context, minor_status, ctx, ptr, bodysize,
+ message_buffer, qop_state));
+ } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+ &bodysize, &ptr,
+ KG2_TOK_WRAP_INTEG,
+ input_token_buffer->length))) {
+ if (GSS_ERROR(retval = kg2_unwrap_integ(context, minor_status,
+ ctx, ptr, bodysize,
+ message_buffer, qop_state)))
+ return(retval);
+
+ if (conf_state)
+ *conf_state = 0;
+ return(GSS_S_COMPLETE);
+ } else if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+ &bodysize, &ptr,
+ KG2_TOK_WRAP_PRIV,
+ input_token_buffer->length))) {
+ if (GSS_ERROR(retval = kg2_unwrap_priv(context, minor_status,
+ ctx, ptr, bodysize,
+ message_buffer, qop_state)))
+ return(retval);
+
+ if (conf_state)
+ *conf_state = 1;
+ return(GSS_S_COMPLETE);
+ }
+ } else {
+ if (!(err = g_verify_token_header((gss_OID) ctx->mech_used,
+ &bodysize, &ptr, toktype,
+ input_token_buffer->length))) {
+ return(kg_unseal_v1(context, minor_status, ctx, ptr, bodysize,
+ message_buffer, conf_state, qop_state,
+ toktype));
+ }
+ }
+
+ *minor_status = err;
+ return(GSS_S_DEFECTIVE_TOKEN);
+}
diff --git a/src/lib/gssapi/krb5/rel_oid.c b/src/lib/gssapi/krb5/rel_oid.c
index f35727e3f..afb2171b8 100644
--- a/src/lib/gssapi/krb5/rel_oid.c
+++ b/src/lib/gssapi/krb5/rel_oid.c
@@ -63,7 +63,8 @@ krb5_gss_internal_release_oid(minor_status, oid)
* return GSS_S_CONTINUE_NEEDED for any OIDs it does not recognize.
*/
- if ((*oid != gss_mech_krb5) &&
+ if ((*oid != gss_mech_krb5_v2) &&
+ (*oid != gss_mech_krb5) &&
(*oid != gss_mech_krb5_old) &&
(*oid != gss_nt_krb5_name) &&
(*oid != gss_nt_krb5_principal)) {
diff --git a/src/lib/gssapi/krb5/ser_sctx.c b/src/lib/gssapi/krb5/ser_sctx.c
index 36e70d742..36a16d426 100644
--- a/src/lib/gssapi/krb5/ser_sctx.c
+++ b/src/lib/gssapi/krb5/ser_sctx.c
@@ -40,192 +40,6 @@
* still be done. --marc
*/
-/*
- * Determine the size required for this krb5_gss_enc_desc.
- */
-static krb5_error_code
-kg_enc_desc_size(kcontext, arg, sizep)
- krb5_context kcontext;
- krb5_pointer arg;
- size_t *sizep;
-{
- krb5_error_code kret;
- krb5_gss_enc_desc *edescp;
- size_t required;
-
- /*
- * krb5_gss_cred_id_t requires:
- * krb5_int32 for KG_ENC_DESC
- * krb5_int32 for processed.
- * krb5_int32 for trailer.
- */
- kret = EINVAL;
- if ((edescp = (krb5_gss_enc_desc *) arg)) {
- required = 3*sizeof(krb5_int32);
- if (edescp->key)
- kret = krb5_size_opaque(kcontext,
- KV5M_KEYBLOCK,
- (krb5_pointer) edescp->key,
- &required);
- else
- kret = 0;
-
- /*
- * We need to use size_opaque here because we're not sure as to the
- * ancestry of this eblock, and we can't be sure that the magic number
- * is set in it, so we ASSuME that it's ok.
- */
- if (!kret)
- kret = krb5_size_opaque(kcontext,
- KV5M_ENCRYPT_BLOCK,
- (krb5_pointer) &edescp->eblock,
- &required);
-
- if (!kret)
- *sizep += required;
- }
- return(kret);
-}
-
-/*
- * Externalize this krb5_gss_enc_desc.
- */
-static krb5_error_code
-kg_enc_desc_externalize(kcontext, arg, buffer, lenremain)
- krb5_context kcontext;
- krb5_pointer arg;
- krb5_octet **buffer;
- size_t *lenremain;
-{
- krb5_error_code kret;
- krb5_gss_enc_desc *enc_desc;
- size_t required;
- krb5_octet *bp;
- size_t remain;
-
- required = 0;
- bp = *buffer;
- remain = *lenremain;
- kret = EINVAL;
- if ((enc_desc = (krb5_gss_enc_desc *) arg)) {
- kret = ENOMEM;
- if (!kg_enc_desc_size(kcontext, arg, &required) &&
- (required <= remain)) {
- /* Our identifier */
- (void) krb5_ser_pack_int32(KG_ENC_DESC, &bp, &remain);
-
- /* Now static data */
- (void) krb5_ser_pack_int32((krb5_int32) enc_desc->processed,
- &bp, &remain);
-
- /* Now pack up dynamic data */
- if (enc_desc->key)
- kret = krb5_externalize_opaque(kcontext,
- KV5M_KEYBLOCK,
- (krb5_pointer) enc_desc->key,
- &bp, &remain);
- else
- kret = 0;
-
- if (!kret)
- kret = krb5_externalize_opaque(kcontext,
- KV5M_ENCRYPT_BLOCK,
- (krb5_pointer)&enc_desc->eblock,
- &bp, &remain);
- if (!kret) {
- (void) krb5_ser_pack_int32(KG_ENC_DESC, &bp, &remain);
- *buffer = bp;
- *lenremain = remain;
- }
- }
- }
- return(kret);
-}
-
-/*
- * Internalize this krb5_gss_enc_desc.
- */
-static krb5_error_code
-kg_enc_desc_internalize(kcontext, argp, buffer, lenremain)
- krb5_context kcontext;
- krb5_pointer *argp;
- krb5_octet **buffer;
- size_t *lenremain;
-{
- krb5_error_code kret;
- krb5_gss_enc_desc *edescp;
- krb5_int32 ibuf;
- krb5_octet *bp;
- krb5_encrypt_block *eblockp;
- size_t remain;
-
- bp = *buffer;
- remain = *lenremain;
- kret = EINVAL;
- /* Read our magic number */
- if (krb5_ser_unpack_int32(&ibuf, &bp, &remain))
- ibuf = 0;
- if (ibuf == KG_ENC_DESC) {
- kret = ENOMEM;
-
- /* Get an enc_desc */
- if ((remain >= (2*sizeof(krb5_int32))) &&
- (edescp = (krb5_gss_enc_desc *)
- xmalloc(sizeof(krb5_gss_enc_desc)))) {
- memset(edescp, 0, sizeof(krb5_gss_enc_desc));
-
- /* Get the static data */
- (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
- edescp->processed = (int) ibuf;
-
- /* edescp->key */
- if ((kret = krb5_internalize_opaque(kcontext,
- KV5M_KEYBLOCK,
- (krb5_pointer *) &edescp->key,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
-
- /* edescp->eblock */
- if (!kret &&
- (kret = krb5_internalize_opaque(kcontext,
- KV5M_ENCRYPT_BLOCK,
- (krb5_pointer *) &eblockp,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
- else {
- /* Successful, copy in allocated eblock to our structure */
- memcpy(&edescp->eblock, eblockp, sizeof(edescp->eblock));
- krb5_xfree(eblockp);
- }
-
- /* trailer */
- if (!kret &&
- !(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
- (ibuf == KG_ENC_DESC)) {
- *buffer = bp;
- *lenremain = remain;
- *argp = (krb5_pointer) edescp;
- }
- else {
- if (!kret && (ibuf != KG_ENC_DESC))
- kret = EINVAL;
- if (edescp->eblock.key)
- krb5_free_keyblock(kcontext, edescp->eblock.key);
- if (edescp->eblock.priv && edescp->eblock.priv_size)
- krb5_xfree(edescp->eblock.priv);
- if (edescp->key)
- krb5_free_keyblock(kcontext, edescp->key);
- xfree(edescp);
- }
- }
- }
- return(kret);
-}
-
static krb5_error_code
kg_oid_externalize(kcontext, arg, buffer, lenremain)
krb5_context kcontext;
@@ -416,12 +230,15 @@ kg_ctx_size(kcontext, arg, sizep)
* krb5_int32 for seq_recv.
* krb5_int32 for established.
* krb5_int32 for big_endian.
+ * krb5_int32 for gsskrb5_version.
+ * krb5_int32 for nctypes.
* krb5_int32 for trailer.
*/
kret = EINVAL;
if ((ctx = (krb5_gss_ctx_id_rec *) arg)) {
- required = 14*sizeof(krb5_int32);
+ required = 16*sizeof(krb5_int32);
required += sizeof(ctx->seed);
+ required += ctx->nctypes*sizeof(krb5_int32);
kret = 0;
if (!kret && ctx->here)
@@ -442,14 +259,16 @@ kg_ctx_size(kcontext, arg, sizep)
(krb5_pointer) ctx->subkey,
&required);
- if (!kret)
- kret = kg_enc_desc_size(kcontext,
- (krb5_pointer) &ctx->enc,
+ if (!kret && ctx->enc)
+ kret = krb5_size_opaque(kcontext,
+ KV5M_KEYBLOCK,
+ (krb5_pointer) ctx->enc,
&required);
- if (!kret)
- kret = kg_enc_desc_size(kcontext,
- (krb5_pointer) &ctx->seq,
+ if (!kret && ctx->seq)
+ kret = krb5_size_opaque(kcontext,
+ KV5M_KEYBLOCK,
+ (krb5_pointer) ctx->seq,
&required);
if (!kret)
@@ -486,6 +305,7 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
size_t required;
krb5_octet *bp;
size_t remain;
+ int i;
required = 0;
bp = *buffer;
@@ -526,6 +346,10 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
&bp, &remain);
(void) krb5_ser_pack_int32((krb5_int32) ctx->big_endian,
&bp, &remain);
+ (void) krb5_ser_pack_int32((krb5_int32) ctx->gsskrb5_version,
+ &bp, &remain);
+ (void) krb5_ser_pack_int32((krb5_int32) ctx->nctypes,
+ &bp, &remain);
/* Now dynamic data */
kret = 0;
@@ -552,14 +376,16 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
(krb5_pointer) ctx->subkey,
&bp, &remain);
- if (!kret)
- kret = kg_enc_desc_externalize(kcontext,
- (krb5_pointer) &ctx->enc,
+ if (!kret && ctx->enc)
+ kret = krb5_externalize_opaque(kcontext,
+ KV5M_KEYBLOCK,
+ (krb5_pointer) ctx->enc,
&bp, &remain);
- if (!kret)
- kret = kg_enc_desc_externalize(kcontext,
- (krb5_pointer) &ctx->seq,
+ if (!kret && ctx->seq)
+ kret = krb5_externalize_opaque(kcontext,
+ KV5M_KEYBLOCK,
+ (krb5_pointer) ctx->seq,
&bp, &remain);
if (!kret && ctx->seqstate)
@@ -571,6 +397,13 @@ kg_ctx_externalize(kcontext, arg, buffer, lenremain)
KV5M_AUTH_CONTEXT,
(krb5_pointer) ctx->auth_context,
&bp, &remain);
+
+ for (i=0; i<ctx->nctypes; i++) {
+ if (!kret) {
+ kret = krb5_ser_pack_int32((krb5_int32) ctx->ctypes[i],
+ &bp, &remain);
+ }
+ }
if (!kret) {
(void) krb5_ser_pack_int32(KG_CONTEXT, &bp, &remain);
@@ -597,7 +430,7 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
krb5_int32 ibuf;
krb5_octet *bp;
size_t remain;
- krb5_gss_enc_desc *edp;
+ int i;
bp = *buffer;
remain = *lenremain;
@@ -640,6 +473,10 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
ctx->established = (int) ibuf;
(void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
ctx->big_endian = (int) ibuf;
+ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+ ctx->gsskrb5_version = (int) ibuf;
+ (void) krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+ ctx->nctypes = (int) ibuf;
if ((kret = kg_oid_internalize(kcontext, &ctx->mech_used, &bp,
&remain))) {
@@ -670,29 +507,21 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
if (kret == EINVAL)
kret = 0;
}
- if (!kret) {
- if ((kret = kg_enc_desc_internalize(kcontext,
- (krb5_pointer *) &edp,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
- else {
- memcpy(&ctx->enc, edp, sizeof(ctx->enc));
- xfree(edp);
- }
+ if (!kret &&
+ (kret = krb5_internalize_opaque(kcontext,
+ KV5M_KEYBLOCK,
+ (krb5_pointer *) &ctx->enc,
+ &bp, &remain))) {
+ if (kret == EINVAL)
+ kret = 0;
}
- if (!kret) {
- if ((kret = kg_enc_desc_internalize(kcontext,
- (krb5_pointer *) &edp,
- &bp, &remain))) {
- if (kret == EINVAL)
- kret = 0;
- }
- else {
- memcpy(&ctx->seq, edp, sizeof(ctx->seq));
- xfree(edp);
- }
+ if (!kret &&
+ (kret = krb5_internalize_opaque(kcontext,
+ KV5M_KEYBLOCK,
+ (krb5_pointer *) &ctx->seq,
+ &bp, &remain))) {
+ if (kret == EINVAL)
+ kret = 0;
}
if (!kret) {
@@ -708,6 +537,22 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
(krb5_pointer *) &ctx->auth_context,
&bp, &remain);
+ if (!kret) {
+ if (ctx->nctypes) {
+ if ((ctx->ctypes = (krb5_cksumtype *)
+ malloc(ctx->nctypes*sizeof(krb5_cksumtype))) == NULL){
+ kret = ENOMEM;
+ }
+
+ for (i=0; i<ctx->nctypes; i++) {
+ if (!kret) {
+ kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain);
+ ctx->ctypes[i] = (krb5_cksumtype) ibuf;
+ }
+ }
+ }
+ }
+
/* Get trailer */
if (!kret &&
!(kret = krb5_ser_unpack_int32(&ibuf, &bp, &remain)) &&
@@ -719,18 +564,10 @@ kg_ctx_internalize(kcontext, argp, buffer, lenremain)
else {
if (!kret && (ibuf != KG_CONTEXT))
kret = EINVAL;
- if (ctx->seq.eblock.key)
- krb5_free_keyblock(kcontext, ctx->seq.eblock.key);
- if (ctx->seq.eblock.priv && ctx->seq.eblock.priv_size)
- krb5_xfree(ctx->seq.eblock.priv);
- if (ctx->seq.key)
- krb5_free_keyblock(kcontext, ctx->seq.key);
- if (ctx->enc.eblock.key)
- krb5_free_keyblock(kcontext, ctx->enc.eblock.key);
- if (ctx->enc.eblock.priv && ctx->enc.eblock.priv_size)
- krb5_xfree(ctx->enc.eblock.priv);
- if (ctx->enc.key)
- krb5_free_keyblock(kcontext, ctx->enc.key);
+ if (ctx->seq)
+ krb5_free_keyblock(kcontext, ctx->seq);
+ if (ctx->enc)
+ krb5_free_keyblock(kcontext, ctx->enc);
if (ctx->subkey)
krb5_free_keyblock(kcontext, ctx->subkey);
if (ctx->there)
diff --git a/src/lib/gssapi/krb5/util_cksum.c b/src/lib/gssapi/krb5/util_cksum.c
index 68561f10b..10e6b657f 100644
--- a/src/lib/gssapi/krb5/util_cksum.c
+++ b/src/lib/gssapi/krb5/util_cksum.c
@@ -36,20 +36,25 @@ kg_checksum_channel_bindings(context, cb, cksum, bigend)
{
int len;
char *buf, *ptr;
+ size_t sumlen;
+ krb5_data plaind;
krb5_error_code code;
- /* initialize the the cksum and allocate the contents buffer */
+ /* initialize the the cksum */
+ if (code = krb5_c_checksum_length(context, CKSUMTYPE_RSA_MD5, &sumlen))
+ return(code);
+
cksum->checksum_type = CKSUMTYPE_RSA_MD5;
- cksum->length = krb5_checksum_size(context, CKSUMTYPE_RSA_MD5);
- if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) {
- return(ENOMEM);
- }
+ cksum->length = sumlen;
/* generate a buffer full of zeros if no cb specified */
if (cb == GSS_C_NO_CHANNEL_BINDINGS) {
- memset(cksum->contents, '\0', cksum->length);
- return(0);
+ if ((cksum->contents = (krb5_octet *) xmalloc(cksum->length)) == NULL) {
+ return(ENOMEM);
+ }
+ memset(cksum->contents, '\0', cksum->length);
+ return(0);
}
/* create the buffer to checksum into */
@@ -75,9 +80,11 @@ kg_checksum_channel_bindings(context, cb, cksum, bigend)
/* checksum the data */
- if (code = krb5_calculate_checksum(context, CKSUMTYPE_RSA_MD5,
- buf, len, NULL, 0, cksum)) {
- xfree(cksum->contents);
+ plaind.length = len;
+ plaind.data = buf;
+
+ if (code = krb5_c_make_checksum(context, CKSUMTYPE_RSA_MD5, 0, 0,
+ &plaind, cksum)) {
xfree(buf);
return(code);
}
diff --git a/src/lib/gssapi/krb5/util_crypt.c b/src/lib/gssapi/krb5/util_crypt.c
index 1684377ad..93d46946c 100644
--- a/src/lib/gssapi/krb5/util_crypt.c
+++ b/src/lib/gssapi/krb5/util_crypt.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "k5-int.h"
#include "gssapiP_krb5.h"
#include <memory.h>
@@ -31,103 +57,126 @@
static unsigned char zeros[8] = {0,0,0,0,0,0,0,0};
int
-kg_confounder_size(ed)
- krb5_gss_enc_desc *ed;
+kg_confounder_size(context, key)
+ krb5_context context;
+ krb5_keyblock *key;
{
- /* XXX Abstraction violation!!! */
+ krb5_error_code code;
+ size_t blocksize;
+
+ if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+ return(-1); /* XXX */
- return(ed->eblock.crypto_entry->block_length);
+ return(blocksize);
}
krb5_error_code
-kg_make_confounder(ed, buf)
- krb5_gss_enc_desc *ed;
+kg_make_confounder(context, key, buf)
+ krb5_context context;
+ krb5_keyblock *key;
unsigned char *buf;
{
- /* XXX Abstraction violation!!! */
+ krb5_error_code code;
+ size_t blocksize;
+ krb5_data random;
+
+ if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+ return(code);
- return(krb5_random_confounder(ed->eblock.crypto_entry->block_length, buf));
+ random.length = blocksize;
+ random.data = buf;
+
+ return(krb5_c_random_make_octets(context, &random));
}
int
-kg_encrypt_size(ed, n)
- krb5_gss_enc_desc *ed;
+kg_encrypt_size(context, key, n)
+ krb5_context context;
+ krb5_keyblock *key;
int n;
{
- return(krb5_encrypt_size(n, ed->eblock.crypto_entry));
+ krb5_error_code code;
+ size_t enclen;
+
+ if (code = krb5_c_encrypt_length(context, key->enctype, n, &enclen))
+ return(-1); /* XXX */
+
+ return(enclen);
}
krb5_error_code
-kg_encrypt(context, ed, iv, in, out, length)
+kg_encrypt(context, key, iv, in, out, length)
krb5_context context;
- krb5_gss_enc_desc *ed;
+ krb5_keyblock *key;
krb5_pointer iv;
krb5_pointer in;
krb5_pointer out;
int length;
{
krb5_error_code code;
- krb5_pointer tmp;
-
- if (! ed->processed) {
- if (code = krb5_process_key(context, &ed->eblock, ed->key))
- return(code);
- ed->processed = 1;
+ size_t blocksize;
+ krb5_data ivd, *pivd, inputd;
+ krb5_enc_data outputd;
+
+ if (iv) {
+ if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+ return(code);
+
+ ivd.length = blocksize;
+ ivd.data = iv;
+ pivd = &ivd;
+ } else {
+ pivd = NULL;
}
- /* this is lame. the krb5 encryption interfaces no longer allow
- you to encrypt in place. perhaps this should be fixed, but
- dealing here is easier for now --marc */
-
- if ((tmp = (krb5_pointer) xmalloc(length)) == NULL)
- return(ENOMEM);
+ inputd.length = length;
+ inputd.data = in;
- memcpy(tmp, in, length);
+ outputd.ciphertext.length = length;
+ outputd.ciphertext.data = out;
- code = krb5_encrypt(context, tmp, out, length, &ed->eblock,
- iv?iv:(krb5_pointer)zeros);
-
- xfree(tmp);
-
- if (code)
- return(code);
-
- return(0);
+ return(krb5_c_encrypt(context, key,
+ /* XXX this routine is only used for the old
+ bare-des stuff which doesn't use the
+ key usage */ 0, pivd, &inputd, &outputd));
}
/* length is the length of the cleartext. */
krb5_error_code
-kg_decrypt(context, ed, iv, in, out, length)
+kg_decrypt(context, key, iv, in, out, length)
krb5_context context;
- krb5_gss_enc_desc *ed;
+ krb5_keyblock *key;
krb5_pointer iv;
krb5_pointer in;
krb5_pointer out;
int length;
{
krb5_error_code code;
- int elen;
- char *buf;
-
- if (! ed->processed) {
- if (code = krb5_process_key(context, &ed->eblock, ed->key))
- return(code);
- ed->processed = 1;
+ size_t blocksize, enclen;
+ krb5_data ivd, *pivd, outputd;
+ krb5_enc_data inputd;
+
+ if (iv) {
+ if (code = krb5_c_block_size(context, key->enctype, &blocksize))
+ return(code);
+
+ ivd.length = blocksize;
+ ivd.data = iv;
+ pivd = &ivd;
+ } else {
+ pivd = NULL;
}
- elen = krb5_encrypt_size(length, ed->eblock.crypto_entry);
- if ((buf = (char *) xmalloc(elen)) == NULL)
- return(ENOMEM);
-
- if (code = krb5_decrypt(context, in, buf, elen, &ed->eblock,
- iv?iv:(krb5_pointer)zeros)) {
- xfree(buf);
- return(code);
- }
+ inputd.enctype = ENCTYPE_UNKNOWN;
+ inputd.ciphertext.length = length;
+ inputd.ciphertext.data = in;
- memcpy(out, buf, length);
- xfree(buf);
+ outputd.length = length;
+ outputd.data = out;
- return(0);
+ return(krb5_c_decrypt(context, key,
+ /* XXX this routine is only used for the old
+ bare-des stuff which doesn't use the
+ key usage */ 0, pivd, &inputd, &outputd));
}
diff --git a/src/lib/gssapi/krb5/util_ctxsetup.c b/src/lib/gssapi/krb5/util_ctxsetup.c
new file mode 100644
index 000000000..0add6bf73
--- /dev/null
+++ b/src/lib/gssapi/krb5/util_ctxsetup.c
@@ -0,0 +1,208 @@
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
+#include "gssapiP_krb5.h"
+
+/* from the token, flags is stored directly. nctypes/ctypes is
+ allocated and returns the length and list of ctypes in the token.
+ noptions/options lists all the options which the caller cares
+ about. Those which are present in the token are filled in; the
+ order and length are not changed. If an error is returned, the
+ option list is in an indeterminate state. */
+
+OM_uint32
+kg2_parse_token(minor_status, ptr, token_length, flags, nctypes, ctypes,
+ noptions, options, kmsg, mic)
+ OM_uint32 *minor_status;
+ unsigned char *ptr;
+ int token_length;
+ krb5_ui_4 *flags;
+ int *nctypes; /* OUT */
+ krb5_cksumtype **ctypes; /* OUT */
+ int noptions;
+ struct kg2_option *options; /* INOUT */
+ krb5_data *kmsg;
+ krb5_data *mic;
+{
+ int field_length, i;
+ int opt_id;
+
+ *ctypes = 0;
+
+ /* read the flags */
+
+ if (token_length < 4)
+ goto defective;
+ *flags = (ptr[0]<<24) | (ptr[1]<<16) | (ptr[2]<<8) | ptr[3];
+ ptr += 4;
+ token_length -= 4;
+
+ /* read out the token list */
+
+ if (token_length < 2)
+ goto defective;
+ field_length = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ token_length -= 2;
+
+ *nctypes = field_length;
+
+ if (*nctypes == 0) {
+ *minor_status = 0;
+ return(GSS_S_DEFECTIVE_TOKEN);
+ }
+
+ if ((*ctypes = (krb5_cksumtype *)
+ malloc((*nctypes) * sizeof(krb5_cksumtype))) == NULL) {
+ *minor_status = ENOMEM;
+ return(GSS_S_FAILURE);
+ }
+
+ for (i=0; i<field_length; i++) {
+ if (token_length < 4)
+ goto defective;
+
+ (*ctypes)[i] = (krb5_cksumtype) ((ptr[0]<<24) | (ptr[1]<<16) |
+ (ptr[2]<<8) | ptr[3]);
+ ptr += 4;
+ token_length -= 4;
+ }
+
+ do {
+ if (token_length < 4)
+ goto defective;
+ opt_id = (ptr[0]<<8) | ptr[1];
+ field_length = (ptr[2]<<8) | ptr[3];
+ ptr += 4;
+ token_length -= 4;
+
+ if (token_length < field_length)
+ goto defective;
+
+ for (i=0; i<noptions; i++) {
+ if (options[i].option_id = opt_id) {
+ options[i].length = field_length;
+ options[i].data = ptr;
+ }
+ break;
+ }
+
+ ptr += field_length;
+ token_length -= field_length;
+ } while (opt_id);
+
+ if (token_length < 2)
+ goto defective;
+ field_length = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ token_length -= 2;
+
+ if (token_length < field_length)
+ goto defective;
+
+ kmsg->length = field_length;
+ kmsg->data = ptr;
+
+ ptr += field_length;
+ token_length -= field_length;
+
+ /* if there's anything left, assume it's a mic. the mic isn't
+ necessarily present */
+
+ if (mic && token_length) {
+ if (token_length < 2)
+ goto defective;
+ field_length = (ptr[0]<<8) | ptr[1];
+ ptr += 2;
+ token_length -= 2;
+
+ if (token_length < field_length)
+ goto defective;
+
+ mic->length = field_length;
+ mic->data = ptr;
+
+ ptr += field_length;
+ token_length -= field_length;
+ } else if (mic) {
+ mic->length = 0;
+ mic->data = ptr;
+ }
+
+ if (token_length)
+ goto defective;
+
+ return(GSS_S_COMPLETE);
+
+defective:
+ if (*ctypes)
+ free(*ctypes);
+
+ *minor_status = 0;
+ return(GSS_S_DEFECTIVE_TOKEN);
+}
+
+/* nc1/c1 will be modified to contain the intersection of the
+ two lists. */
+
+void
+kg2_intersect_ctypes(nc1, c1, nc2, c2)
+ int *nc1;
+ krb5_cksumtype *c1;
+ int nc2;
+ const krb5_cksumtype *c2;
+{
+ int i, j, count;
+ krb5_cksumtype tmp;
+
+ count = 0;
+
+ for (i=0; i<*nc1; i++) {
+ /* first, check to make sure that c1[i] isn't a duplicate in c1 */
+ for (j=0; j<i; j++)
+ if (c1[i] == c1[j])
+ break;
+ if (j<i)
+ continue;
+ /* check if c1[i] is in c2. If it is, keep it by swapping
+ it into c1[count] and incrementing count. If count < i, then
+ that field has already been looked at and skipped as
+ not intersecting, which is ok. */
+
+ for (j=0; j<nc2; j++)
+ if (c1[i] == c2[j])
+ break;
+ if ((j<nc2) && (count != i)) {
+ tmp = c1[count];
+ c1[count] = c1[i];
+ c1[i] = tmp;
+ }
+ count++;
+ }
+
+ *nc1 = count;
+}
+
diff --git a/src/lib/gssapi/krb5/util_seed.c b/src/lib/gssapi/krb5/util_seed.c
index 14f365245..206ee68a7 100644
--- a/src/lib/gssapi/krb5/util_seed.c
+++ b/src/lib/gssapi/krb5/util_seed.c
@@ -36,24 +36,20 @@ kg_make_seed(context, key, seed)
unsigned char *seed;
{
krb5_error_code code;
- krb5_gss_enc_desc ed;
+ krb5_keyblock *tmpkey;
int i;
- if (code = krb5_copy_keyblock(context, key, &ed.key))
+ if (code = krb5_copy_keyblock(context, key, &tmpkey))
return(code);
/* reverse the key bytes, as per spec */
- for (i=0; i<ed.key->length; i++)
- ed.key->contents[i] = key->contents[key->length - 1 - i];
+ for (i=0; i<tmpkey->length; i++)
+ tmpkey->contents[i] = key->contents[key->length - 1 - i];
- krb5_use_enctype(context, &ed.eblock, ENCTYPE_DES_CBC_RAW);
- ed.processed = 0;
+ code = kg_encrypt(context, tmpkey, NULL, zeros, seed, 16);
- code = kg_encrypt(context, &ed, NULL, zeros, seed, 16);
-
- krb5_finish_key(context, &ed.eblock);
- krb5_free_keyblock(context, ed.key);
+ krb5_free_keyblock(context, tmpkey);
return(code);
}
diff --git a/src/lib/gssapi/krb5/util_seqnum.c b/src/lib/gssapi/krb5/util_seqnum.c
index ed9293f77..e14b2f3fe 100644
--- a/src/lib/gssapi/krb5/util_seqnum.c
+++ b/src/lib/gssapi/krb5/util_seqnum.c
@@ -27,9 +27,9 @@
*/
krb5_error_code
-kg_make_seq_num(context, ed, direction, seqnum, cksum, buf)
+kg_make_seq_num(context, key, direction, seqnum, cksum, buf)
krb5_context context;
- krb5_gss_enc_desc *ed;
+ krb5_keyblock *key;
int direction;
krb5_int32 seqnum;
unsigned char *cksum;
@@ -47,12 +47,12 @@ kg_make_seq_num(context, ed, direction, seqnum, cksum, buf)
plain[6] = direction;
plain[7] = direction;
- return(kg_encrypt(context, ed, cksum, plain, buf, 8));
+ return(kg_encrypt(context, key, cksum, plain, buf, 8));
}
-krb5_error_code kg_get_seq_num(context, ed, cksum, buf, direction, seqnum)
+krb5_error_code kg_get_seq_num(context, key, cksum, buf, direction, seqnum)
krb5_context context;
- krb5_gss_enc_desc *ed;
+ krb5_keyblock *key;
unsigned char *cksum;
unsigned char *buf;
int *direction;
@@ -61,7 +61,7 @@ krb5_error_code kg_get_seq_num(context, ed, cksum, buf, direction, seqnum)
krb5_error_code code;
unsigned char plain[8];
- if (code = kg_decrypt(context, ed, cksum, buf, plain, 8))
+ if (code = kg_decrypt(context, key, cksum, buf, plain, 8))
return(code);
if ((plain[4] != plain[5]) ||
diff --git a/src/lib/gssapi/krb5/wrap_size_limit.c b/src/lib/gssapi/krb5/wrap_size_limit.c
index f2366d16e..745949260 100644
--- a/src/lib/gssapi/krb5/wrap_size_limit.c
+++ b/src/lib/gssapi/krb5/wrap_size_limit.c
@@ -20,6 +20,32 @@
* PERFORMANCE OF THIS SOFTWARE.
*/
+/*
+ * Copyright (C) 1998 by the FundsXpress, INC.
+ *
+ * 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.
+ *
+ * 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 FundsXpress. not be used in advertising or publicity pertaining
+ * to distribution of the software without specific, written prior
+ * permission. FundsXpress makes no representations about the suitability of
+ * this software for any purpose. It is provided "as is" without express
+ * or implied warranty.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+ * WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ */
+
#include "gssapiP_krb5.h"
/*
@@ -39,8 +65,7 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
{
krb5_context context;
krb5_gss_ctx_id_rec *ctx;
- OM_uint32 cfsize;
- OM_uint32 ohlen;
+ krb5_error_code code;
if (GSS_ERROR(kg_get_context(minor_status, &context)))
return(GSS_S_FAILURE);
@@ -63,19 +88,86 @@ krb5_gss_wrap_size_limit(minor_status, context_handle, conf_req_flag,
return(GSS_S_NO_CONTEXT);
}
- /* Calculate the token size and subtract that from the output size */
- cfsize = (conf_req_flag) ? kg_confounder_size(&ctx->enc) : 0;
- ohlen = g_token_size((gss_OID) ctx->mech_used,
- (unsigned int) cfsize + ctx->cksum_size + 14);
+ if (ctx->gsskrb5_version == 2000) {
+ if (conf_req_flag) {
+ /* this is pretty gross. take the max output, and call
+ krb5_c_encrypt_length to see how much overhead is added
+ on. subtract that much, and see if it fits in the
+ requested space. If not, start subtracting 1 until it
+ does. This doesn't necessarily give us the optimal
+ packing, but I think that's ok (I could start adding 1
+ until I went over, but that seems like it's not worth
+ the effort). This is probably O(blocksize), but that's
+ never going to be large. */
+
+ OM_uint32 headerlen, plainlen;
+ size_t enclen;
+
+ headerlen = g_token_size((gss_OID) ctx->mech_used, 2);
+ plainlen = req_output_size - headerlen;
+
+ if (code = krb5_c_encrypt_length(context, ctx->enc->enctype,
+ plainlen, &enclen)) {
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ plainlen -= plainlen - (enclen - plainlen);
+
+ if (code = krb5_c_encrypt_length(context, ctx->enc->enctype,
+ plainlen, &enclen)) {
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
- if (ohlen < req_output_size)
+ while (headerlen + enclen > req_output_size) {
+ plainlen--;
+
+ if (code = krb5_c_encrypt_length(context, ctx->enc->enctype,
+ plainlen, &enclen)) {
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+ }
+
+ /* subtract off the fixed size inside the encrypted part */
+
+ plainlen -= 7;
+
+ *max_input_size = plainlen;
+ } else {
+ size_t cksumlen;
+ OM_uint32 headerlen;
+
+ if (code = krb5_c_checksum_length(context, ctx->ctypes[0],
+ &cksumlen)) {
+ *minor_status = code;
+ return(GSS_S_FAILURE);
+ }
+
+ headerlen = g_token_size((gss_OID) ctx->mech_used, 13 + cksumlen);
+
+ *max_input_size = req_output_size - headerlen;
+ }
+ } else {
+ OM_uint32 cfsize;
+ OM_uint32 ohlen;
+
+ /* Calculate the token size and subtract that from the output size */
+ cfsize = (conf_req_flag) ? kg_confounder_size(context, ctx->enc) : 0;
+ ohlen = g_token_size((gss_OID) ctx->mech_used,
+ (unsigned int) cfsize + ctx->cksum_size + 14);
+
+ if (ohlen < req_output_size)
/*
* Cannot have trailer length that will cause us to pad over
* our length
*/
*max_input_size = (req_output_size - ohlen - 1) & (~7);
- else
+ else
*max_input_size = 0;
+ }
+
*minor_status = 0;
return(GSS_S_COMPLETE);
}