diff options
author | Andrew Tridgell <tridge@samba.org> | 2009-09-17 15:24:20 -0700 |
---|---|---|
committer | Andrew Tridgell <tridge@samba.org> | 2009-09-17 15:24:20 -0700 |
commit | 39971fff27f71b514308d10d7a2d8c3fb58c2420 (patch) | |
tree | 101f2adac9ef41af17579d22f6ddd56ada62ce5d /source4/auth/gensec | |
parent | 23676b6e9e8aad0ac2aa78d04e65f637b4551527 (diff) | |
parent | e71d9728f52e969e07927c5b38fa062c6ef6d1eb (diff) | |
download | samba-39971fff27f71b514308d10d7a2d8c3fb58c2420.tar.gz samba-39971fff27f71b514308d10d7a2d8c3fb58c2420.tar.bz2 samba-39971fff27f71b514308d10d7a2d8c3fb58c2420.zip |
Merge branch 'master' of /home/tridge/samba/git/combined
Diffstat (limited to 'source4/auth/gensec')
-rw-r--r-- | source4/auth/gensec/config.mk | 2 | ||||
-rw-r--r-- | source4/auth/gensec/spnego.c | 8 | ||||
-rw-r--r-- | source4/auth/gensec/spnego.h | 65 | ||||
-rw-r--r-- | source4/auth/gensec/spnego_parse.c | 408 |
4 files changed, 6 insertions, 477 deletions
diff --git a/source4/auth/gensec/config.mk b/source4/auth/gensec/config.mk index 84314f54e2..105a58b4ae 100644 --- a/source4/auth/gensec/config.mk +++ b/source4/auth/gensec/config.mk @@ -58,7 +58,7 @@ PRIVATE_DEPENDENCIES = ASN1_UTIL CREDENTIALS # End MODULE gensec_spnego ################################################ -gensec_spnego_OBJ_FILES = $(addprefix $(gensecsrcdir)/, spnego.o spnego_parse.o) +gensec_spnego_OBJ_FILES = $(addprefix $(gensecsrcdir)/, spnego.o) ../libcli/auth/spnego_parse.o $(eval $(call proto_header_template,$(gensecsrcdir)/spnego_proto.h,$(gensec_spnego_OBJ_FILES:.o=.c))) diff --git a/source4/auth/gensec/spnego.c b/source4/auth/gensec/spnego.c index b3567202c1..977d52ec10 100644 --- a/source4/auth/gensec/spnego.c +++ b/source4/auth/gensec/spnego.c @@ -23,7 +23,7 @@ */ #include "includes.h" -#include "auth/gensec/spnego.h" +#include "../libcli/auth/spnego.h" #include "librpc/gen_ndr/ndr_dcerpc.h" #include "auth/credentials/credentials.h" #include "auth/gensec/gensec.h" @@ -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 deleted file mode 100644 index 24e80ecb0b..0000000000 --- a/source4/auth/gensec/spnego.h +++ /dev/null @@ -1,65 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - RFC2478 Compliant SPNEGO implementation - - Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#define SPNEGO_DELEG_FLAG 0x01 -#define SPNEGO_MUTUAL_FLAG 0x02 -#define SPNEGO_REPLAY_FLAG 0x04 -#define SPNEGO_SEQUENCE_FLAG 0x08 -#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, - SPNEGO_ACCEPT_INCOMPLETE = 1, - SPNEGO_REJECT = 2, - SPNEGO_NONE_RESULT = 3 -}; - -struct spnego_negTokenInit { - const char **mechTypes; - int reqFlags; - DATA_BLOB mechToken; - DATA_BLOB mechListMIC; - char *targetPrincipal; -}; - -struct spnego_negTokenTarg { - uint8_t negResult; - const char *supportedMech; - DATA_BLOB responseToken; - DATA_BLOB mechListMIC; -}; - -struct spnego_data { - int type; - struct spnego_negTokenInit negTokenInit; - struct spnego_negTokenTarg negTokenTarg; -}; - -enum spnego_message_type { - SPNEGO_NEG_TOKEN_INIT = 0, - SPNEGO_NEG_TOKEN_TARG = 1, -}; - -#include "auth/gensec/spnego_proto.h" diff --git a/source4/auth/gensec/spnego_parse.c b/source4/auth/gensec/spnego_parse.c deleted file mode 100644 index a79f15b8ee..0000000000 --- a/source4/auth/gensec/spnego_parse.c +++ /dev/null @@ -1,408 +0,0 @@ -/* - Unix SMB/CIFS implementation. - - RFC2478 Compliant SPNEGO implementation - - Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2003 - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - - You should have received a copy of the GNU General Public License - along with this program. If not, see <http://www.gnu.org/licenses/>. -*/ - -#include "includes.h" -#include "auth/gensec/spnego.h" -#include "auth/gensec/gensec.h" -#include "../lib/util/asn1.h" - -static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, - struct spnego_negTokenInit *token) -{ - ZERO_STRUCTP(token); - - asn1_start_tag(asn1, ASN1_CONTEXT(0)); - asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - - while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) { - int i; - uint8_t context; - if (!asn1_peek_uint8(asn1, &context)) { - asn1->has_error = true; - break; - } - - switch (context) { - /* Read mechTypes */ - case ASN1_CONTEXT(0): - asn1_start_tag(asn1, ASN1_CONTEXT(0)); - asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - - token->mechTypes = talloc(NULL, const char *); - for (i = 0; !asn1->has_error && - 0 < asn1_tag_remaining(asn1); i++) { - token->mechTypes = talloc_realloc(NULL, - token->mechTypes, - const char *, i+2); - asn1_read_OID(asn1, token->mechTypes, token->mechTypes + i); - } - token->mechTypes[i] = NULL; - - asn1_end_tag(asn1); - asn1_end_tag(asn1); - break; - /* 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_end_tag(asn1); - break; - /* Read mechToken */ - case ASN1_CONTEXT(2): - asn1_start_tag(asn1, ASN1_CONTEXT(2)); - asn1_read_OctetString(asn1, mem_ctx, &token->mechToken); - asn1_end_tag(asn1); - break; - /* Read mecListMIC */ - case ASN1_CONTEXT(3): - { - uint8_t type_peek; - asn1_start_tag(asn1, ASN1_CONTEXT(3)); - if (!asn1_peek_uint8(asn1, &type_peek)) { - asn1->has_error = true; - break; - } - if (type_peek == ASN1_OCTET_STRING) { - asn1_read_OctetString(asn1, mem_ctx, - &token->mechListMIC); - } else { - /* RFC 2478 says we have an Octet String here, - but W2k sends something different... */ - char *mechListMIC; - asn1_push_tag(asn1, ASN1_SEQUENCE(0)); - asn1_push_tag(asn1, ASN1_CONTEXT(0)); - asn1_read_GeneralString(asn1, mem_ctx, &mechListMIC); - asn1_pop_tag(asn1); - asn1_pop_tag(asn1); - - token->targetPrincipal = mechListMIC; - } - asn1_end_tag(asn1); - break; - } - default: - asn1->has_error = true; - break; - } - } - - asn1_end_tag(asn1); - asn1_end_tag(asn1); - - return !asn1->has_error; -} - -static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenInit *token) -{ - asn1_push_tag(asn1, ASN1_CONTEXT(0)); - asn1_push_tag(asn1, ASN1_SEQUENCE(0)); - - /* Write mechTypes */ - if (token->mechTypes && *token->mechTypes) { - int i; - - asn1_push_tag(asn1, ASN1_CONTEXT(0)); - asn1_push_tag(asn1, ASN1_SEQUENCE(0)); - for (i = 0; token->mechTypes[i]; i++) { - asn1_write_OID(asn1, token->mechTypes[i]); - } - asn1_pop_tag(asn1); - asn1_pop_tag(asn1); - } - - /* write reqFlags */ - if (token->reqFlags & SPNEGO_REQ_FLAG) { - int flags = token->reqFlags & ~SPNEGO_REQ_FLAG; - - asn1_push_tag(asn1, ASN1_CONTEXT(1)); - asn1_write_Integer(asn1, flags); - asn1_pop_tag(asn1); - } - - /* write mechToken */ - if (token->mechToken.data) { - asn1_push_tag(asn1, ASN1_CONTEXT(2)); - asn1_write_OctetString(asn1, token->mechToken.data, - token->mechToken.length); - asn1_pop_tag(asn1); - } - - /* write mechListMIC */ - if (token->mechListMIC.data) { - asn1_push_tag(asn1, ASN1_CONTEXT(3)); -#if 0 - /* This is what RFC 2478 says ... */ - asn1_write_OctetString(asn1, token->mechListMIC.data, - token->mechListMIC.length); -#else - /* ... but unfortunately this is what Windows - sends/expects */ - asn1_push_tag(asn1, ASN1_SEQUENCE(0)); - asn1_push_tag(asn1, ASN1_CONTEXT(0)); - asn1_push_tag(asn1, ASN1_GENERAL_STRING); - asn1_write(asn1, token->mechListMIC.data, - token->mechListMIC.length); - asn1_pop_tag(asn1); - asn1_pop_tag(asn1); - asn1_pop_tag(asn1); -#endif - asn1_pop_tag(asn1); - } - - asn1_pop_tag(asn1); - asn1_pop_tag(asn1); - - return !asn1->has_error; -} - -static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx, - struct spnego_negTokenTarg *token) -{ - ZERO_STRUCTP(token); - - asn1_start_tag(asn1, ASN1_CONTEXT(1)); - asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - - while (!asn1->has_error && 0 < asn1_tag_remaining(asn1)) { - uint8_t context; - if (!asn1_peek_uint8(asn1, &context)) { - asn1->has_error = true; - break; - } - - switch (context) { - case ASN1_CONTEXT(0): - asn1_start_tag(asn1, ASN1_CONTEXT(0)); - asn1_start_tag(asn1, ASN1_ENUMERATED); - asn1_read_uint8(asn1, &token->negResult); - asn1_end_tag(asn1); - asn1_end_tag(asn1); - break; - case ASN1_CONTEXT(1): - asn1_start_tag(asn1, ASN1_CONTEXT(1)); - asn1_read_OID(asn1, mem_ctx, &token->supportedMech); - asn1_end_tag(asn1); - break; - case ASN1_CONTEXT(2): - asn1_start_tag(asn1, ASN1_CONTEXT(2)); - asn1_read_OctetString(asn1, mem_ctx, &token->responseToken); - asn1_end_tag(asn1); - break; - case ASN1_CONTEXT(3): - asn1_start_tag(asn1, ASN1_CONTEXT(3)); - asn1_read_OctetString(asn1, mem_ctx, &token->mechListMIC); - asn1_end_tag(asn1); - break; - default: - asn1->has_error = true; - break; - } - } - - asn1_end_tag(asn1); - asn1_end_tag(asn1); - - return !asn1->has_error; -} - -static bool write_negTokenTarg(struct asn1_data *asn1, struct spnego_negTokenTarg *token) -{ - asn1_push_tag(asn1, ASN1_CONTEXT(1)); - asn1_push_tag(asn1, ASN1_SEQUENCE(0)); - - if (token->negResult != SPNEGO_NONE_RESULT) { - asn1_push_tag(asn1, ASN1_CONTEXT(0)); - asn1_write_enumerated(asn1, token->negResult); - asn1_pop_tag(asn1); - } - - if (token->supportedMech) { - asn1_push_tag(asn1, ASN1_CONTEXT(1)); - asn1_write_OID(asn1, token->supportedMech); - asn1_pop_tag(asn1); - } - - if (token->responseToken.data) { - asn1_push_tag(asn1, ASN1_CONTEXT(2)); - asn1_write_OctetString(asn1, token->responseToken.data, - token->responseToken.length); - asn1_pop_tag(asn1); - } - - if (token->mechListMIC.data) { - asn1_push_tag(asn1, ASN1_CONTEXT(3)); - asn1_write_OctetString(asn1, token->mechListMIC.data, - token->mechListMIC.length); - asn1_pop_tag(asn1); - } - - asn1_pop_tag(asn1); - asn1_pop_tag(asn1); - - return !asn1->has_error; -} - -ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data *token) -{ - struct asn1_data *asn1; - ssize_t ret = -1; - uint8_t context; - - ZERO_STRUCTP(token); - - if (data.length == 0) { - return ret; - } - - asn1 = asn1_init(mem_ctx); - if (asn1 == NULL) { - return -1; - } - - asn1_load(asn1, data); - - if (!asn1_peek_uint8(asn1, &context)) { - asn1->has_error = true; - } else { - switch (context) { - case ASN1_APPLICATION(0): - asn1_start_tag(asn1, ASN1_APPLICATION(0)); - asn1_check_OID(asn1, GENSEC_OID_SPNEGO); - if (read_negTokenInit(asn1, mem_ctx, &token->negTokenInit)) { - token->type = SPNEGO_NEG_TOKEN_INIT; - } - asn1_end_tag(asn1); - break; - case ASN1_CONTEXT(1): - if (read_negTokenTarg(asn1, mem_ctx, &token->negTokenTarg)) { - token->type = SPNEGO_NEG_TOKEN_TARG; - } - break; - default: - asn1->has_error = true; - break; - } - } - - if (!asn1->has_error) ret = asn1->ofs; - asn1_free(asn1); - - return ret; -} - -ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_data *spnego) -{ - struct asn1_data *asn1 = asn1_init(mem_ctx); - ssize_t ret = -1; - - if (asn1 == NULL) { - return -1; - } - - switch (spnego->type) { - case SPNEGO_NEG_TOKEN_INIT: - asn1_push_tag(asn1, ASN1_APPLICATION(0)); - asn1_write_OID(asn1, GENSEC_OID_SPNEGO); - write_negTokenInit(asn1, &spnego->negTokenInit); - asn1_pop_tag(asn1); - break; - case SPNEGO_NEG_TOKEN_TARG: - write_negTokenTarg(asn1, &spnego->negTokenTarg); - break; - default: - asn1->has_error = true; - break; - } - - if (!asn1->has_error) { - *blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length); - ret = asn1->ofs; - } - asn1_free(asn1); - - return ret; -} - -bool spnego_free_data(struct spnego_data *spnego) -{ - bool ret = true; - - if (!spnego) goto out; - - switch(spnego->type) { - case SPNEGO_NEG_TOKEN_INIT: - if (spnego->negTokenInit.mechTypes) { - talloc_free(spnego->negTokenInit.mechTypes); - } - data_blob_free(&spnego->negTokenInit.mechToken); - data_blob_free(&spnego->negTokenInit.mechListMIC); - talloc_free(spnego->negTokenInit.targetPrincipal); - break; - case SPNEGO_NEG_TOKEN_TARG: - if (spnego->negTokenTarg.supportedMech) { - talloc_free(discard_const(spnego->negTokenTarg.supportedMech)); - } - data_blob_free(&spnego->negTokenTarg.responseToken); - data_blob_free(&spnego->negTokenTarg.mechListMIC); - break; - default: - ret = false; - break; - } - ZERO_STRUCTP(spnego); -out: - return ret; -} - -bool spnego_write_mech_types(TALLOC_CTX *mem_ctx, - const char **mech_types, - DATA_BLOB *blob) -{ - struct asn1_data *asn1 = asn1_init(mem_ctx); - - /* Write mechTypes */ - if (mech_types && *mech_types) { - int i; - - asn1_push_tag(asn1, ASN1_SEQUENCE(0)); - for (i = 0; mech_types[i]; i++) { - asn1_write_OID(asn1, mech_types[i]); - } - asn1_pop_tag(asn1); - } - - if (asn1->has_error) { - asn1_free(asn1); - return false; - } - - *blob = data_blob_talloc(mem_ctx, asn1->data, asn1->length); - if (blob->length != asn1->length) { - asn1_free(asn1); - return false; - } - - asn1_free(asn1); - - return true; -} |