From 201249ee71bf9de3f42c2bfd1b44459a304205d7 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Thu, 13 Aug 2009 15:12:01 +0900 Subject: [PATCH] Support ASN.1 BIT STRING and use it in SPNEGO. --- lib/util/asn1.c | 42 ++++++++++++++++++++++++++++++++++++ lib/util/asn1.h | 2 + source4/auth/gensec/spnego.c | 6 +++- source4/auth/gensec/spnego.h | 4 +- source4/auth/gensec/spnego_parse.c | 13 ++++++----- 5 files changed, 57 insertions(+), 10 deletions(-) diff --git a/lib/util/asn1.c b/lib/util/asn1.c index 317ee13..70c2c57 100644 --- a/lib/util/asn1.c +++ b/lib/util/asn1.c @@ -205,6 +205,15 @@ bool asn1_write_Integer(struct asn1_data *data, int i) return asn1_pop_tag(data); } +/* write a BIT STRING */ +bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding) +{ + if (!asn1_push_tag(data, ASN1_BIT_STRING)) return false; + if (!asn1_write_uint8(data, padding)) return false; + if (!asn1_write(data, p, length)) return false; + return asn1_pop_tag(data); +} + bool ber_write_OID_String(DATA_BLOB *blob, const char *OID) { uint_t v, v2; @@ -727,6 +736,39 @@ bool asn1_read_Integer(struct asn1_data *data, int *i) return asn1_end_tag(data); } +/* read a BIT STRING */ +bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding) +{ + int len; + ZERO_STRUCTP(blob); + if (!asn1_start_tag(data, ASN1_BIT_STRING)) return false; + len = asn1_tag_remaining(data); + if (len < 0) { + data->has_error = true; + return false; + } + if (!asn1_read_uint8(data, padding)) return false; + + *blob = data_blob_talloc(mem_ctx, NULL, len); + if (!blob->data) { + data->has_error = true; + return false; + } + if (asn1_read(data, blob->data, len - 1)) { + blob->length--; + blob->data[len] = 0; + asn1_end_tag(data); + } + + if (data->has_error) { + data_blob_free(blob); + *blob = data_blob_null; + *padding = 0; + return false; + } + return true; +} + /* read an integer */ bool asn1_read_enumerated(struct asn1_data *data, int *v) { diff --git a/lib/util/asn1.h b/lib/util/asn1.h index 4c66240..9abae50 100644 --- a/lib/util/asn1.h +++ b/lib/util/asn1.h @@ -60,6 +60,7 @@ bool asn1_push_tag(struct asn1_data *data, uint8_t tag); bool asn1_pop_tag(struct asn1_data *data); bool asn1_write_implicit_Integer(struct asn1_data *data, int i); bool asn1_write_Integer(struct asn1_data *data, int i); +bool asn1_write_BitString(struct asn1_data *data, const void *p, size_t length, uint8_t padding); bool ber_write_OID_String(DATA_BLOB *blob, const char *OID); bool asn1_write_OID(struct asn1_data *data, const char *OID); bool asn1_write_OctetString(struct asn1_data *data, const void *p, size_t length); @@ -90,6 +91,7 @@ bool asn1_read_OctetString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLO bool asn1_read_ContextSimple(struct asn1_data *data, uint8_t num, DATA_BLOB *blob); bool asn1_read_implicit_Integer(struct asn1_data *data, int *i); bool asn1_read_Integer(struct asn1_data *data, int *i); +bool asn1_read_BitString(struct asn1_data *data, TALLOC_CTX *mem_ctx, DATA_BLOB *blob, uint8_t *padding); bool asn1_read_enumerated(struct asn1_data *data, int *v); bool asn1_check_enumerated(struct asn1_data *data, int v); bool asn1_write_enumerated(struct asn1_data *data, uint8_t v); diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index b356720..867f234 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -628,7 +628,8 @@ static NTSTATUS gensec_spnego_create_negTokenInit(struct gensec_security *gensec /* List the remaining mechs as options */ spnego_out.negTokenInit.mechTypes = send_mech_types; - spnego_out.negTokenInit.reqFlags = 0; + spnego_out.negTokenInit.reqFlags = null_data_blob; + spnego_out.negTokenInit.reqFlagsPadding = 0; if (spnego_state->state_position == SPNEGO_SERVER_START) { /* server credentials */ @@ -844,7 +845,8 @@ static NTSTATUS gensec_spnego_update(struct gensec_security *gensec_security, TA /* compose reply */ spnego_out.type = SPNEGO_NEG_TOKEN_INIT; spnego_out.negTokenInit.mechTypes = my_mechs; - spnego_out.negTokenInit.reqFlags = 0; + spnego_out.negTokenInit.reqFlags = null_data_blob; + spnego_out.negTokenInit.reqFlagsPadding = 0; spnego_out.negTokenInit.mechListMIC = null_data_blob; spnego_out.negTokenInit.mechToken = unwrapped_out; diff --git a/source4/auth/gensec/spnego.h b/source4/auth/gensec/spnego.h index 24e80ec..9bf31a5 100644 --- a/source4/auth/gensec/spnego.h +++ b/source4/auth/gensec/spnego.h @@ -27,7 +27,6 @@ #define SPNEGO_ANON_FLAG 0x10 #define SPNEGO_CONF_FLAG 0x20 #define SPNEGO_INTEG_FLAG 0x40 -#define SPNEGO_REQ_FLAG 0x80 enum spnego_negResult { SPNEGO_ACCEPT_COMPLETED = 0, @@ -38,7 +37,8 @@ enum spnego_negResult { struct spnego_negTokenInit { const char **mechTypes; - int reqFlags; + DATA_BLOB reqFlags; + uint8_t reqFlagsPadding; DATA_BLOB mechToken; DATA_BLOB mechListMIC; char *targetPrincipal; diff --git a/source4/auth/gensec/spnego_parse.c b/source4/auth/gensec/spnego_parse.c index a79f15b..f558f67 100644 --- a/source4/auth/gensec/spnego_parse.c +++ b/source4/auth/gensec/spnego_parse.c @@ -63,8 +63,8 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, /* Read reqFlags */ case ASN1_CONTEXT(1): asn1_start_tag(asn1, ASN1_CONTEXT(1)); - asn1_read_Integer(asn1, &token->reqFlags); - token->reqFlags |= SPNEGO_REQ_FLAG; + asn1_read_BitString(asn1, mem_ctx, &token->reqFlags, + &token->reqFlagsPadding); asn1_end_tag(asn1); break; /* Read mechToken */ @@ -131,11 +131,11 @@ static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenIni } /* write reqFlags */ - if (token->reqFlags & SPNEGO_REQ_FLAG) { - int flags = token->reqFlags & ~SPNEGO_REQ_FLAG; - + if (token->reqFlags.length > 0) { asn1_push_tag(asn1, ASN1_CONTEXT(1)); - asn1_write_Integer(asn1, flags); + asn1_write_BitString(asn1, token->reqFlags.data, + token->reqFlags.length, + token->reqFlagsPadding); asn1_pop_tag(asn1); } @@ -354,6 +354,7 @@ bool spnego_free_data(struct spnego_data *spnego) if (spnego->negTokenInit.mechTypes) { talloc_free(spnego->negTokenInit.mechTypes); } + data_blob_free(&spnego->negTokenInit.reqFlags); data_blob_free(&spnego->negTokenInit.mechToken); data_blob_free(&spnego->negTokenInit.mechListMIC); talloc_free(spnego->negTokenInit.targetPrincipal); -- 1.6.3.3