#include "includes.h"
#include "smbd/smbd.h"
#include "smbd/globals.h"
-#include "../libcli/auth/spnego.h"
#include "serverid.h"
#include "auth.h"
#include "messages.h"
extern fstring remote_proto;
-static void get_challenge(struct smbd_server_connection *sconn, uint8 buff[8])
+static void get_challenge(struct smbXsrv_connection *xconn, uint8_t buff[8])
{
NTSTATUS nt_status;
/* We might be called more than once, multiple negprots are
* permitted */
- if (sconn->smb1.negprot.auth_context) {
+ if (xconn->smb1.negprot.auth_context) {
DEBUG(3, ("get challenge: is this a secondary negprot? "
"sconn->negprot.auth_context is non-NULL!\n"));
- TALLOC_FREE(sconn->smb1.negprot.auth_context);
+ TALLOC_FREE(xconn->smb1.negprot.auth_context);
}
DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
nt_status = make_auth4_context(
- sconn, &sconn->smb1.negprot.auth_context);
+ xconn, &xconn->smb1.negprot.auth_context);
if (!NT_STATUS_IS_OK(nt_status)) {
DEBUG(0, ("make_auth_context_subsystem returned %s",
nt_errstr(nt_status)));
smb_panic("cannot make_negprot_global_auth_context!");
}
DEBUG(10, ("get challenge: getting challenge\n"));
- sconn->smb1.negprot.auth_context->get_ntlm_challenge(
- sconn->smb1.negprot.auth_context, buff);
+ xconn->smb1.negprot.auth_context->get_ntlm_challenge(
+ xconn->smb1.negprot.auth_context, buff);
}
/****************************************************************************
Reply for the lanman 1.0 protocol.
****************************************************************************/
-static void reply_lanman1(struct smb_request *req, uint16 choice)
+static void reply_lanman1(struct smb_request *req, uint16_t choice)
{
int secword=0;
time_t t = time(NULL);
- struct smbd_server_connection *sconn = req->sconn;
+ struct smbXsrv_connection *xconn = req->xconn;
uint16_t raw;
if (lp_async_smb_echo_handler()) {
raw = 0;
raw = (lp_read_raw()?1:0) | (lp_write_raw()?2:0);
}
- sconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
+ xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (xconn->smb1.negprot.encrypted_passwords) {
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
}
- reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
+ reply_outbuf(req, 13, xconn->smb1.negprot.encrypted_passwords?8:0);
SSVAL(req->outbuf,smb_vwv0,choice);
SSVAL(req->outbuf,smb_vwv1,secword);
/* Create a token value and add it to the outgoing packet. */
- if (sconn->smb1.negprot.encrypted_passwords) {
- get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
+ if (xconn->smb1.negprot.encrypted_passwords) {
+ get_challenge(xconn, (uint8_t *)smb_buf(req->outbuf));
SSVAL(req->outbuf,smb_vwv11, 8);
}
- smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN1);
+ smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN1);
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(req->outbuf,smb_vwv2, sconn->smb1.negprot.max_recv);
+ SSVAL(req->outbuf,smb_vwv2, xconn->smb1.negprot.max_recv);
SSVAL(req->outbuf,smb_vwv3, lp_max_mux()); /* maxmux */
SSVAL(req->outbuf,smb_vwv4, 1);
SSVAL(req->outbuf,smb_vwv5, raw); /* tell redirector we support
Reply for the lanman 2.0 protocol.
****************************************************************************/
-static void reply_lanman2(struct smb_request *req, uint16 choice)
+static void reply_lanman2(struct smb_request *req, uint16_t choice)
{
int secword=0;
time_t t = time(NULL);
- struct smbd_server_connection *sconn = req->sconn;
+ struct smbXsrv_connection *xconn = req->xconn;
uint16_t raw;
if (lp_async_smb_echo_handler()) {
raw = 0;
raw = (lp_read_raw()?1:0) | (lp_write_raw()?2:0);
}
- sconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
+ xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (xconn->smb1.negprot.encrypted_passwords) {
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
}
- reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
+ reply_outbuf(req, 13, xconn->smb1.negprot.encrypted_passwords?8:0);
SSVAL(req->outbuf,smb_vwv0, choice);
SSVAL(req->outbuf,smb_vwv1, secword);
SIVAL(req->outbuf,smb_vwv6, getpid());
/* Create a token value and add it to the outgoing packet. */
- if (sconn->smb1.negprot.encrypted_passwords) {
- get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
+ if (xconn->smb1.negprot.encrypted_passwords) {
+ get_challenge(xconn, (uint8_t *)smb_buf(req->outbuf));
SSVAL(req->outbuf,smb_vwv11, 8);
}
- smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN2);
+ smbXsrv_connection_init_tables(xconn, PROTOCOL_LANMAN2);
/* Reply, SMBlockread, SMBwritelock supported. */
SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
+ SSVAL(req->outbuf,smb_vwv2,xconn->smb1.negprot.max_recv);
SSVAL(req->outbuf,smb_vwv3,lp_max_mux());
SSVAL(req->outbuf,smb_vwv4,1);
SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
Generate the spnego negprot reply blob. Return the number of bytes used.
****************************************************************************/
-DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
+DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbXsrv_connection *xconn)
{
DATA_BLOB blob = data_blob_null;
DATA_BLOB blob_out = data_blob_null;
/* See if we can get an SPNEGO blob */
status = auth_generic_prepare(talloc_tos(),
- sconn->remote_address,
+ xconn->remote_address,
&gensec_security);
if (NT_STATUS_IS_OK(status)) {
status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
TALLOC_FREE(gensec_security);
}
- sconn->smb1.negprot.spnego = true;
+ xconn->smb1.negprot.spnego = true;
/* strangely enough, NT does not sent the single OID NTLMSSP when
not a ADS member, it sends no OIDs at all
Reply for the nt protocol.
****************************************************************************/
-static void reply_nt1(struct smb_request *req, uint16 choice)
+static void reply_nt1(struct smb_request *req, uint16_t choice)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
bool negotiate_spnego = False;
struct timespec ts;
ssize_t ret;
- struct smbd_server_connection *sconn = req->sconn;
+ struct smbXsrv_connection *xconn = req->xconn;
bool signing_desired = false;
bool signing_required = false;
- sconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
+ xconn->smb1.negprot.encrypted_passwords = lp_encrypt_passwords();
/* Check the flags field to see if this is Vista.
WinXP sets it and Vista does not. But we have to
if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
{
- if (get_remote_arch() != RA_SAMBA) {
+ if ((get_remote_arch() != RA_SAMBA) &&
+ (get_remote_arch() != RA_CIFSFS)) {
set_remote_arch( RA_VISTA );
}
}
/* do spnego in user level security if the client
supports it and we can do encrypted passwords */
- if (sconn->smb1.negprot.encrypted_passwords &&
+ if (xconn->smb1.negprot.encrypted_passwords &&
lp_use_spnego() &&
(req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
negotiate_spnego = True;
capabilities |= CAP_DFS;
secword |= NEGOTIATE_SECURITY_USER_LEVEL;
- if (sconn->smb1.negprot.encrypted_passwords) {
+ if (xconn->smb1.negprot.encrypted_passwords) {
secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
}
- signing_desired = smb_signing_is_desired(req->sconn->smb1.signing_state);
- signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
+ signing_desired = smb_signing_is_desired(xconn->smb1.signing_state);
+ signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
if (signing_desired) {
secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
SSVAL(req->outbuf,smb_vwv0,choice);
SCVAL(req->outbuf,smb_vwv1,secword);
- smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1);
+ smbXsrv_connection_init_tables(xconn, PROTOCOL_NT1);
SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */
SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
SIVAL(req->outbuf,smb_vwv3+1,
- sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
+ xconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */
SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */
SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */
if (!negotiate_spnego) {
/* Create a token value and add it to the outgoing packet. */
- if (sconn->smb1.negprot.encrypted_passwords) {
- uint8 chal[8];
+ if (xconn->smb1.negprot.encrypted_passwords) {
+ uint8_t chal[8];
/* note that we do not send a challenge at all if
we are using plaintext */
- get_challenge(sconn, chal);
+ get_challenge(xconn, chal);
ret = message_push_blob(
&req->outbuf, data_blob_const(chal, sizeof(chal)));
if (ret == -1) {
}
DEBUG(3,("not using SPNEGO\n"));
} else {
- DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
+ DATA_BLOB spnego_blob = negprot_spnego(req, xconn);
if (spnego_blob.data == NULL) {
reply_nterror(req, NT_STATUS_NO_MEMORY);
protocol [LANMAN1.0]
protocol [LM1.2X002]
protocol [LANMAN2.1]
+
+OSX:
+protocol [NT LM 0.12]
+protocol [SMB 2.002]
+protocol [SMB 2.???]
*/
/*
* Modified to recognize the architecture of the remote machine better.
*
* This appears to be the matrix of which protocol is used by which
- * MS product.
- Protocol WfWg Win95 WinNT Win2K OS/2 Vista
- PC NETWORK PROGRAM 1.0 1 1 1 1 1 1
- XENIX CORE 2 2
- MICROSOFT NETWORKS 3.0 2 2
- DOS LM1.2X002 3 3
- MICROSOFT NETWORKS 1.03 3
- DOS LANMAN2.1 4 4
- LANMAN1.0 4 2 3 2
- Windows for Workgroups 3.1a 5 5 5 3 3
- LM1.2X002 6 4 4 4
- LANMAN2.1 7 5 5 5
- NT LM 0.12 6 8 6 6
- SMB 2.001 7
+ * product.
+ Protocol WfWg Win95 WinNT Win2K OS/2 Vista OSX
+ PC NETWORK PROGRAM 1.0 1 1 1 1 1 1
+ XENIX CORE 2 2
+ MICROSOFT NETWORKS 3.0 2 2
+ DOS LM1.2X002 3 3
+ MICROSOFT NETWORKS 1.03 3
+ DOS LANMAN2.1 4 4
+ LANMAN1.0 4 2 3 2
+ Windows for Workgroups 3.1a 5 5 5 3 3
+ LM1.2X002 6 4 4 4
+ LANMAN2.1 7 5 5 5
+ NT LM 0.12 6 8 6 6 6 1
+ SMB 2.001 7
+ SMB 2.002 2
+ SMB 2.??? 3
*
* tim@fsg.com 09/29/95
* Win2K added by matty 17/7/99
*/
-#define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
-#define ARCH_WIN95 0x2
-#define ARCH_WINNT 0x4
-#define ARCH_WIN2K 0xC /* Win2K is like NT */
-#define ARCH_OS2 0x14 /* Again OS/2 is like NT */
-#define ARCH_SAMBA 0x20
-#define ARCH_CIFSFS 0x40
-#define ARCH_VISTA 0x8C /* Vista is like XP/2K */
-
-#define ARCH_ALL 0x7F
+#define PROT_PC_NETWORK_PROGRAM_1_0 0x0001
+#define PROT_XENIX_CORE 0x0002
+#define PROT_MICROSOFT_NETWORKS_3_0 0x0004
+#define PROT_DOS_LM1_2X002 0x0008
+#define PROT_MICROSOFT_NETWORKS_1_03 0x0010
+#define PROT_DOS_LANMAN2_1 0x0020
+#define PROT_LANMAN1_0 0x0040
+#define PROT_WFWG 0x0080
+#define PROT_LM1_2X002 0x0100
+#define PROT_LANMAN2_1 0x0200
+#define PROT_NT_LM_0_12 0x0400
+#define PROT_SMB_2_001 0x0800
+#define PROT_SMB_2_002 0x1000
+#define PROT_SMB_2_FF 0x2000
+#define PROT_SAMBA 0x4000
+#define PROT_POSIX_2 0x8000
+
+#define ARCH_WFWG ( PROT_PC_NETWORK_PROGRAM_1_0 | PROT_MICROSOFT_NETWORKS_3_0 | \
+ PROT_DOS_LM1_2X002 | PROT_DOS_LANMAN2_1 | PROT_WFWG )
+#define ARCH_WIN95 ( ARCH_WFWG | PROT_NT_LM_0_12 )
+#define ARCH_WINNT ( PROT_PC_NETWORK_PROGRAM_1_0 | PROT_XENIX_CORE | \
+ PROT_MICROSOFT_NETWORKS_1_03 | PROT_LANMAN1_0 | PROT_WFWG | \
+ PROT_LM1_2X002 | PROT_LANMAN2_1 | PROT_NT_LM_0_12 )
+#define ARCH_WIN2K ( ARCH_WINNT & ~(PROT_XENIX_CORE | PROT_MICROSOFT_NETWORKS_1_03) )
+#define ARCH_OS2 ( ARCH_WINNT & ~(PROT_MICROSOFT_NETWORKS_1_03 | PROT_WFWG) )
+#define ARCH_VISTA ( ARCH_WIN2K | PROT_SMB_2_001 )
+#define ARCH_SAMBA ( PROT_SAMBA )
+#define ARCH_CIFSFS ( PROT_POSIX_2 )
+#define ARCH_OSX ( PROT_NT_LM_0_12 | PROT_SMB_2_002 | PROT_SMB_2_FF )
/* List of supported protocols, most desired first */
static const struct {
const char *proto_name;
const char *short_name;
- void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
+ void (*proto_reply_fn)(struct smb_request *req, uint16_t choice);
int protocol_level;
} supported_protocols[] = {
{"SMB 2.???", "SMB2_FF", reply_smb20ff, PROTOCOL_SMB2_10},
int chosen_level = -1;
int protocol;
const char *p;
- int arch = ARCH_ALL;
+ int protocols = 0;
int num_cliprotos;
char **cliprotos;
int i;
size_t converted_size;
+ struct smbXsrv_connection *xconn = req->xconn;
struct smbd_server_connection *sconn = req->sconn;
+ bool signing_required = true;
START_PROFILE(SMBnegprot);
- if (sconn->smb1.negprot.done) {
+ if (xconn->smb1.negprot.done) {
END_PROFILE(SMBnegprot);
exit_server_cleanly("multiple negprot's are not permitted");
}
- sconn->smb1.negprot.done = true;
+ xconn->smb1.negprot.done = true;
if (req->buflen == 0) {
DEBUG(0, ("negprot got no protocols\n"));
}
for (i=0; i<num_cliprotos; i++) {
- if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
- | ARCH_WIN2K );
- else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(cliprotos[i], "NT LM 0.12"))
- arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
- | ARCH_CIFSFS);
- else if (strcsequal(cliprotos[i], "SMB 2.001"))
- arch = ARCH_VISTA;
- else if (strcsequal(cliprotos[i], "LANMAN2.1"))
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(cliprotos[i], "LM1.2X002"))
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
- arch &= ARCH_WINNT;
- else if (strcsequal(cliprotos[i], "XENIX CORE"))
- arch &= ( ARCH_WINNT | ARCH_OS2 );
- else if (strcsequal(cliprotos[i], "Samba")) {
- arch = ARCH_SAMBA;
+ if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a")) {
+ protocols |= PROT_WFWG;
+ } else if (strcsequal(cliprotos[i], "DOS LM1.2X002")) {
+ protocols |= PROT_DOS_LM1_2X002;
+ } else if (strcsequal(cliprotos[i], "DOS LANMAN2.1")) {
+ protocols |= PROT_DOS_LANMAN2_1;
+ } else if (strcsequal(cliprotos[i], "LANMAN1.0")) {
+ protocols |= PROT_LANMAN1_0;
+ } else if (strcsequal(cliprotos[i], "NT LM 0.12")) {
+ protocols |= PROT_NT_LM_0_12;
+ } else if (strcsequal(cliprotos[i], "SMB 2.001")) {
+ protocols |= PROT_SMB_2_001;
+ } else if (strcsequal(cliprotos[i], "SMB 2.002")) {
+ protocols |= PROT_SMB_2_002;
+ } else if (strcsequal(cliprotos[i], "SMB 2.???")) {
+ protocols |= PROT_SMB_2_FF;
+ } else if (strcsequal(cliprotos[i], "LANMAN2.1")) {
+ protocols |= PROT_LANMAN2_1;
+ } else if (strcsequal(cliprotos[i], "LM1.2X002")) {
+ protocols |= PROT_LM1_2X002;
+ } else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03")) {
+ protocols |= PROT_MICROSOFT_NETWORKS_1_03;
+ } else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 3.0")) {
+ protocols |= PROT_MICROSOFT_NETWORKS_3_0;
+ } else if (strcsequal(cliprotos[i], "PC NETWORK PROGRAM 1.0")) {
+ protocols |= PROT_PC_NETWORK_PROGRAM_1_0;
+ } else if (strcsequal(cliprotos[i], "XENIX CORE")) {
+ protocols |= PROT_XENIX_CORE;
+ } else if (strcsequal(cliprotos[i], "Samba")) {
+ protocols = PROT_SAMBA;
break;
} else if (strcsequal(cliprotos[i], "POSIX 2")) {
- arch = ARCH_CIFSFS;
+ protocols = PROT_POSIX_2;
break;
}
}
- /* CIFSFS can send one arch only, NT LM 0.12. */
- if (i == 1 && (arch & ARCH_CIFSFS)) {
- arch = ARCH_CIFSFS;
- }
-
- switch ( arch ) {
+ switch ( protocols ) {
+ /* Old CIFSFS can send one arch only, NT LM 0.12. */
+ case PROT_NT_LM_0_12:
case ARCH_CIFSFS:
set_remote_arch(RA_CIFSFS);
break;
set_remote_arch(RA_WIN95);
break;
case ARCH_WINNT:
- if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
- set_remote_arch(RA_WIN2K);
- else
- set_remote_arch(RA_WINNT);
+ set_remote_arch(RA_WINNT);
break;
case ARCH_WIN2K:
- /* Vista may have been set in the negprot so don't
- override it here */
- if ( get_remote_arch() != RA_VISTA )
- set_remote_arch(RA_WIN2K);
+ set_remote_arch(RA_WIN2K);
break;
case ARCH_VISTA:
set_remote_arch(RA_VISTA);
case ARCH_OS2:
set_remote_arch(RA_OS2);
break;
+ case ARCH_OSX:
+ set_remote_arch(RA_OSX);
+ break;
default:
set_remote_arch(RA_UNKNOWN);
break;
DEBUG( 5, ( "negprot index=%d\n", choice ) );
- if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
- && (chosen_level < PROTOCOL_NT1)) {
+ /* We always have xconn->smb1.signing_state also for >= SMB2_02 */
+ signing_required = smb_signing_is_mandatory(xconn->smb1.signing_state);
+ if (signing_required && (chosen_level < PROTOCOL_NT1)) {
exit_server_cleanly("SMB signing is required and "
"client negotiated a downlevel protocol");
}
TALLOC_FREE(cliprotos);
if (lp_async_smb_echo_handler() && (chosen_level < PROTOCOL_SMB2_02) &&
- !fork_echo_handler(sconn)) {
+ !fork_echo_handler(xconn)) {
exit_server("Failed to fork echo handler");
}