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 <g...@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 <j...@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 <j...@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

Reply via email to