Skip to content

Commit

Permalink
Use k5-der.h in GSS library
Browse files Browse the repository at this point in the history
Remove the DER implementations in lib/gssapi and use k5-der.h instead.
  • Loading branch information
greghudson committed Mar 24, 2023
1 parent 548da16 commit fdceb22
Show file tree
Hide file tree
Showing 12 changed files with 474 additions and 1,530 deletions.
4 changes: 2 additions & 2 deletions src/lib/gssapi/generic/gssapiP_generic.h
Original file line number Diff line number Diff line change
Expand Up @@ -153,8 +153,8 @@ int g_make_string_buffer (const char *str, gss_buffer_t buffer);

unsigned int g_token_size (const gss_OID_desc * mech, unsigned int body_size);

void g_make_token_header (const gss_OID_desc * mech, unsigned int body_size,
unsigned char **buf, int tok_type);
void g_make_token_header (struct k5buf *buf, const gss_OID_desc *mech,
size_t body_size, int tok_type);

/* flags for g_verify_token_header() */
#define G_VFY_TOKEN_HDR_WRAPPER_REQUIRED 0x01
Expand Down
199 changes: 39 additions & 160 deletions src/lib/gssapi/generic/util_token.c
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@
*/

#include "gssapiP_generic.h"
#include "k5-der.h"
#ifdef HAVE_MEMORY_H
#include <memory.h>
#endif
Expand All @@ -31,131 +32,33 @@
* $Id$
*/

/* XXXX this code currently makes the assumption that a mech oid will
never be longer than 127 bytes. This assumption is not inherent in
the interfaces, so the code can be fixed if the OSI namespace
balloons unexpectedly. */

/*
* Each token looks like this:
* 0x60 tag for APPLICATION 0, SEQUENCE
* (constructed, definite-length)
* <length> possible multiple bytes, need to parse/generate
* 0x06 tag for OBJECT IDENTIFIER
* <moid_length> compile-time constant string (assume 1 byte)
* <moid_bytes> compile-time constant string
* <inner_bytes> the ANY containing the application token
* bytes 0,1 are the token type
* bytes 2,n are the token data
*
* Note that the token type field is a feature of RFC 1964 mechanisms and
* is not used by other GSSAPI mechanisms. As such, a token type of -1
* is interpreted to mean that no token type should be expected or
* generated.
*
* For the purposes of this abstraction, the token "header" consists of
* the sequence tag and length octets, the mech OID DER encoding, and the
* first two inner bytes, which indicate the token type. The token
* "body" consists of everything else.
*/
static unsigned int
der_length_size(int length)
{
if (length < (1<<7))
return(1);
else if (length < (1<<8))
return(2);
#if INT_MAX == 0x7fff
else
return(3);
#else
else if (length < (1<<16))
return(3);
else if (length < (1<<24))
return(4);
else
return(5);
#endif
}

static void
der_write_length(unsigned char **buf, int length)
{
if (length < (1<<7)) {
*(*buf)++ = (unsigned char) length;
} else {
*(*buf)++ = (unsigned char) (der_length_size(length)+127);
#if INT_MAX > 0x7fff
if (length >= (1<<24))
*(*buf)++ = (unsigned char) (length>>24);
if (length >= (1<<16))
*(*buf)++ = (unsigned char) ((length>>16)&0xff);
#endif
if (length >= (1<<8))
*(*buf)++ = (unsigned char) ((length>>8)&0xff);
*(*buf)++ = (unsigned char) (length&0xff);
}
}

/* returns decoded length, or < 0 on failure. Advances buf and
decrements bufsize */

static int
der_read_length(unsigned char **buf, int *bufsize)
{
unsigned char sf;
int ret;

if (*bufsize < 1)
return(-1);
sf = *(*buf)++;
(*bufsize)--;
if (sf & 0x80) {
if ((sf &= 0x7f) > ((*bufsize)-1))
return(-1);
if (sf > sizeof(int))
return (-1);
ret = 0;
for (; sf; sf--) {
ret = (ret<<8) + (*(*buf)++);
(*bufsize)--;
}
} else {
ret = sf;
}

return(ret);
}

/* returns the length of a token, given the mech oid and the body size */

/* Return the length of an RFC 4121 token with RFC 2743 token framing, given
* the mech oid and the body size (without the two-byte RFC 4121 token ID). */
unsigned int
g_token_size(const gss_OID_desc * mech, unsigned int body_size)
{
/* set body_size to sequence contents size */
body_size += 4 + (unsigned int)mech->length; /* NEED overflow check */
return(1 + der_length_size(body_size) + body_size);
}
size_t mech_der_len = k5_der_value_len(mech->length);

/* fills in a buffer with the token header. The buffer is assumed to
be the right size. buf is advanced past the token header */
return k5_der_value_len(mech_der_len + 2 + body_size);
}

/*
* Add RFC 2743 generic token framing to buf with room left for body_size bytes
* in the sequence to be added by the caller. If tok_type is not -1, add it as
* a two-byte RFC 4121 token identifier after the framing and include room for
* it in the sequence.
*/
void
g_make_token_header(
const gss_OID_desc * mech,
unsigned int body_size,
unsigned char **buf,
int tok_type)
g_make_token_header(struct k5buf *buf, const gss_OID_desc *mech,
size_t body_size, int tok_type)
{
*(*buf)++ = 0x60;
der_write_length(buf, ((tok_type == -1) ? 2 : 4) + mech->length + body_size);
*(*buf)++ = 0x06;
*(*buf)++ = (unsigned char) mech->length;
TWRITE_STR(*buf, mech->elements, mech->length);
if (tok_type != -1) {
*(*buf)++ = (unsigned char) ((tok_type>>8)&0xff);
*(*buf)++ = (unsigned char) (tok_type&0xff);
}
size_t tok_len = (tok_type == -1) ? 0 : 2;
size_t seq_len = k5_der_value_len(mech->length) + body_size + tok_len;

k5_der_add_taglen(buf, 0x60, seq_len);
k5_der_add_value(buf, 0x06, mech->elements, mech->length);
if (tok_type != -1)
k5_buf_add_uint16_be(buf, tok_type);
}

/*
Expand All @@ -176,54 +79,30 @@ g_verify_token_header(
unsigned int toksize_in,
int flags)
{
unsigned char *buf = *buf_in;
int seqsize;
struct k5input in, mech_der;
gss_OID_desc toid;
int toksize = toksize_in;

if ((toksize-=1) < 0)
return(G_BAD_TOK_HEADER);
if (*buf++ != 0x60) {
if (flags & G_VFY_TOKEN_HDR_WRAPPER_REQUIRED)
return(G_BAD_TOK_HEADER);
buf--;
toksize++;
goto skip_wrapper;
k5_input_init(&in, *buf_in, toksize_in);

if (k5_der_get_value(&in, 0x60, &in)) {
if (in.ptr + in.len != *buf_in + toksize_in)
return G_BAD_TOK_HEADER;
if (!k5_der_get_value(&in, 0x06, &mech_der))
return G_BAD_TOK_HEADER;
toid.elements = (uint8_t *)mech_der.ptr;
toid.length = mech_der.len;
if (!g_OID_equal(&toid, mech))
return G_WRONG_MECH;
} else if (flags & G_VFY_TOKEN_HDR_WRAPPER_REQUIRED) {
return G_BAD_TOK_HEADER;
}

if ((seqsize = der_read_length(&buf, &toksize)) < 0)
return(G_BAD_TOK_HEADER);

if (seqsize != toksize)
return(G_BAD_TOK_HEADER);

if ((toksize-=1) < 0)
return(G_BAD_TOK_HEADER);
if (*buf++ != 0x06)
return(G_BAD_TOK_HEADER);

if ((toksize-=1) < 0)
return(G_BAD_TOK_HEADER);
toid.length = *buf++;

if ((toksize-=toid.length) < 0)
return(G_BAD_TOK_HEADER);
toid.elements = buf;
buf+=toid.length;

if (! g_OID_equal(&toid, mech))
return G_WRONG_MECH;
skip_wrapper:
if (tok_type != -1) {
if ((toksize-=2) < 0)
return(G_BAD_TOK_HEADER);

if ((*buf++ != ((tok_type>>8)&0xff)) ||
(*buf++ != (tok_type&0xff)))
return(G_WRONG_TOKID);
if (k5_input_get_uint16_be(&in) != tok_type)
return in.status ? G_BAD_TOK_HEADER : G_WRONG_TOKID;
}
*buf_in = buf;
*body_size = toksize;

*buf_in = (uint8_t *)in.ptr;
*body_size = in.len;
return 0;
}
26 changes: 11 additions & 15 deletions src/lib/gssapi/krb5/accept_sec_context.c
Original file line number Diff line number Diff line change
Expand Up @@ -684,6 +684,7 @@ kg_accept_krb5(minor_status, context_handle,
krb5_enctype negotiated_etype;
krb5_authdata_context ad_context = NULL;
krb5_ap_req *request = NULL;
struct k5buf buf;

code = krb5int_accessor (&kaccess, KRB5INT_ACCESS_VERSION);
if (code) {
Expand Down Expand Up @@ -1009,7 +1010,6 @@ kg_accept_krb5(minor_status, context_handle,
/* generate an AP_REP if necessary */

if (ctx->gss_flags & GSS_C_MUTUAL_FLAG) {
unsigned char * ptr3;
krb5_int32 seq_temp;
int cfx_generate_subkey;

Expand Down Expand Up @@ -1114,18 +1114,16 @@ kg_accept_krb5(minor_status, context_handle,
ctx->established = 1;

token.length = g_token_size(mech_used, ap_rep.length);

if ((token.value = (unsigned char *) gssalloc_malloc(token.length))
== NULL) {
token.value = gssalloc_malloc(token.length);
if (token.value == NULL) {
major_status = GSS_S_FAILURE;
code = ENOMEM;
goto fail;
}
ptr3 = token.value;
g_make_token_header(mech_used, ap_rep.length,
&ptr3, KG_TOK_CTX_AP_REP);

TWRITE_STR(ptr3, ap_rep.data, ap_rep.length);
k5_buf_init_fixed(&buf, token.value, token.length);
g_make_token_header(&buf, mech_used, ap_rep.length, KG_TOK_CTX_AP_REP);
k5_buf_add_len(&buf, ap_rep.data, ap_rep.length);
assert(buf.len == token.length);

ctx->established = 1;

Expand Down Expand Up @@ -1220,7 +1218,6 @@ kg_accept_krb5(minor_status, context_handle,
(request->ap_options & AP_OPTS_MUTUAL_REQUIRED) ||
major_status == GSS_S_CONTINUE_NEEDED)) {
unsigned int tmsglen;
int toktype;

/*
* The client is expecting a response, so we can send an
Expand All @@ -1242,17 +1239,16 @@ kg_accept_krb5(minor_status, context_handle,
goto done;

tmsglen = scratch.length;
toktype = KG_TOK_CTX_ERROR;

token.length = g_token_size(mech_used, tmsglen);
token.value = gssalloc_malloc(token.length);
if (!token.value)
goto done;
k5_buf_init_fixed(&buf, token.value, token.length);
g_make_token_header(&buf, mech_used, tmsglen, KG_TOK_CTX_ERROR);
k5_buf_add_len(&buf, scratch.data, scratch.length);
assert(buf.len == token.length);

ptr = token.value;
g_make_token_header(mech_used, tmsglen, &ptr, toktype);

TWRITE_STR(ptr, scratch.data, scratch.length);
krb5_free_data_contents(context, &scratch);

*output_token = token;
Expand Down

0 comments on commit fdceb22

Please sign in to comment.