/*
- Unix SMB/Netbios implementation.
- Version 1.9.
+ Unix SMB/CIFS implementation.
negprot reply code
Copyright (C) Andrew Tridgell 1992-1998
#include "includes.h"
-extern int Protocol;
+extern fstring remote_proto;
+extern enum protocol_types Protocol;
extern int max_recv;
-extern fstring global_myworkgroup;
-extern fstring remote_machine;
+
BOOL global_encrypted_passwords_negotiated = False;
BOOL global_spnego_negotiated = False;
-auth_authsupplied_info *negprot_global_auth_info = NULL;
+struct auth_context *negprot_global_auth_context = NULL;
+
+static void get_challenge(char buff[8])
+{
+ NTSTATUS nt_status;
+ const uint8 *cryptkey;
+
+ /* We might be called more than once, muliple negprots are premitted */
+ if (negprot_global_auth_context) {
+ DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
+ (negprot_global_auth_context->free)(&negprot_global_auth_context);
+ }
+
+ DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
+ if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
+ DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
+ smb_panic("cannot make_negprot_global_auth_context!\n");
+ }
+ DEBUG(10, ("get challenge: getting challenge\n"));
+ cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
+ memcpy(buff, cryptkey, 8);
+}
/****************************************************************************
-reply for the core protocol
+ Reply for the core protocol.
****************************************************************************/
+
static int reply_corep(char *inbuf, char *outbuf)
{
int outsize = set_message(outbuf,1,0,True);
return outsize;
}
-
/****************************************************************************
-reply for the coreplus protocol
+ Reply for the coreplus protocol.
****************************************************************************/
+
static int reply_coreplus(char *inbuf, char *outbuf)
{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int outsize = set_message(outbuf,13,0,True);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw and writebraw (possibly) */
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
+ int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
+ int outsize = set_message(outbuf,13,0,True);
+ SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
+ readbraw and writebraw (possibly) */
+ /* Reply, SMBlockread, SMBwritelock supported. */
+ SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
+ SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
- Protocol = PROTOCOL_COREPLUS;
+ Protocol = PROTOCOL_COREPLUS;
- return outsize;
+ return outsize;
}
-
/****************************************************************************
-reply for the lanman 1.0 protocol
+ Reply for the lanman 1.0 protocol.
****************************************************************************/
+
static int reply_lanman1(char *inbuf, char *outbuf)
{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int secword=0;
- time_t t = time(NULL);
- DATA_BLOB cryptkey;
-
- global_encrypted_passwords_negotiated = lp_encrypted_passwords();
-
- if (lp_security()>=SEC_USER) secword |= 1;
- if (global_encrypted_passwords_negotiated) secword |= 2;
-
- set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
- SSVAL(outbuf,smb_vwv1,secword);
- /* Create a token value and add it to the outgoing packet. */
- if (global_encrypted_passwords_negotiated) {
- if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
- smb_panic("cannot make_negprot_global_auth_info!\n");
- }
- cryptkey = auth_get_challenge(negprot_global_auth_info);
- memcpy(smb_buf(outbuf), cryptkey.data, 8);
- data_blob_free(&cryptkey);
- }
-
- Protocol = PROTOCOL_LANMAN1;
-
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(outbuf,smb_vwv2,max_recv);
- SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
- SSVAL(outbuf,smb_vwv4,1);
- SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
- readbraw writebraw (possibly) */
- SIVAL(outbuf,smb_vwv6,sys_getpid());
- SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
-
- put_dos_date(outbuf,smb_vwv8,t);
-
- return (smb_len(outbuf)+4);
-}
+ int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
+ int secword=0;
+ time_t t = time(NULL);
+
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
+
+ if (lp_security()>=SEC_USER)
+ secword |= NEGOTIATE_SECURITY_USER_LEVEL;
+ if (global_encrypted_passwords_negotiated)
+ secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
+
+ set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+ SSVAL(outbuf,smb_vwv1,secword);
+ /* Create a token value and add it to the outgoing packet. */
+ if (global_encrypted_passwords_negotiated) {
+ get_challenge(smb_buf(outbuf));
+ SSVAL(outbuf,smb_vwv11, 8);
+ }
+
+ Protocol = PROTOCOL_LANMAN1;
+
+ /* Reply, SMBlockread, SMBwritelock supported. */
+ SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
+ SSVAL(outbuf,smb_vwv2,max_recv);
+ SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
+ SSVAL(outbuf,smb_vwv4,1);
+ SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
+ readbraw writebraw (possibly) */
+ SIVAL(outbuf,smb_vwv6,sys_getpid());
+ SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
+
+ srv_put_dos_date(outbuf,smb_vwv8,t);
+ return (smb_len(outbuf)+4);
+}
/****************************************************************************
-reply for the lanman 2.0 protocol
+ Reply for the lanman 2.0 protocol.
****************************************************************************/
+
static int reply_lanman2(char *inbuf, char *outbuf)
{
- int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
- int secword=0;
- time_t t = time(NULL);
- DATA_BLOB cryptkey;
+ int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
+ int secword=0;
+ time_t t = time(NULL);
- global_encrypted_passwords_negotiated = lp_encrypted_passwords();
+ global_encrypted_passwords_negotiated = lp_encrypted_passwords();
- if (lp_security()>=SEC_USER) secword |= 1;
- if (global_encrypted_passwords_negotiated) secword |= 2;
-
- set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
- SSVAL(outbuf,smb_vwv1,secword);
- SIVAL(outbuf,smb_vwv6,sys_getpid());
-
- if (global_encrypted_passwords_negotiated) {
- if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
- smb_panic("cannot make_negprot_global_auth_info!\n");
- }
- cryptkey = auth_get_challenge(negprot_global_auth_info);
- memcpy(smb_buf(outbuf), cryptkey.data, 8);
- data_blob_free(&cryptkey);
- }
-
- Protocol = PROTOCOL_LANMAN2;
-
- /* Reply, SMBlockread, SMBwritelock supported. */
- SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
- SSVAL(outbuf,smb_vwv2,max_recv);
- SSVAL(outbuf,smb_vwv3,lp_maxmux());
- SSVAL(outbuf,smb_vwv4,1);
- SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
- SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
- put_dos_date(outbuf,smb_vwv8,t);
-
- return (smb_len(outbuf)+4);
-}
+ if (lp_security()>=SEC_USER)
+ secword |= NEGOTIATE_SECURITY_USER_LEVEL;
+ if (global_encrypted_passwords_negotiated)
+ secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
+
+ set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
+ SSVAL(outbuf,smb_vwv1,secword);
+ SIVAL(outbuf,smb_vwv6,sys_getpid());
+
+ /* Create a token value and add it to the outgoing packet. */
+ if (global_encrypted_passwords_negotiated) {
+ get_challenge(smb_buf(outbuf));
+ SSVAL(outbuf,smb_vwv11, 8);
+ }
+ Protocol = PROTOCOL_LANMAN2;
+ /* Reply, SMBlockread, SMBwritelock supported. */
+ SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
+ SSVAL(outbuf,smb_vwv2,max_recv);
+ SSVAL(outbuf,smb_vwv3,lp_maxmux());
+ SSVAL(outbuf,smb_vwv4,1);
+ SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
+ SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
+ srv_put_dos_date(outbuf,smb_vwv8,t);
-/*
- generate the spnego negprot reply blob. Return the number of bytes used
-*/
-static int negprot_spnego(char *p)
+ return (smb_len(outbuf)+4);
+}
+
+/****************************************************************************
+ Generate the spnego negprot reply blob. Return the number of bytes used.
+****************************************************************************/
+
+static int negprot_spnego(char *p, uint8 *pkeylen)
{
DATA_BLOB blob;
- extern pstring global_myname;
- uint8 guid[16];
- const char *OIDs_krb5[] = {OID_NTLMSSP,
- OID_KERBEROS5,
+ nstring dos_name;
+ fstring unix_name;
+ char guid[17];
+ const char *OIDs_krb5[] = {OID_KERBEROS5,
OID_KERBEROS5_OLD,
+ OID_NTLMSSP,
NULL};
- const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
- char *principal;
int len;
global_spnego_negotiated = True;
- memset(guid, 0, 16);
- safe_strcpy((char *)guid, global_myname, 16);
- strlower((char *)guid);
+ ZERO_STRUCT(guid);
+
+ safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
+ strlower_m(unix_name);
+ push_ascii_nstring(dos_name, unix_name);
+ safe_strcpy(guid, dos_name, sizeof(guid)-1);
+
+#ifdef DEVELOPER
+ /* valgrind fixer... */
+ {
+ size_t sl = strlen(guid);
+ if (sizeof(guid)-sl)
+ memset(&guid[sl], '\0', sizeof(guid)-sl);
+ }
+#endif
-#if 0
/* strangely enough, NT does not sent the single OID NTLMSSP when
not a ADS member, it sends no OIDs at all
- we can't do this until we teach our sesssion setup parser to know
- about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
+ OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
+ about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
+
+ Our sessionsetup code now handles raw NTLMSSP connects, so we can go
+ back to doing what W2K3 does here. This is needed to make PocketPC 2003
+ CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
+ for details. JRA.
+
*/
- if (lp_security() != SEC_ADS) {
+
+ if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
memcpy(p, guid, 16);
+ *pkeylen = 0;
return 16;
- }
-#endif
- {
- ADS_STRUCT *ads;
- ads = ads_init(NULL, NULL, NULL);
-
- /* win2000 uses host$@REALM, which we will probably use eventually,
- but for now this works */
- asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
- blob = spnego_gen_negTokenInit(guid,
- lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain,
- principal);
- free(principal);
- ads_destroy(&ads);
+ } else {
+ fstring myname;
+ char *host_princ_s = NULL;
+ name_to_fqdn(myname, global_myname());
+ strlower_m(myname);
+ asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
+ blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
+ SAFE_FREE(host_princ_s);
}
memcpy(p, blob.data, blob.length);
len = blob.length;
+ if (len > 256) {
+ DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len));
+ len = 255;
+ }
+ *pkeylen = len;
data_blob_free(&blob);
return len;
}
-
-
/****************************************************************************
-reply for the nt protocol
+ Reply for the nt protocol.
****************************************************************************/
+
static int reply_nt1(char *inbuf, char *outbuf)
{
/* dual names + lock_and_read + nt SMBs + remote API calls */
int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
- CAP_LEVEL_II_OPLOCKS|CAP_STATUS32;
+ CAP_LEVEL_II_OPLOCKS;
int secword=0;
- time_t t = time(NULL);
- DATA_BLOB cryptkey;
char *p, *q;
BOOL negotiate_spnego = False;
+ time_t t = time(NULL);
global_encrypted_passwords_negotiated = lp_encrypted_passwords();
if (global_encrypted_passwords_negotiated &&
(lp_security() != SEC_SHARE) &&
+ lp_use_spnego() &&
(SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
negotiate_spnego = True;
capabilities |= CAP_EXTENDED_SECURITY;
+ add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
+ /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
+ partially constructed. */
+ SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
}
- capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
+ capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
+
+ if (lp_unix_extensions()) {
+ capabilities |= CAP_UNIX;
+ }
- if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
+ if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
- }
- if (SMB_OFF_T_BITS == 64) {
+ if (SMB_OFF_T_BITS == 64)
capabilities |= CAP_LARGE_FILES;
- }
-
- if (lp_readraw() && lp_writeraw()) {
+
+ if (lp_readraw() && lp_writeraw())
capabilities |= CAP_RAW_MODE;
- }
- /* allow for disabling unicode */
- if (lp_unicode()) {
- capabilities |= CAP_UNICODE;
- }
+ if (lp_nt_status_support())
+ capabilities |= CAP_STATUS32;
if (lp_host_msdfs())
capabilities |= CAP_DFS;
- if (lp_security() >= SEC_USER) secword |= 1;
- if (global_encrypted_passwords_negotiated) secword |= 2;
+ if (lp_security() >= SEC_USER)
+ secword |= NEGOTIATE_SECURITY_USER_LEVEL;
+ if (global_encrypted_passwords_negotiated)
+ secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
+ if (lp_server_signing()) {
+ if (lp_security() >= SEC_USER) {
+ secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
+ /* No raw mode with smb signing. */
+ capabilities &= ~CAP_RAW_MODE;
+ if (lp_server_signing() == Required)
+ secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
+ srv_set_signing_negotiated();
+ } else {
+ DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
+ if (lp_server_signing() == Required) {
+ exit_server("reply_nt1: smb signing required and share level security selected.");
+ }
+ }
+ }
+
set_message(outbuf,17,0,True);
- CVAL(outbuf,smb_vwv1) = secword;
+ SCVAL(outbuf,smb_vwv1,secword);
Protocol = PROTOCOL_NT1;
SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
- SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
+ SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
put_long_date(outbuf+smb_vwv11+1,t);
- SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
+ SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
p = q = smb_buf(outbuf);
if (!negotiate_spnego) {
- if (global_encrypted_passwords_negotiated) {
- if (!make_auth_info_subsystem(&negprot_global_auth_info)) {
- smb_panic("cannot make_negprot_global_auth_info!\n");
- }
- cryptkey = auth_get_challenge(negprot_global_auth_info);
- memcpy(p, cryptkey.data, 8);
- data_blob_free(&cryptkey);
+ /* Create a token value and add it to the outgoing packet. */
+ if (global_encrypted_passwords_negotiated) {
+ /* note that we do not send a challenge at all if
+ we are using plaintext */
+ get_challenge(p);
+ SCVAL(outbuf,smb_vwv16+1,8);
+ p += 8;
}
- SSVALS(outbuf,smb_vwv16+1,8);
- p += 8;
- p += srvstr_push(outbuf, p, global_myworkgroup, -1,
+ p += srvstr_push(outbuf, p, lp_workgroup(), -1,
STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
DEBUG(3,("not using SPNEGO\n"));
} else {
- int len = negprot_spnego(p);
+ uint8 keylen;
+ int len = negprot_spnego(p, &keylen);
- SSVALS(outbuf,smb_vwv16+1,len);
+ SCVAL(outbuf,smb_vwv16+1,keylen);
p += len;
DEBUG(3,("using SPNEGO\n"));
}
#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_ALL 0x3F
+#define ARCH_ALL 0x7F
/* List of supported protocols, most desired first */
-static struct {
- char *proto_name;
- char *short_name;
- int (*proto_reply_fn)(char *, char *);
- int protocol_level;
+static const struct {
+ const char *proto_name;
+ const char *short_name;
+ int (*proto_reply_fn)(char *, char *);
+ int protocol_level;
} supported_protocols[] = {
- {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
- {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
- {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
- {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
- {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
- {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
- {NULL,NULL,NULL,0},
+ {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
+ {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
+ {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
+ {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
+ {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
+ {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
+ {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
+ {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
+ {NULL,NULL,NULL,0},
};
-
/****************************************************************************
- reply to a negprot
+ Reply to a negprot.
****************************************************************************/
+
int reply_negprot(connection_struct *conn,
char *inbuf,char *outbuf, int dum_size,
int dum_buffsize)
{
- int outsize = set_message(outbuf,1,0,True);
- int Index=0;
- int choice= -1;
- int protocol;
- char *p;
- int bcc = SVAL(smb_buf(inbuf),-2);
- int arch = ARCH_ALL;
- START_PROFILE(SMBnegprot);
-
- p = smb_buf(inbuf)+1;
- while (p < (smb_buf(inbuf) + bcc))
- {
- Index++;
- DEBUG(3,("Requested protocol [%s]\n",p));
- if (strcsequal(p,"Windows for Workgroups 3.1a"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcsequal(p,"DOS LM1.2X002"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(p,"DOS LANMAN2.1"))
- arch &= ( ARCH_WFWG | ARCH_WIN95 );
- else if (strcsequal(p,"NT LM 0.12"))
- arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
- else if (strcsequal(p,"LANMAN2.1"))
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(p,"LM1.2X002"))
- arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
- else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
- arch &= ARCH_WINNT;
- else if (strcsequal(p,"XENIX CORE"))
- arch &= ( ARCH_WINNT | ARCH_OS2 );
- else if (strcsequal(p,"Samba")) {
- arch = ARCH_SAMBA;
- break;
- }
+ int outsize = set_message(outbuf,1,0,True);
+ int Index=0;
+ int choice= -1;
+ int protocol;
+ char *p;
+ int bcc = SVAL(smb_buf(inbuf),-2);
+ int arch = ARCH_ALL;
+
+ static BOOL done_negprot = False;
+
+ START_PROFILE(SMBnegprot);
+
+ if (done_negprot) {
+ END_PROFILE(SMBnegprot);
+ exit_server("multiple negprot's are not permitted");
+ }
+ done_negprot = True;
+
+ p = smb_buf(inbuf)+1;
+ while (p < (smb_buf(inbuf) + bcc)) {
+ Index++;
+ DEBUG(3,("Requested protocol [%s]\n",p));
+ if (strcsequal(p,"Windows for Workgroups 3.1a"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
+ else if (strcsequal(p,"DOS LM1.2X002"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 );
+ else if (strcsequal(p,"DOS LANMAN2.1"))
+ arch &= ( ARCH_WFWG | ARCH_WIN95 );
+ else if (strcsequal(p,"NT LM 0.12"))
+ arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
+ else if (strcsequal(p,"LANMAN2.1"))
+ arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
+ else if (strcsequal(p,"LM1.2X002"))
+ arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
+ else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
+ arch &= ARCH_WINNT;
+ else if (strcsequal(p,"XENIX CORE"))
+ arch &= ( ARCH_WINNT | ARCH_OS2 );
+ else if (strcsequal(p,"Samba")) {
+ arch = ARCH_SAMBA;
+ break;
+ } else if (strcsequal(p,"POSIX 2")) {
+ arch = ARCH_CIFSFS;
+ break;
+ }
- p += strlen(p) + 2;
- }
-
- switch ( arch ) {
- case ARCH_SAMBA:
- set_remote_arch(RA_SAMBA);
- break;
- case ARCH_WFWG:
- set_remote_arch(RA_WFWG);
- break;
- case ARCH_WIN95:
- set_remote_arch(RA_WIN95);
- break;
- case ARCH_WINNT:
- if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
- set_remote_arch(RA_WIN2K);
- else
- set_remote_arch(RA_WINNT);
- break;
- case ARCH_WIN2K:
- set_remote_arch(RA_WIN2K);
- break;
- case ARCH_OS2:
- set_remote_arch(RA_OS2);
- break;
- default:
- set_remote_arch(RA_UNKNOWN);
- break;
- }
+ p += strlen(p) + 2;
+ }
+
+ /* CIFSFS can send one arch only, NT LM 0.12. */
+ if (Index == 1 && (arch & ARCH_CIFSFS)) {
+ arch = ARCH_CIFSFS;
+ }
+
+ switch ( arch ) {
+ case ARCH_CIFSFS:
+ set_remote_arch(RA_CIFSFS);
+ break;
+ case ARCH_SAMBA:
+ set_remote_arch(RA_SAMBA);
+ break;
+ case ARCH_WFWG:
+ set_remote_arch(RA_WFWG);
+ break;
+ case ARCH_WIN95:
+ set_remote_arch(RA_WIN95);
+ break;
+ case ARCH_WINNT:
+ if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
+ set_remote_arch(RA_WIN2K);
+ else
+ set_remote_arch(RA_WINNT);
+ break;
+ case ARCH_WIN2K:
+ set_remote_arch(RA_WIN2K);
+ break;
+ case ARCH_OS2:
+ set_remote_arch(RA_OS2);
+ break;
+ default:
+ set_remote_arch(RA_UNKNOWN);
+ break;
+ }
- /* possibly reload - change of architecture */
- reload_services(True);
+ /* possibly reload - change of architecture */
+ reload_services(True);
+
+ /* moved from the netbios session setup code since we don't have that
+ when the client connects to port 445. Of course there is a small
+ window where we are listening to messages -- jerry */
+
+ claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
- /* Check for protocols, most desirable first */
- for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
- {
- p = smb_buf(inbuf)+1;
- Index = 0;
- if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
- (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
- while (p < (smb_buf(inbuf) + bcc))
- {
- if (strequal(p,supported_protocols[protocol].proto_name))
- choice = Index;
- Index++;
- p += strlen(p) + 2;
- }
- if(choice != -1)
- break;
- }
+ /* Check for protocols, most desirable first */
+ for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
+ p = smb_buf(inbuf)+1;
+ Index = 0;
+ if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
+ (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
+ while (p < (smb_buf(inbuf) + bcc)) {
+ if (strequal(p,supported_protocols[protocol].proto_name))
+ choice = Index;
+ Index++;
+ p += strlen(p) + 2;
+ }
+ if(choice != -1)
+ break;
+ }
- SSVAL(outbuf,smb_vwv0,choice);
- if(choice != -1) {
- extern fstring remote_proto;
- fstrcpy(remote_proto,supported_protocols[protocol].short_name);
- reload_services(True);
- outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
- DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
- }
- else {
- DEBUG(0,("No protocol supported !\n"));
- }
- SSVAL(outbuf,smb_vwv0,choice);
+ SSVAL(outbuf,smb_vwv0,choice);
+ if(choice != -1) {
+ fstrcpy(remote_proto,supported_protocols[protocol].short_name);
+ reload_services(True);
+ outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
+ DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
+ } else {
+ DEBUG(0,("No protocol supported !\n"));
+ }
+ SSVAL(outbuf,smb_vwv0,choice);
- DEBUG( 5, ( "negprot index=%d\n", choice ) );
+ DEBUG( 5, ( "negprot index=%d\n", choice ) );
- END_PROFILE(SMBnegprot);
- return(outsize);
-}
+ if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
+ exit_server("SMB signing is required and client negotiated a downlevel protocol");
+ }
+ END_PROFILE(SMBnegprot);
+ return(outsize);
+}