mirror of
https://github.com/samba-team/samba.git
synced 2025-02-22 05:57:43 +03:00
spnego: share spnego_parse.
Guenther
This commit is contained in:
parent
83023462f9
commit
503d035814
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
RFC2478 Compliant SPNEGO implementation
|
||||
@ -9,17 +9,22 @@
|
||||
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
|
||||
@ -58,7 +63,7 @@ struct spnego_data {
|
||||
};
|
||||
|
||||
enum spnego_message_type {
|
||||
SPNEGO_NEG_TOKEN_INIT = 0,
|
||||
SPNEGO_NEG_TOKEN_INIT = 0,
|
||||
SPNEGO_NEG_TOKEN_TARG = 1,
|
||||
};
|
||||
|
@ -1,4 +1,4 @@
|
||||
/*
|
||||
/*
|
||||
Unix SMB/CIFS implementation.
|
||||
|
||||
RFC2478 Compliant SPNEGO implementation
|
||||
@ -9,20 +9,19 @@
|
||||
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 "../libcli/auth/spnego.h"
|
||||
#include "../lib/util/asn1.h"
|
||||
|
||||
static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
@ -50,13 +49,13 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
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,
|
||||
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;
|
||||
@ -83,7 +82,7 @@ static bool read_negTokenInit(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
break;
|
||||
}
|
||||
if (type_peek == ASN1_OCTET_STRING) {
|
||||
asn1_read_OctetString(asn1, mem_ctx,
|
||||
asn1_read_OctetString(asn1, mem_ctx,
|
||||
&token->mechListMIC);
|
||||
} else {
|
||||
/* RFC 2478 says we have an Octet String here,
|
||||
@ -165,7 +164,7 @@ static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenIni
|
||||
asn1_pop_tag(asn1);
|
||||
asn1_pop_tag(asn1);
|
||||
asn1_pop_tag(asn1);
|
||||
#endif
|
||||
#endif
|
||||
asn1_pop_tag(asn1);
|
||||
}
|
||||
|
||||
@ -175,7 +174,7 @@ static bool write_negTokenInit(struct asn1_data *asn1, struct spnego_negTokenIni
|
||||
return !asn1->has_error;
|
||||
}
|
||||
|
||||
static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
static bool read_negTokenTarg(struct asn1_data *asn1, TALLOC_CTX *mem_ctx,
|
||||
struct spnego_negTokenTarg *token)
|
||||
{
|
||||
ZERO_STRUCTP(token);
|
||||
@ -287,7 +286,7 @@ ssize_t spnego_read_data(TALLOC_CTX *mem_ctx, DATA_BLOB data, struct spnego_data
|
||||
switch (context) {
|
||||
case ASN1_APPLICATION(0):
|
||||
asn1_start_tag(asn1, ASN1_APPLICATION(0));
|
||||
asn1_check_OID(asn1, GENSEC_OID_SPNEGO);
|
||||
asn1_check_OID(asn1, OID_SPNEGO);
|
||||
if (read_negTokenInit(asn1, mem_ctx, &token->negTokenInit)) {
|
||||
token->type = SPNEGO_NEG_TOKEN_INIT;
|
||||
}
|
||||
@ -322,7 +321,7 @@ ssize_t spnego_write_data(TALLOC_CTX *mem_ctx, DATA_BLOB *blob, struct spnego_da
|
||||
switch (spnego->type) {
|
||||
case SPNEGO_NEG_TOKEN_INIT:
|
||||
asn1_push_tag(asn1, ASN1_APPLICATION(0));
|
||||
asn1_write_OID(asn1, GENSEC_OID_SPNEGO);
|
||||
asn1_write_OID(asn1, OID_SPNEGO);
|
||||
write_negTokenInit(asn1, &spnego->negTokenInit);
|
||||
asn1_pop_tag(asn1);
|
||||
break;
|
@ -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) \
|
||||
$(PASSDB_OBJ) $(LIBTSOCKET_OBJ) $(GROUPDB_OBJ) \
|
||||
$(SMBLDAP_OBJ) $(LIBNMB_OBJ) \
|
||||
|
@ -8,6 +8,12 @@
|
||||
|
||||
#include "../libds/common/flags.h"
|
||||
|
||||
#define TOK_ID_KRB_AP_REQ ((const uint8_t *)"\x01\x00")
|
||||
#define TOK_ID_KRB_AP_REP ((const uint8_t *)"\x02\x00")
|
||||
#define TOK_ID_KRB_ERROR ((const uint8_t *)"\x03\x00")
|
||||
#define TOK_ID_GSS_GETMIC ((const uint8_t *)"\x01\x01")
|
||||
#define TOK_ID_GSS_WRAP ((const uint8_t *)"\x02\x01")
|
||||
|
||||
enum wb_posix_mapping {
|
||||
WB_POSIX_MAP_UNKNOWN = -1,
|
||||
WB_POSIX_MAP_TEMPLATE = 0,
|
||||
|
@ -688,7 +688,6 @@ struct smb_iconv_convenience *lp_iconv_convenience(void *lp_ctx);
|
||||
#include "mangle.h"
|
||||
#include "module.h"
|
||||
#include "nsswitch/winbind_client.h"
|
||||
#include "spnego.h"
|
||||
#include "rpc_client.h"
|
||||
#include "dbwrap.h"
|
||||
#include "packet.h"
|
||||
|
@ -3297,12 +3297,6 @@ const char *smb_dos_err_class(uint8 e_class);
|
||||
char *smb_dos_errstr(char *inbuf);
|
||||
WERROR map_werror_from_unix(int error);
|
||||
|
||||
/* The following definitions come from libsmb/spnego.c */
|
||||
|
||||
ssize_t read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token);
|
||||
ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego);
|
||||
bool free_spnego_data(SPNEGO_DATA *spnego);
|
||||
|
||||
/* The following definitions come from libsmb/trustdom_cache.c */
|
||||
|
||||
bool trustdom_cache_enable(void);
|
||||
|
@ -1,81 +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/>.
|
||||
*/
|
||||
|
||||
#ifndef SAMBA_SPNEGO_H
|
||||
#define SAMBA_SPNEGO_H
|
||||
|
||||
#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
|
||||
|
||||
#define SPNEGO_NEG_TOKEN_INIT 0
|
||||
#define SPNEGO_NEG_TOKEN_TARG 1
|
||||
|
||||
/* some well known object IDs */
|
||||
#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_NEG_RESULT_ACCEPT 0
|
||||
#define SPNEGO_NEG_RESULT_INCOMPLETE 1
|
||||
#define SPNEGO_NEG_RESULT_REJECT 2
|
||||
|
||||
/* not really ASN.1, but RFC 1964 */
|
||||
#define TOK_ID_KRB_AP_REQ (uchar*)"\x01\x00"
|
||||
#define TOK_ID_KRB_AP_REP (uchar*)"\x02\x00"
|
||||
#define TOK_ID_KRB_ERROR (uchar*)"\x03\x00"
|
||||
#define TOK_ID_GSS_GETMIC (uchar*)"\x01\x01"
|
||||
#define TOK_ID_GSS_WRAP (uchar*)"\x02\x01"
|
||||
|
||||
typedef enum _spnego_negResult {
|
||||
SPNEGO_ACCEPT_COMPLETED = 0,
|
||||
SPNEGO_ACCEPT_INCOMPLETE = 1,
|
||||
SPNEGO_REJECT = 2
|
||||
} negResult_t;
|
||||
|
||||
typedef struct spnego_negTokenInit {
|
||||
const char **mechTypes;
|
||||
int reqFlags;
|
||||
DATA_BLOB mechToken;
|
||||
DATA_BLOB mechListMIC;
|
||||
} negTokenInit_t;
|
||||
|
||||
typedef struct spnego_negTokenTarg {
|
||||
uint8 negResult;
|
||||
char *supportedMech;
|
||||
DATA_BLOB responseToken;
|
||||
DATA_BLOB mechListMIC;
|
||||
} negTokenTarg_t;
|
||||
|
||||
typedef struct spnego_spnego {
|
||||
int type;
|
||||
negTokenInit_t negTokenInit;
|
||||
negTokenTarg_t negTokenTarg;
|
||||
} SPNEGO_DATA;
|
||||
|
||||
#endif
|
@ -18,6 +18,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
#ifdef HAVE_LDAP
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "../libcli/auth/libcli_auth.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
static const struct {
|
||||
int prot;
|
||||
|
@ -19,6 +19,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
/****************************************************************************
|
||||
Get UNIX extensions version info.
|
||||
|
@ -20,6 +20,7 @@
|
||||
*/
|
||||
|
||||
#include "includes.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
/*
|
||||
generate a negTokenInit packet given a GUID, a list of supported
|
||||
@ -532,11 +533,11 @@ DATA_BLOB spnego_gen_auth_response(DATA_BLOB *reply, NTSTATUS nt_status,
|
||||
uint8 negResult;
|
||||
|
||||
if (NT_STATUS_IS_OK(nt_status)) {
|
||||
negResult = SPNEGO_NEG_RESULT_ACCEPT;
|
||||
negResult = SPNEGO_ACCEPT_COMPLETED;
|
||||
} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
negResult = SPNEGO_NEG_RESULT_INCOMPLETE;
|
||||
negResult = SPNEGO_ACCEPT_INCOMPLETE;
|
||||
} else {
|
||||
negResult = SPNEGO_NEG_RESULT_REJECT;
|
||||
negResult = SPNEGO_REJECT;
|
||||
}
|
||||
|
||||
data = asn1_init(talloc_tos());
|
||||
@ -581,11 +582,11 @@ bool spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status,
|
||||
uint8 negResult;
|
||||
|
||||
if (NT_STATUS_IS_OK(nt_status)) {
|
||||
negResult = SPNEGO_NEG_RESULT_ACCEPT;
|
||||
negResult = SPNEGO_ACCEPT_COMPLETED;
|
||||
} else if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
|
||||
negResult = SPNEGO_NEG_RESULT_INCOMPLETE;
|
||||
negResult = SPNEGO_ACCEPT_INCOMPLETE;
|
||||
} else {
|
||||
negResult = SPNEGO_NEG_RESULT_REJECT;
|
||||
negResult = SPNEGO_REJECT;
|
||||
}
|
||||
|
||||
data = asn1_init(talloc_tos());
|
||||
@ -612,7 +613,7 @@ bool spnego_parse_auth_response(DATA_BLOB blob, NTSTATUS nt_status,
|
||||
asn1_read_OctetString(data, talloc_autofree_context(), auth);
|
||||
asn1_end_tag(data);
|
||||
}
|
||||
} else if (negResult == SPNEGO_NEG_RESULT_INCOMPLETE) {
|
||||
} else if (negResult == SPNEGO_ACCEPT_INCOMPLETE) {
|
||||
data->has_error = 1;
|
||||
}
|
||||
|
||||
|
@ -1,362 +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"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_AUTH
|
||||
|
||||
static bool read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *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;
|
||||
|
||||
switch (asn1->data[asn1->ofs]) {
|
||||
/* Read mechTypes */
|
||||
case ASN1_CONTEXT(0):
|
||||
asn1_start_tag(asn1, ASN1_CONTEXT(0));
|
||||
asn1_start_tag(asn1, ASN1_SEQUENCE(0));
|
||||
|
||||
token->mechTypes = TALLOC_P(talloc_autofree_context(), const char *);
|
||||
for (i = 0; !asn1->has_error &&
|
||||
0 < asn1_tag_remaining(asn1); i++) {
|
||||
const char *p_oid = NULL;
|
||||
token->mechTypes =
|
||||
TALLOC_REALLOC_ARRAY(talloc_autofree_context(),
|
||||
token->mechTypes, const char *, i + 2);
|
||||
if (!token->mechTypes) {
|
||||
asn1->has_error = True;
|
||||
return False;
|
||||
}
|
||||
asn1_read_OID(asn1, talloc_autofree_context(), &p_oid);
|
||||
token->mechTypes[i] = p_oid;
|
||||
}
|
||||
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,
|
||||
talloc_autofree_context(), &token->mechToken);
|
||||
asn1_end_tag(asn1);
|
||||
break;
|
||||
/* Read mecListMIC */
|
||||
case ASN1_CONTEXT(3):
|
||||
asn1_start_tag(asn1, ASN1_CONTEXT(3));
|
||||
if (asn1->data[asn1->ofs] == ASN1_OCTET_STRING) {
|
||||
asn1_read_OctetString(asn1, talloc_autofree_context(),
|
||||
&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,
|
||||
talloc_autofree_context(), &mechListMIC);
|
||||
asn1_pop_tag(asn1);
|
||||
asn1_pop_tag(asn1);
|
||||
|
||||
token->mechListMIC =
|
||||
data_blob(mechListMIC, strlen(mechListMIC));
|
||||
TALLOC_FREE(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(ASN1_DATA *asn1, negTokenInit_t *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(ASN1_DATA *asn1, negTokenTarg_t *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)) {
|
||||
switch (asn1->data[asn1->ofs]) {
|
||||
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): {
|
||||
const char *mech = NULL;
|
||||
asn1_start_tag(asn1, ASN1_CONTEXT(1));
|
||||
asn1_read_OID(asn1, talloc_autofree_context(), &mech);
|
||||
asn1_end_tag(asn1);
|
||||
token->supportedMech = CONST_DISCARD(char *, mech);
|
||||
}
|
||||
break;
|
||||
case ASN1_CONTEXT(2):
|
||||
asn1_start_tag(asn1, ASN1_CONTEXT(2));
|
||||
asn1_read_OctetString(asn1,
|
||||
talloc_autofree_context(), &token->responseToken);
|
||||
asn1_end_tag(asn1);
|
||||
break;
|
||||
case ASN1_CONTEXT(3):
|
||||
asn1_start_tag(asn1, ASN1_CONTEXT(3));
|
||||
asn1_read_OctetString(asn1,
|
||||
talloc_autofree_context(), &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(ASN1_DATA *asn1, negTokenTarg_t *token)
|
||||
{
|
||||
asn1_push_tag(asn1, ASN1_CONTEXT(1));
|
||||
asn1_push_tag(asn1, ASN1_SEQUENCE(0));
|
||||
|
||||
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 read_spnego_data(DATA_BLOB data, SPNEGO_DATA *token)
|
||||
{
|
||||
ASN1_DATA *asn1;
|
||||
ssize_t ret = -1;
|
||||
|
||||
ZERO_STRUCTP(token);
|
||||
|
||||
asn1 = asn1_init(talloc_tos());
|
||||
if (asn1 == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
asn1_load(asn1, data);
|
||||
|
||||
switch (asn1->data[asn1->ofs]) {
|
||||
case ASN1_APPLICATION(0):
|
||||
asn1_start_tag(asn1, ASN1_APPLICATION(0));
|
||||
asn1_check_OID(asn1, OID_SPNEGO);
|
||||
if (read_negTokenInit(asn1, &token->negTokenInit)) {
|
||||
token->type = SPNEGO_NEG_TOKEN_INIT;
|
||||
}
|
||||
asn1_end_tag(asn1);
|
||||
break;
|
||||
case ASN1_CONTEXT(1):
|
||||
if (read_negTokenTarg(asn1, &token->negTokenTarg)) {
|
||||
token->type = SPNEGO_NEG_TOKEN_TARG;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
if (!asn1->has_error) ret = asn1->ofs;
|
||||
asn1_free(asn1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
ssize_t write_spnego_data(DATA_BLOB *blob, SPNEGO_DATA *spnego)
|
||||
{
|
||||
ASN1_DATA *asn1;
|
||||
ssize_t ret = -1;
|
||||
|
||||
asn1 = asn1_init(talloc_tos());
|
||||
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(asn1->data, asn1->length);
|
||||
ret = asn1->ofs;
|
||||
}
|
||||
asn1_free(asn1);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool free_spnego_data(SPNEGO_DATA *spnego)
|
||||
{
|
||||
bool ret = True;
|
||||
|
||||
if (!spnego) goto out;
|
||||
|
||||
switch(spnego->type) {
|
||||
case SPNEGO_NEG_TOKEN_INIT:
|
||||
if (spnego->negTokenInit.mechTypes) {
|
||||
int i;
|
||||
for (i = 0; spnego->negTokenInit.mechTypes[i]; i++) {
|
||||
talloc_free(CONST_DISCARD(char *,spnego->negTokenInit.mechTypes[i]));
|
||||
}
|
||||
talloc_free(spnego->negTokenInit.mechTypes);
|
||||
}
|
||||
data_blob_free(&spnego->negTokenInit.mechToken);
|
||||
data_blob_free(&spnego->negTokenInit.mechListMIC);
|
||||
break;
|
||||
case SPNEGO_NEG_TOKEN_TARG:
|
||||
if (spnego->negTokenTarg.supportedMech) {
|
||||
talloc_free(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;
|
||||
}
|
@ -23,6 +23,7 @@
|
||||
#include "../librpc/gen_ndr/ndr_schannel.h"
|
||||
#include "../libcli/auth/schannel.h"
|
||||
#include "../libcli/auth/schannel_proto.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
#undef DBGC_CLASS
|
||||
#define DBGC_CLASS DBGC_RPC_CLI
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "../librpc/gen_ndr/ndr_schannel.h"
|
||||
#include "../libcli/auth/schannel.h"
|
||||
#include "../libcli/auth/schannel_proto.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
extern struct current_user current_user;
|
||||
|
||||
|
@ -20,6 +20,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "smbd/globals.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
extern fstring remote_proto;
|
||||
extern enum protocol_types Protocol;
|
||||
|
@ -19,6 +19,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "smbd/globals.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
/******************************************************************************
|
||||
Server side encryption.
|
||||
|
@ -24,6 +24,7 @@
|
||||
|
||||
#include "includes.h"
|
||||
#include "smbd/globals.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
extern enum protocol_types Protocol;
|
||||
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "includes.h"
|
||||
#include "smbd/globals.h"
|
||||
#include "../libcli/smb/smb_common.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
|
||||
static NTSTATUS smbd_smb2_session_setup(struct smbd_smb2_request *req,
|
||||
uint64_t in_session_id,
|
||||
|
@ -26,6 +26,7 @@
|
||||
#include "includes.h"
|
||||
#include "utils/ntlm_auth.h"
|
||||
#include "../libcli/auth/libcli_auth.h"
|
||||
#include "../libcli/auth/spnego.h"
|
||||
#include <iniparser.h>
|
||||
|
||||
#ifndef PAM_WINBIND_CONFIG_FILE
|
||||
@ -1113,7 +1114,7 @@ static void manage_squid_basic_request(struct ntlm_auth_state *state,
|
||||
static void offer_gss_spnego_mechs(void) {
|
||||
|
||||
DATA_BLOB token;
|
||||
SPNEGO_DATA spnego;
|
||||
struct spnego_data spnego;
|
||||
ssize_t len;
|
||||
char *reply_base64;
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
@ -1149,8 +1150,8 @@ static void offer_gss_spnego_mechs(void) {
|
||||
spnego.negTokenInit.mechListMIC = data_blob(principal,
|
||||
strlen(principal));
|
||||
|
||||
len = write_spnego_data(&token, &spnego);
|
||||
free_spnego_data(&spnego);
|
||||
len = spnego_write_data(ctx, &token, &spnego);
|
||||
spnego_free_data(&spnego);
|
||||
|
||||
if (len == -1) {
|
||||
DEBUG(1, ("Could not write SPNEGO data blob\n"));
|
||||
@ -1171,7 +1172,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
|
||||
char *buf, int length)
|
||||
{
|
||||
static NTLMSSP_STATE *ntlmssp_state = NULL;
|
||||
SPNEGO_DATA request, response;
|
||||
struct spnego_data request, response;
|
||||
DATA_BLOB token;
|
||||
NTSTATUS status;
|
||||
ssize_t len;
|
||||
@ -1219,7 +1220,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
|
||||
}
|
||||
|
||||
token = base64_decode_data_blob(buf + 3);
|
||||
len = read_spnego_data(token, &request);
|
||||
len = spnego_read_data(ctx, token, &request);
|
||||
data_blob_free(&token);
|
||||
|
||||
if (len == -1) {
|
||||
@ -1367,7 +1368,7 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
|
||||
}
|
||||
}
|
||||
|
||||
free_spnego_data(&request);
|
||||
spnego_free_data(&request);
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
response.negTokenTarg.negResult = SPNEGO_ACCEPT_COMPLETED;
|
||||
@ -1393,8 +1394,8 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
|
||||
SAFE_FREE(user);
|
||||
SAFE_FREE(domain);
|
||||
|
||||
len = write_spnego_data(&token, &response);
|
||||
free_spnego_data(&response);
|
||||
len = spnego_write_data(ctx, &token, &response);
|
||||
spnego_free_data(&response);
|
||||
|
||||
if (len == -1) {
|
||||
DEBUG(1, ("Could not write SPNEGO data blob\n"));
|
||||
@ -1415,13 +1416,14 @@ static void manage_gss_spnego_request(struct ntlm_auth_state *state,
|
||||
|
||||
static NTLMSSP_STATE *client_ntlmssp_state = NULL;
|
||||
|
||||
static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego)
|
||||
static bool manage_client_ntlmssp_init(struct spnego_data spnego)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DATA_BLOB null_blob = data_blob_null;
|
||||
DATA_BLOB to_server;
|
||||
char *to_server_base64;
|
||||
const char *my_mechs[] = {OID_NTLMSSP, NULL};
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
|
||||
DEBUG(10, ("Got spnego negTokenInit with NTLMSSP\n"));
|
||||
|
||||
@ -1466,7 +1468,7 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego)
|
||||
return False;
|
||||
}
|
||||
|
||||
write_spnego_data(&to_server, &spnego);
|
||||
spnego_write_data(ctx, &to_server, &spnego);
|
||||
data_blob_free(&spnego.negTokenInit.mechToken);
|
||||
|
||||
to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server);
|
||||
@ -1476,13 +1478,14 @@ static bool manage_client_ntlmssp_init(SPNEGO_DATA spnego)
|
||||
return True;
|
||||
}
|
||||
|
||||
static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
|
||||
static void manage_client_ntlmssp_targ(struct spnego_data spnego)
|
||||
{
|
||||
NTSTATUS status;
|
||||
DATA_BLOB null_blob = data_blob_null;
|
||||
DATA_BLOB request;
|
||||
DATA_BLOB to_server;
|
||||
char *to_server_base64;
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
|
||||
DEBUG(10, ("Got spnego negTokenTarg with NTLMSSP\n"));
|
||||
|
||||
@ -1525,7 +1528,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
|
||||
spnego.negTokenTarg.responseToken = request;
|
||||
spnego.negTokenTarg.mechListMIC = null_blob;
|
||||
|
||||
write_spnego_data(&to_server, &spnego);
|
||||
spnego_write_data(ctx, &to_server, &spnego);
|
||||
data_blob_free(&request);
|
||||
|
||||
to_server_base64 = base64_encode_data_blob(talloc_tos(), to_server);
|
||||
@ -1537,17 +1540,18 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego)
|
||||
|
||||
#ifdef HAVE_KRB5
|
||||
|
||||
static bool manage_client_krb5_init(SPNEGO_DATA spnego)
|
||||
static bool manage_client_krb5_init(struct spnego_data spnego)
|
||||
{
|
||||
char *principal;
|
||||
DATA_BLOB tkt, to_server;
|
||||
DATA_BLOB session_key_krb5 = data_blob_null;
|
||||
SPNEGO_DATA reply;
|
||||
struct spnego_data reply;
|
||||
char *reply_base64;
|
||||
int retval;
|
||||
|
||||
const char *my_mechs[] = {OID_KERBEROS5_OLD, NULL};
|
||||
ssize_t len;
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
|
||||
if ( (spnego.negTokenInit.mechListMIC.data == NULL) ||
|
||||
(spnego.negTokenInit.mechListMIC.length == 0) ) {
|
||||
@ -1609,7 +1613,7 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego)
|
||||
reply.negTokenInit.mechToken = tkt;
|
||||
reply.negTokenInit.mechListMIC = data_blob_null;
|
||||
|
||||
len = write_spnego_data(&to_server, &reply);
|
||||
len = spnego_write_data(ctx, &to_server, &reply);
|
||||
data_blob_free(&tkt);
|
||||
|
||||
if (len == -1) {
|
||||
@ -1626,7 +1630,7 @@ static bool manage_client_krb5_init(SPNEGO_DATA spnego)
|
||||
return True;
|
||||
}
|
||||
|
||||
static void manage_client_krb5_targ(SPNEGO_DATA spnego)
|
||||
static void manage_client_krb5_targ(struct spnego_data spnego)
|
||||
{
|
||||
switch (spnego.negTokenTarg.negResult) {
|
||||
case SPNEGO_ACCEPT_INCOMPLETE:
|
||||
@ -1654,8 +1658,9 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state,
|
||||
char *buf, int length)
|
||||
{
|
||||
DATA_BLOB request;
|
||||
SPNEGO_DATA spnego;
|
||||
struct spnego_data spnego;
|
||||
ssize_t len;
|
||||
TALLOC_CTX *ctx = talloc_tos();
|
||||
|
||||
if (!opt_username || !*opt_username) {
|
||||
x_fprintf(x_stderr, "username must be specified!\n\n");
|
||||
@ -1700,7 +1705,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state,
|
||||
/* So we got a server challenge to generate a SPNEGO
|
||||
client-to-server request... */
|
||||
|
||||
len = read_spnego_data(request, &spnego);
|
||||
len = spnego_read_data(ctx, request, &spnego);
|
||||
data_blob_free(&request);
|
||||
|
||||
if (len == -1) {
|
||||
@ -1786,7 +1791,7 @@ static void manage_gss_spnego_client_request(struct ntlm_auth_state *state,
|
||||
return;
|
||||
|
||||
out:
|
||||
free_spnego_data(&spnego);
|
||||
spnego_free_data(&spnego);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -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)))
|
||||
|
||||
|
@ -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"
|
||||
|
Loading…
x
Reference in New Issue
Block a user