[SCM] Samba Shared Repository - branch master updated - tevent-0-9-8-375-g503d035

Günther Deschner gd at samba.org
Wed Sep 16 17:13:15 MDT 2009


The branch, master has been updated
       via  503d0358140fbf56bd83090f143272aeb770baa9 (commit)
      from  83023462f95f60ecfd3019abe896cca1d2aed771 (commit)

http://gitweb.samba.org/?p=samba.git;a=shortlog;h=master


- Log -----------------------------------------------------------------
commit 503d0358140fbf56bd83090f143272aeb770baa9
Author: Günther Deschner <gd at samba.org>
Date:   Thu Sep 17 00:21:01 2009 +0200

    spnego: share spnego_parse.
    
    Guenther

-----------------------------------------------------------------------

Summary of changes:
 libcli/auth/spnego.h               |   70 ++++++
 libcli/auth/spnego_parse.c         |  407 +++++++++++++++++++++++++++++++++++
 source3/Makefile.in                |    2 +-
 source3/include/ads.h              |    6 +
 source3/include/includes.h         |    1 -
 source3/include/proto.h            |    6 -
 source3/include/spnego.h           |   81 -------
 source3/libads/sasl.c              |    1 +
 source3/libsmb/cliconnect.c        |    1 +
 source3/libsmb/clifsinfo.c         |    1 +
 source3/libsmb/clispnego.c         |   15 +-
 source3/libsmb/spnego.c            |  362 --------------------------------
 source3/rpc_client/cli_pipe.c      |    1 +
 source3/rpc_server/srv_pipe.c      |    1 +
 source3/smbd/negprot.c             |    1 +
 source3/smbd/seal.c                |    1 +
 source3/smbd/sesssetup.c           |    1 +
 source3/smbd/smb2_sesssetup.c      |    1 +
 source3/utils/ntlm_auth.c          |   43 ++--
 source4/auth/gensec/config.mk      |    2 +-
 source4/auth/gensec/spnego.c       |    2 +-
 source4/auth/gensec/spnego.h       |   65 ------
 source4/auth/gensec/spnego_parse.c |  408 ------------------------------------
 23 files changed, 527 insertions(+), 952 deletions(-)
 create mode 100644 libcli/auth/spnego.h
 create mode 100644 libcli/auth/spnego_parse.c
 delete mode 100644 source3/include/spnego.h
 delete mode 100644 source3/libsmb/spnego.c
 delete mode 100644 source4/auth/gensec/spnego.h
 delete mode 100644 source4/auth/gensec/spnego_parse.c


Changeset truncated at 500 lines:

diff --git a/libcli/auth/spnego.h b/libcli/auth/spnego.h
new file mode 100644
index 0000000..250ffed
--- /dev/null
+++ b/libcli/auth/spnego.h
@@ -0,0 +1,70 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   RFC2478 Compliant SPNEGO implementation
+
+   Copyright (C) Jim McDonough <jmcd at 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 OID_SPNEGO "1.3.6.1.5.5.2"
+#define OID_NTLMSSP "1.3.6.1.4.1.311.2.2.10"
+#define OID_KERBEROS5_OLD "1.2.840.48018.1.2.2"
+#define OID_KERBEROS5 "1.2.840.113554.1.2.2"
+
+#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/libcli/auth/spnego_parse.c b/libcli/auth/spnego_parse.c
new file mode 100644
index 0000000..27e5774
--- /dev/null
+++ b/libcli/auth/spnego_parse.c
@@ -0,0 +1,407 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   RFC2478 Compliant SPNEGO implementation
+
+   Copyright (C) Jim McDonough <jmcd at 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 "../libcli/auth/spnego.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, 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, 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;
+}
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 65feb84..1b93631 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -1297,7 +1297,7 @@ TDBTORTURE_OBJ = @tdbdir@/tools/tdbtorture.o $(LIBREPLACE_OBJ) \
 NTLM_AUTH_OBJ1 = utils/ntlm_auth.o utils/ntlm_auth_diagnostics.o
 
 NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
-		../lib/util/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
+		../lib/util/asn1.o ../libcli/auth/spnego_parse.o libsmb/clikrb5.o libads/kerberos.o \
 		$(LIBADS_SERVER_OBJ) \


-- 
Samba Shared Repository


More information about the samba-cvs mailing list