[PATCH] New spnego_auth{start|update|end} functions
Anthony Liguori
aliguor at us.ibm.com
Fri Aug 1 20:02:40 GMT 2003
All,
This patch introduces a set of routines to access spnego authenticate
similar to the ntlmssp_server_start, _update, _end functions.
A sample usage would be:
SPNEGO_STATE *spnego_state = 0;
spnego_auth_start(&spnego_state, True); /* true for server, false for
client */
spnego_register_ntlmssp(spnego_state); /* add NTLMSSP a supported SPNEGO
mechanism */
/* get packet in blob request */
while spnego_auth_update(spnego_state, request, &reply) ==
NT_STATUS_MORE_PROCESSING_REQUIRED
send reply
read request
end while
spnego_auth_end(&spnego_state);
Anthony Liguori
Linux/Active Directory Interoperability
Linux Technology Center (LTC) - IBM Austin
E-mail: aliguor at us.ibm.com
Phone: (512) 838-1208
-------------- next part --------------
diff -Npur --exclude=CVS --exclude='*.bak' --exclude='*.o' --exclude='*.po' --exclude='*.so' --exclude='.#*' --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude='*proto*.h' --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude='config.*' --exclude=bin --exclude='*.configure' --exclude=autom4te.cache --exclude='build_options.c*' --exclude=TAGS --exclude='*~' --exclude='#*#' ../../samba-prestine/source/include/spnego.h ./include/spnego.h
--- ../../samba-prestine/source/include/spnego.h 2003-07-31 05:21:13.000000000 -0500
+++ ./include/spnego.h 2003-07-31 16:38:26.000000000 -0500
@@ -43,7 +43,7 @@ typedef enum _spnego_negResult {
} negResult_t;
typedef struct spnego_negTokenInit {
- const char **mechTypes;
+ char **mechTypes;
int reqFlags;
DATA_BLOB mechToken;
DATA_BLOB mechListMIC;
@@ -51,15 +51,33 @@ typedef struct spnego_negTokenInit {
typedef struct spnego_negTokenTarg {
uint8 negResult;
- const char *supportedMech;
+ char *supportedMech;
DATA_BLOB responseToken;
DATA_BLOB mechListMIC;
} negTokenTarg_t;
-typedef struct spnego_spnego {
+typedef struct spnego_data {
int type;
negTokenInit_t negTokenInit;
negTokenTarg_t negTokenTarg;
} SPNEGO_DATA;
+struct spnego_state;
+typedef struct spnego_sec_mech {
+ const char *oid;
+ void *state;
+ NTSTATUS (*hint)(struct spnego_sec_mech *, DATA_BLOB *);
+ NTSTATUS (*step)(struct spnego_sec_mech *,
+ const DATA_BLOB, DATA_BLOB *);
+ NTSTATUS (*end)(struct spnego_state *);
+ struct spnego_sec_mech *next;
+} SPNEGO_SEC_MECH;
+
+typedef struct spnego_state {
+ TALLOC_CTX *mem_ctx;
+ SPNEGO_SEC_MECH *mech_list;
+ SPNEGO_SEC_MECH *mech;
+ BOOL server;
+} SPNEGO_STATE;
+
#endif
diff -Npur --exclude=CVS --exclude='*.bak' --exclude='*.o' --exclude='*.po' --exclude='*.so' --exclude='.#*' --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude='*proto*.h' --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude='config.*' --exclude=bin --exclude='*.configure' --exclude=autom4te.cache --exclude='build_options.c*' --exclude=TAGS --exclude='*~' --exclude='#*#' ../../samba-prestine/source/libsmb/spnego.c ./libsmb/spnego.c
--- ../../samba-prestine/source/libsmb/spnego.c 2003-07-31 10:53:59.000000000 -0500
+++ ./libsmb/spnego.c 2003-08-01 09:47:04.000000000 -0500
@@ -26,6 +26,9 @@
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_AUTH
+/*****************************************************************************
+ * Private SPNEGO Parsing routines
+ ****************************************************************************/
static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token)
{
ZERO_STRUCTP(token);
@@ -213,6 +216,9 @@ static BOOL write_negTokenTarg(ASN1_DATA
return !asn1->has_error;
}
+/*****************************************************************************
+ * Public SPNEGO Parsing routines
+ ****************************************************************************/
ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token)
{
ASN1_DATA asn1;
@@ -311,3 +317,226 @@ out:
return ret;
}
+/*****************************************************************************
+ * Private SPNEGO negotiation routines
+ ****************************************************************************/
+static NTSTATUS spnego_negotiate(SPNEGO_STATE *spnego_state,
+ const DATA_BLOB request, DATA_BLOB *reply)
+{
+ SPNEGO_DATA spnego;
+ NTSTATUS ret = NT_STATUS_INVALID_PARAMETER;
+ SPNEGO_SEC_MECH *mech;
+
+ if (-1 == read_spnego_data(request, &spnego)) {
+ return ret;
+ }
+
+ if (SPNEGO_NEG_TOKEN_INIT != spnego.type) {
+ DEBUG(1, ("spnego_negotiate: expected negTokenInit got"
+ " negTokenTarg\n"));
+ goto out;
+ }
+ if (!spnego.negTokenInit.mechTypes ||
+ !spnego.negTokenInit.mechTypes[0]) {
+ DEBUG(1, ("spnego_negotiate: no mechType specificed\n"));
+ goto out;
+ }
+
+ for (mech = spnego_state->mech_list;
+ mech &&strcmp(spnego.negTokenInit.mechTypes[0],
+ mech->oid); mech = mech->next) { }
+
+ if (!mech) {
+ DEBUG(1, ("spnego_negotiate: unknown OID %s\n",
+ spnego.negTokenInit.mechTypes[0]));
+ goto out;
+ }
+
+ spnego_state->mech = mech;
+
+ ret = spnego_state->mech->step(spnego_state->mech,
+ spnego.negTokenInit.mechToken,
+ reply);
+out:
+ free_spnego_data(&spnego);
+ return ret;
+}
+
+static NTSTATUS spnego_choose_mech(SPNEGO_STATE *spnego_state,
+ const DATA_BLOB request,
+ DATA_BLOB *reply)
+{
+ SPNEGO_DATA spnego;
+ NTSTATUS ret = NT_STATUS_INVALID_PARAMETER;
+ int i;
+ SPNEGO_SEC_MECH *mech;
+
+ if (-1 == read_spnego_data(request, &spnego)) {
+ return ret;
+ }
+
+ if (SPNEGO_NEG_TOKEN_INIT != spnego.type) {
+ DEBUG(1, ("spnego_choose_mech: expected negTokenInit got"
+ " negTokenTarg\n"));
+ goto out;
+ }
+ if (!spnego.negTokenInit.mechTypes) {
+ DEBUG(1, ("spnego_choose_mech: no mechType specificed\n"));
+ goto out;
+ }
+
+ for (i = 0; spnego.negTokenInit.mechTypes[i]; i++) {
+ for (mech = spnego_state->mech_list; mech; mech = mech->next) {
+ if (!strcmp(spnego.negTokenInit.mechTypes[i],
+ mech->oid)) {
+ break;
+ }
+ }
+ }
+
+ if (!mech) {
+ DEBUG(1, ("spnego_choose_mech: cannot negotiate an acceptable"
+ " mechType\n"));
+ goto out;
+ }
+ free_spnego_data(&spnego);
+
+ spnego_state->mech = mech;
+
+ spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 2);
+ spnego.negTokenInit.mechTypes[0] =
+ smb_xstrdup(spnego_state->mech->oid);
+ spnego.negTokenInit.mechTypes[1] = NULL;
+ ret = spnego_state->mech->hint(spnego_state->mech,
+ &spnego.negTokenInit.mechToken);
+
+ if (-1 == write_spnego_data(reply, &spnego)) {
+ ret = NT_STATUS_INVALID_PARAMETER;
+ }
+
+out:
+ free_spnego_data(&spnego);
+ return ret;
+}
+
+static NTSTATUS spnego_mech_offerings(SPNEGO_STATE *spnego_state,
+ const DATA_BLOB unused,
+ DATA_BLOB *reply)
+{
+ SPNEGO_DATA spnego;
+ NTSTATUS ret;
+ SPNEGO_SEC_MECH *mech;
+ int capacity = 0;
+ int i = 0;
+
+ ZERO_STRUCT(spnego);
+
+ /* Server negTokenInit (mech offerings) */
+ spnego.type = SPNEGO_NEG_TOKEN_INIT;
+
+ for (mech = spnego_state->mech_list; mech; mech = mech->next) {
+ if ((i + 1) >= capacity) {
+ capacity += 10;
+ spnego.negTokenInit.mechTypes =
+ talloc_realloc(spnego_state->mem_ctx,
+ spnego.negTokenInit.mechTypes,
+ capacity * sizeof(char *));
+ }
+
+ spnego.negTokenInit.mechTypes[i] =
+ talloc_strdup(spnego_state->mem_ctx,
+ spnego_state->mech_list[i].oid);
+ i++;
+ }
+
+ spnego.negTokenInit.mechTypes[i] = NULL;
+
+ if (!spnego.negTokenInit.mechTypes[0]) {
+ DEBUG(0, ("spnego_mech_offerings: no mechTypes!\n"));
+ ret = NT_STATUS_INVALID_PARAMETER;
+ goto out;
+ }
+
+ ret = spnego_state->mech_list->hint(spnego_state->mech_list,
+ &spnego.negTokenInit.mechListMIC);
+
+ if (-1 == write_spnego_data(reply, &spnego)) {
+ ret = NT_STATUS_INVALID_PARAMETER;
+ }
+out:
+ free_spnego_data(&spnego);
+ return ret;
+}
+
+/*****************************************************************************
+ * Public SPNEGO state machine functions
+ ****************************************************************************/
+/**
+ * Create an SPNEGO state machine
+ *
+ * @param spnego_state [out] the allocated SPNEGO state
+ */
+NTSTATUS spnego_auth_start(SPNEGO_STATE **spnego_state, BOOL server)
+{
+ TALLOC_CTX *ctx = talloc_init("SPNEGO context");
+ int i;
+
+ *spnego_state = talloc_zero(ctx, sizeof(**spnego_state));
+ if (!*spnego_state) {
+ DEBUG(0,("spnego_auth_start: talloc failed\n"));
+ talloc_destroy(ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ (*spnego_state)->mem_ctx = ctx;
+ (*spnego_state)->server = server;
+
+ return NT_STATUS_OK;
+}
+
+/**
+ * Destroy an SPNEGO state machine
+ *
+ * @param spnego_state [in] the allocated SPNEGO state
+ */
+NTSTATUS spnego_auth_end(SPNEGO_STATE **spnego_state)
+{
+ NTSTATUS ret = NT_STATUS_OK;
+
+ if ((*spnego_state)->mech) {
+ ret = (*spnego_state)->mech->end(*spnego_state);
+ }
+
+ talloc_destroy((*spnego_state)->mem_ctx);
+ *spnego_state = NULL;
+
+ return ret;
+}
+
+/**
+ * Next state function for the SPNEGO state machine
+ *
+ * @param spnego_state SPNEGO state
+ * @param request The request as a DATA_BLOB--an empty request is valid on if
+ * the server is initiating the exchange
+ * @param reply The reply as an allocated DATA_BLOB--caller must free
+ * @return Errors, NT_STATUS_MORE_PROCESSING_REQUIRED or NT_STATUS_OK
+ */
+NTSTATUS spnego_auth_update(SPNEGO_STATE *spnego_state,
+ const DATA_BLOB request, DATA_BLOB *reply)
+{
+ NTSTATUS ret;
+
+ if (spnego_state->mech) {
+ ret = spnego_state->mech->step(spnego_state->mech,
+ request, reply);
+ } else if (!request.data) {
+ ret = spnego_mech_offerings(spnego_state, request, reply);
+ } else if (spnego_state->server) {
+ ret = spnego_negotiate(spnego_state, request, reply);
+ } else {
+ ret = spnego_choose_mech(spnego_state, request, reply);
+ }
+
+ return ret;
+}
diff -Npur --exclude=CVS --exclude='*.bak' --exclude='*.o' --exclude='*.po' --exclude='*.so' --exclude='.#*' --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude='*proto*.h' --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude='config.*' --exclude=bin --exclude='*.configure' --exclude=autom4te.cache --exclude='build_options.c*' --exclude=TAGS --exclude='*~' --exclude='#*#' ../../samba-prestine/source/libsmb/spnego_ntlmssp.c ./libsmb/spnego_ntlmssp.c
--- ../../samba-prestine/source/libsmb/spnego_ntlmssp.c 1969-12-31 18:00:00.000000000 -0600
+++ ./libsmb/spnego_ntlmssp.c 2003-08-01 11:11:13.000000000 -0500
@@ -0,0 +1,262 @@
+/*
+ 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 2 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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+/*****************************************************************************
+ * Private SPNEGO-NTLMSSP routines
+ ****************************************************************************/
+static NTSTATUS spnego_ntlmssp_end(SPNEGO_STATE *state)
+{
+ return state->server ?
+ ntlmssp_server_end((NTLMSSP_STATE **)&state->mech->state) :
+ ntlmssp_client_end((NTLMSSP_CLIENT_STATE **)
+ &state->mech->state);
+}
+
+static NTSTATUS spnego_ntlmssp_results(SPNEGO_SEC_MECH *mech,
+ const DATA_BLOB request,
+ DATA_BLOB *reply)
+{
+ SPNEGO_DATA spnego;
+ NTSTATUS ret = NT_STATUS_INVALID_PARAMETER;
+
+ mech->step = 0;
+
+ if (-1 == read_spnego_data(request, &spnego)) {
+ return ret;
+ }
+
+ if (SPNEGO_NEG_TOKEN_TARG != spnego.type) {
+ DEBUG(1, ("spnego_ntlmssp_results: expecting negTokenTarg got"
+ " negTokenInit\n"));
+ goto out;
+ }
+
+ switch (spnego.negTokenTarg.negResult) {
+ case SPNEGO_ACCEPT_COMPLETED:
+ ret = NT_STATUS_OK;
+ break;
+ case SPNEGO_REJECT:
+ ret = NT_STATUS_ACCESS_DENIED;
+ break;
+ default:
+ break;
+ }
+
+out:
+ free_spnego_data(&spnego);
+ return ret;
+}
+
+static NTSTATUS spnego_ntlmssp_verify_auth(SPNEGO_SEC_MECH *mech,
+ const DATA_BLOB request,
+ DATA_BLOB *reply)
+{
+ SPNEGO_DATA spnego;
+ NTSTATUS ret = NT_STATUS_INVALID_PARAMETER;
+ NTLMSSP_STATE *ntlmssp_state = (NTLMSSP_STATE *)mech->state;
+
+ mech->step = 0;
+
+ if (-1 == read_spnego_data(request, &spnego)) {
+ return ret;
+ }
+
+ if (SPNEGO_NEG_TOKEN_TARG != spnego.type) {
+ DEBUG(1, ("spnego_server_negotiate: expected negTokenTarg got"
+ " negTokenInit\n"));
+ goto out;
+ }
+
+ if (!spnego.negTokenTarg.responseToken.data) {
+ DEBUG(1, ("spnego_server_negotiate: invalid responseToken\n"));
+ goto out;
+ }
+
+ ret = ntlmssp_server_update(ntlmssp_state,
+ spnego.negTokenTarg.responseToken, reply);
+ data_blob_free(reply);
+
+ ZERO_STRUCT(spnego);
+ spnego.type = SPNEGO_NEG_TOKEN_TARG;
+ spnego.negTokenTarg.negResult = !NT_STATUS_IS_OK(ret) ?
+ SPNEGO_ACCEPT_COMPLETED : SPNEGO_REJECT;
+
+ if (-1 == write_spnego_data(reply, &spnego)) {
+ ret = NT_STATUS_INVALID_PARAMETER;
+ }
+
+out:
+ return ret;
+}
+
+static NTSTATUS spnego_ntlmssp_authenticate(SPNEGO_SEC_MECH *mech,
+ const DATA_BLOB request,
+ DATA_BLOB *reply)
+{
+ NTLMSSP_CLIENT_STATE *ntlmssp_state =
+ (NTLMSSP_CLIENT_STATE *)mech->state;
+ SPNEGO_DATA spnego, spnego_out;
+ NTSTATUS ret = NT_STATUS_INVALID_PARAMETER;
+
+ mech->step = 0;
+ if (-1 == read_spnego_data(request, &spnego)) {
+ return ret;
+ }
+
+ ZERO_STRUCT(spnego_out);
+
+ if (SPNEGO_NEG_TOKEN_TARG != spnego.type) {
+ DEBUG(1, ("spnego_ntlmssp_gen_challenge: expected negTokenTarg"
+ " got negTokenInit\n"));
+ goto out;
+ }
+
+ if (!spnego.negTokenTarg.responseToken.data) {
+ DEBUG(1, ("spnego_ntlmssp_gen_challenge: invalid "
+ "responseToken\n"));
+ goto out;
+ }
+
+ spnego_out.type = SPNEGO_NEG_TOKEN_TARG;
+ spnego_out.negTokenTarg.supportedMech = smb_xstrdup(OID_NTLMSSP);
+ ret = ntlmssp_client_update(ntlmssp_state,
+ spnego.negTokenTarg.responseToken,
+ &spnego_out.negTokenTarg.responseToken);
+
+ if (-1 == write_spnego_data(reply, &spnego_out)) {
+ ret = NT_STATUS_INVALID_PARAMETER;
+ } else {
+ ret = NT_STATUS_MORE_PROCESSING_REQUIRED;
+ mech->step = spnego_ntlmssp_results;
+ }
+
+out:
+ free_spnego_data(&spnego);
+ free_spnego_data(&spnego_out);
+ return ret;
+}
+
+static NTSTATUS spnego_ntlmssp_challenge(SPNEGO_SEC_MECH *mech,
+ const DATA_BLOB request,
+ DATA_BLOB *reply)
+{
+ NTLMSSP_STATE **ntlmssp_state;
+ SPNEGO_DATA spnego;
+ NTSTATUS ret;
+
+ mech->step = 0;
+
+ ntlmssp_state = (NTLMSSP_STATE **)&mech->state;
+ ret = ntlmssp_server_start(ntlmssp_state);
+
+ if (!NT_STATUS_IS_OK(ret)) {
+ goto out;
+ }
+
+ ret = NT_STATUS_MORE_PROCESSING_REQUIRED;
+
+ ZERO_STRUCT(spnego);
+ spnego.type = SPNEGO_NEG_TOKEN_TARG;
+ spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
+ spnego.negTokenTarg.supportedMech = smb_xstrdup(OID_NTLMSSP);
+ ret = ntlmssp_server_update(*ntlmssp_state, request,
+ &spnego.negTokenTarg.responseToken);
+
+ if (-1 == write_spnego_data(reply, &spnego)) {
+ ret = NT_STATUS_INVALID_PARAMETER;
+ } else {
+ mech->step = spnego_ntlmssp_verify_auth;
+ }
+
+ free_spnego_data(&spnego);
+out:
+ return ret;
+}
+
+static NTSTATUS spnego_ntlmssp_initial(SPNEGO_SEC_MECH *mech, DATA_BLOB *reply)
+{
+ NTLMSSP_CLIENT_STATE **ntlmssp_state =
+ (NTLMSSP_CLIENT_STATE **)mech->state;
+
+ if (!NT_STATUS_IS_OK(ntlmssp_client_start(ntlmssp_state))) {
+ return NT_STATUS_INVALID_PARAMETER;
+ }
+
+ return ntlmssp_client_update(*ntlmssp_state, data_blob(0, 0),
+ reply);
+}
+
+static NTSTATUS spnego_ntlmssp_hint(SPNEGO_SEC_MECH *unused, DATA_BLOB *reply)
+{
+ ASN1_DATA asn1;
+
+ ZERO_STRUCT(asn1);
+ asn1_push_tag(&asn1, ASN1_SEQUENCE(0));
+ asn1_push_tag(&asn1, ASN1_CONTEXT(0));
+ asn1_write_GeneralString(&asn1, "NONE");
+ asn1_pop_tag(&asn1);
+ asn1_pop_tag(&asn1);
+
+ *reply = data_blob(asn1.data, asn1.length);
+
+ asn1_free(&asn1);
+
+ return NT_STATUS_MORE_PROCESSING_REQUIRED;
+}
+
+static SPNEGO_SEC_MECH srv_builtin_mechs = {
+ OID_NTLMSSP,
+ NULL,
+ spnego_ntlmssp_hint,
+ spnego_ntlmssp_challenge,
+ spnego_ntlmssp_end,
+ NULL
+};
+
+static SPNEGO_SEC_MECH cli_builtin_mechs = {
+ OID_NTLMSSP,
+ NULL,
+ spnego_ntlmssp_initial,
+ spnego_ntlmssp_authenticate,
+ spnego_ntlmssp_end,
+ NULL
+};
+
+BOOL spnego_register_ntlmssp(SPNEGO_STATE *state)
+{
+ SPNEGO_SEC_MECH *mech = state->server ?
+ talloc_memdup(state->mem_ctx, &srv_builtin_mechs,
+ sizeof(srv_builtin_mechs)):
+ talloc_memdup(state->mem_ctx, &cli_builtin_mechs,
+ sizeof(cli_builtin_mechs));
+
+ mech->next = state->mech_list;
+ state->mech_list = mech;
+
+ return True;
+}
diff -Npur --exclude=CVS --exclude='*.bak' --exclude='*.o' --exclude='*.po' --exclude='*.so' --exclude='.#*' --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude='*proto*.h' --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude='config.*' --exclude=bin --exclude='*.configure' --exclude=autom4te.cache --exclude='build_options.c*' --exclude=TAGS --exclude='*~' --exclude='#*#' ../../samba-prestine/source/Makefile.in ./Makefile.in
--- ../../samba-prestine/source/Makefile.in 2003-08-01 09:47:37.000000000 -0500
+++ ./Makefile.in 2003-08-01 12:52:19.000000000 -0500
@@ -560,7 +560,8 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \
$(LIB_SMBD_OBJ) $(SAM_OBJ) $(REGISTRY_OBJ) $(POPT_LIB_OBJ) \
$(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) \
$(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \
- $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o
+ $(RPC_ECHO_OBJ) $(SMBLDAP_OBJ) $(IDMAP_OBJ) libsmb/spnego.o \
+ libsmb/spnego_ntlmssp.o
WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) $(UBIQX_OBJ) \
$(LIBSMB_OBJ) $(LIB_OBJ) $(NSSWINS_OBJ)
@@ -617,7 +618,7 @@ POPT_OBJS=popt/findme.o popt/popt.o popt
TDBBACKUP_OBJ = tdb/tdbbackup.o tdb/tdbback.o $(TDBBASE_OBJ)
NTLM_AUTH_OBJ = utils/ntlm_auth.o $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
- libsmb/asn1.o libsmb/spnego.o
+ libsmb/asn1.o libsmb/spnego.o libsmb/spnego_ntlmssp.o
######################################################################
# now the rules...
diff -Npur --exclude=CVS --exclude='*.bak' --exclude='*.o' --exclude='*.po' --exclude='*.so' --exclude='.#*' --exclude=Makefile --exclude=stamp-h --exclude=configure --exclude=findsmb --exclude='*proto*.h' --exclude=build_env.h --exclude=tdbsam2_parse_info.h --exclude='config.*' --exclude=bin --exclude='*.configure' --exclude=autom4te.cache --exclude='build_options.c*' --exclude=TAGS --exclude='*~' --exclude='#*#' ../../samba-prestine/source/utils/ntlm_auth.c ./utils/ntlm_auth.c
--- ../../samba-prestine/source/utils/ntlm_auth.c 2003-08-01 02:59:23.000000000 -0500
+++ ./utils/ntlm_auth.c 2003-08-01 10:48:39.000000000 -0500
@@ -344,65 +344,20 @@ static void manage_squid_basic_request(e
}
}
-static void offer_gss_spnego_mechs(void) {
-
- DATA_BLOB token;
- ASN1_DATA asn1;
- SPNEGO_DATA spnego;
- ssize_t len;
- char *reply_base64;
-
- ZERO_STRUCT(spnego);
-
- /* Server negTokenInit (mech offerings) */
- spnego.type = SPNEGO_NEG_TOKEN_INIT;
- spnego.negTokenInit.mechTypes = smb_xmalloc(sizeof(char *) * 2);
- spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_NTLMSSP);
- spnego.negTokenInit.mechTypes[1] = NULL;
-
- ZERO_STRUCT(asn1);
- asn1_push_tag(&asn1, ASN1_SEQUENCE(0));
- asn1_push_tag(&asn1, ASN1_CONTEXT(0));
- asn1_write_GeneralString(&asn1, "NONE");
- asn1_pop_tag(&asn1);
- asn1_pop_tag(&asn1);
- spnego.negTokenInit.mechListMIC = data_blob(asn1.data, asn1.length);
- asn1_free(&asn1);
-
- len = write_spnego_data(&token, &spnego);
- free_spnego_data(&spnego);
-
- if (len == -1) {
- DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- reply_base64 = base64_encode_data_blob(token);
- x_fprintf(x_stdout, "TT %s *\n", reply_base64);
-
- SAFE_FREE(reply_base64);
- data_blob_free(&token);
- DEBUG(10, ("sent SPNEGO negTokenInit\n"));
- return;
-}
-
static void manage_gss_spnego_request(enum squid_mode squid_mode,
char *buf, int length)
{
- static NTLMSSP_STATE *ntlmssp_state = NULL;
- SPNEGO_DATA spnego;
- DATA_BLOB request, token;
+ static SPNEGO_STATE *spnego_state = NULL;
+ DATA_BLOB request;
+ DATA_BLOB reply = data_blob(NULL, 0);
NTSTATUS status;
- ssize_t len;
const char *reply_code;
char *reply_base64;
pstring reply_argument;
if (strlen(buf) < 2) {
-
- if (ntlmssp_state != NULL) {
+ if (spnego_state != NULL) {
DEBUG(1, ("Request for initial SPNEGO request where "
"we already have a state\n"));
x_fprintf(x_stdout, "BH\n");
@@ -413,147 +368,57 @@ static void manage_gss_spnego_request(en
x_fprintf(x_stdout, "BH\n");
return;
}
-
- if ( (strlen(buf) == 2) && (strcmp(buf, "YR") == 0) ) {
-
- /* Initial request, get the negTokenInit offering
- mechanisms */
-
- offer_gss_spnego_mechs();
- return;
- }
-
- /* All subsequent requests are "KK" (Knock, Knock ;)) and have
- a blob. This might be negTokenInit or negTokenTarg */
-
- if ( (strlen(buf) <= 3) || (strncmp(buf, "KK", 2) != 0) ) {
+ if (!strncmp(buf, "YR", 2)) {
+ request = data_blob(NULL, 0);
+ } else if (strlen(buf) > 3 && !strncmp(buf, "KK", 2)) {
+ request = base64_decode_data_blob(buf + 3);
+ } else {
DEBUG(1, ("GSS-SPNEGO query [%s] invalid\n", buf));
x_fprintf(x_stdout, "BH\n");
return;
}
- request = base64_decode_data_blob(buf + 3);
- len = read_spnego_data(request, &spnego);
- data_blob_free(&request);
-
- if (len == -1) {
- DEBUG(1, ("GSS-SPNEGO query [%s] invalid", buf));
- x_fprintf(x_stdout, "BH\n");
- return;
+ if (NULL == spnego_state) {
+ spnego_auth_start(&spnego_state, True);
+ spnego_register_ntlmssp(spnego_state);
}
- if (spnego.type == SPNEGO_NEG_TOKEN_INIT) {
-
- /* Second request from Client. This is where the
- client offers its mechanism to use. We currently
- only support NTLMSSP, the decision for Kerberos
- would be taken here. */
-
- if ( (spnego.negTokenInit.mechTypes == NULL) ||
- (spnego.negTokenInit.mechTypes[0] == NULL) ) {
- DEBUG(1, ("Client did not offer any mechanism"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if ( strcmp(spnego.negTokenInit.mechTypes[0], OID_NTLMSSP) != 0 ) {
- DEBUG(1, ("Client did not choose NTLMSSP but %s\n",
- spnego.negTokenInit.mechTypes[0]));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if ( spnego.negTokenInit.mechToken.data == NULL ) {
- DEBUG(1, ("Client did not provide NTLMSSP data\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- if ( ntlmssp_state != NULL ) {
- DEBUG(1, ("Client wants a new NTLMSSP challenge, but "
- "already got one\n"));
- x_fprintf(x_stdout, "BH\n");
- ntlmssp_server_end(&ntlmssp_state);
- return;
- }
+ if (spnego_state->mech) {
+ NTLMSSP_STATE *ntlmssp_state;
- ntlmssp_server_start(&ntlmssp_state);
+ ntlmssp_state = (NTLMSSP_STATE *)spnego_state->mech->state;
ntlmssp_state->check_password = winbind_pw_check;
ntlmssp_state->get_domain = get_winbind_domain;
ntlmssp_state->get_global_myname = get_winbind_netbios_name;
-
- DEBUG(10, ("got NTLMSSP packet:\n"));
- dump_data(10, spnego.negTokenInit.mechToken.data,
- spnego.negTokenInit.mechToken.length);
-
- free_spnego_data(&spnego);
-
- spnego.type = SPNEGO_NEG_TOKEN_TARG;
- spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
- spnego.negTokenTarg.supportedMech = strdup(OID_NTLMSSP);
-
- status = ntlmssp_server_update(ntlmssp_state,
- spnego.negTokenInit.mechToken,
- &spnego.negTokenTarg.responseToken);
-
- } else {
-
- /* spnego.type == SPNEGO_NEG_TOKEN_TARG */
-
- DATA_BLOB response;
-
- if (spnego.negTokenTarg.responseToken.data == NULL) {
- DEBUG(1, ("Got a negTokenArg without a responseToken!\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- status = ntlmssp_server_update(ntlmssp_state,
- spnego.negTokenTarg.responseToken,
- &response);
-
- data_blob_free(&spnego.negTokenTarg.responseToken);
-
- spnego.negTokenTarg.responseToken = response;
-
}
- if (NT_STATUS_IS_OK(status)) {
- spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
+ status = spnego_auth_update(spnego_state, request, &reply);
+ data_blob_free(&request);
+
+ if (NT_STATUS_IS_OK(status)) {
+ NTLMSSP_STATE *ntlmssp_state;
+ ntlmssp_state = (NTLMSSP_STATE *)spnego_state->mech->state;
reply_code = "AF";
pstr_sprintf(reply_argument, "%s\\%s",
ntlmssp_state->domain, ntlmssp_state->user);
+ spnego_auth_end(&spnego_state);
} else if (NT_STATUS_EQUAL(status,
NT_STATUS_MORE_PROCESSING_REQUIRED)) {
- spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE;
reply_code = "TT";
pstr_sprintf(reply_argument, "*");
} else {
- spnego.negTokenTarg.negResult = SPNEGO_REJECT;
reply_code = "NA";
pstrcpy(reply_argument, nt_errstr(status));
+ spnego_auth_end(&spnego_state);
}
- len = write_spnego_data(&token, &spnego);
- free_spnego_data(&spnego);
-
- if (len == -1) {
- DEBUG(1, ("Could not write SPNEGO data blob\n"));
- x_fprintf(x_stdout, "BH\n");
- return;
- }
-
- reply_base64 = base64_encode_data_blob(token);
+ reply_base64 = base64_encode_data_blob(reply);
+ data_blob_free(&reply);
x_fprintf(x_stdout, "%s %s %s\n",
reply_code, reply_base64, reply_argument);
SAFE_FREE(reply_base64);
- data_blob_free(&token);
-
- if (NT_STATUS_IS_OK(status)) {
- ntlmssp_server_end(&ntlmssp_state);
- }
return;
}
More information about the samba-technical
mailing list