summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKouhei Sutou <kou@clear-code.com>2009-08-13 15:12:01 +0900
committerGünther Deschner <gd@samba.org>2009-09-17 20:10:54 +0200
commitf8dae40fc8e40f747a4571a2500bba9f1a790fa5 (patch)
tree778ee30d1a61903a9a4abe617777be6a48dfc3fa
parentc2055de162b154efb1aef0d2977f860a01ffdbbc (diff)
downloadsamba-f8dae40fc8e40f747a4571a2500bba9f1a790fa5.tar.gz
samba-f8dae40fc8e40f747a4571a2500bba9f1a790fa5.tar.bz2
samba-f8dae40fc8e40f747a4571a2500bba9f1a790fa5.zip
spnego: Support ASN.1 BIT STRING and use it in SPNEGO.
Signed-off-by: Günther Deschner <gd@samba.org>
-rw-r--r--lib/util/asn1.c42
-rw-r--r--lib/util/asn1.h2
-rw-r--r--libcli/auth/spnego.h4
-rw-r--r--libcli/auth/spnego_parse.c13
-rw-r--r--source3/utils/ntlm_auth.c6
-rw-r--r--source4/auth/gensec/spnego.c6
6 files changed, 61 insertions, 12 deletions
diff --git a/lib/util/asn1.c b/lib/util/asn1.c
index 317ee1314c..70c2c57450 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 4c6624056e..9abae50d64 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 08350a44ff..4b60f22d32 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 27e57740dc..3f7047b0e0 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 a607cb0658..3bdc45a6ef 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 8f06eab8bb..977d52ec10 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;