From f8dae40fc8e40f747a4571a2500bba9f1a790fa5 Mon Sep 17 00:00:00 2001 From: Kouhei Sutou Date: Thu, 13 Aug 2009 15:12:01 +0900 Subject: [PATCH] spnego: Support ASN.1 BIT STRING and use it in SPNEGO. MIME-Version: 1.0 Content-Type: text/plain; charset=utf8 Content-Transfer-Encoding: 8bit Signed-off-by: Günther Deschner --- lib/util/asn1.c | 42 ++++++++++++++++++++++++++++++++++++ lib/util/asn1.h | 2 ++ libcli/auth/spnego.h | 4 ++-- libcli/auth/spnego_parse.c | 13 +++++------ source3/utils/ntlm_auth.c | 6 ++++-- source4/auth/gensec/spnego.c | 6 ++++-- 6 files changed, 61 insertions(+), 12 deletions(-) diff --git a/lib/util/asn1.c b/lib/util/asn1.c index 317ee1314c6..70c2c57450c 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 4c6624056e0..9abae50d64e 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/libcli/auth/spnego.h b/libcli/auth/spnego.h index 08350a44ff3..4b60f22d32d 100644 --- a/libcli/auth/spnego.h +++ b/libcli/auth/spnego.h @@ -32,7 +32,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, @@ -43,7 +42,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/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c index 27e57740dc2..3f7047b0e0b 100644 --- a/libcli/auth/spnego_parse.c +++ b/libcli/auth/spnego_parse.c @@ -62,8 +62,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 */ @@ -130,11 +130,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); } @@ -353,6 +353,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); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index a607cb06587..3bdc45a6ef7 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1454,7 +1454,8 @@ static bool manage_client_ntlmssp_init(struct spnego_data spnego) spnego.type = SPNEGO_NEG_TOKEN_INIT; spnego.negTokenInit.mechTypes = my_mechs; - spnego.negTokenInit.reqFlags = 0; + spnego.negTokenInit.reqFlags = data_blob_null; + spnego.negTokenInit.reqFlagsPadding = 0; spnego.negTokenInit.mechListMIC = null_blob; status = ntlmssp_update(client_ntlmssp_state, null_blob, @@ -1609,7 +1610,8 @@ static bool manage_client_krb5_init(struct spnego_data spnego) reply.type = SPNEGO_NEG_TOKEN_INIT; reply.negTokenInit.mechTypes = my_mechs; - reply.negTokenInit.reqFlags = 0; + reply.negTokenInit.reqFlags = data_blob_null; + reply.negTokenInit.reqFlagsPadding = 0; reply.negTokenInit.mechToken = tkt; reply.negTokenInit.mechListMIC = data_blob_null; diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index 8f06eab8bbe..977d52ec107 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; -- 2.34.1