1/*
2   Unix SMB/CIFS implementation.
3   negprot reply code
4   Copyright (C) Andrew Tridgell 1992-1998
5   Copyright (C) Volker Lendecke 2007
6
7   This program is free software; you can redistribute it and/or modify
8   it under the terms of the GNU General Public License as published by
9   the Free Software Foundation; either version 3 of the License, or
10   (at your option) any later version.
11
12   This program is distributed in the hope that it will be useful,
13   but WITHOUT ANY WARRANTY; without even the implied warranty of
14   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15   GNU General Public License for more details.
16
17   You should have received a copy of the GNU General Public License
18   along with this program.  If not, see <http://www.gnu.org/licenses/>.
19*/
20
21#include "includes.h"
22#include "smbd/globals.h"
23#include "../libcli/auth/spnego.h"
24
25extern fstring remote_proto;
26
27static void get_challenge(uint8 buff[8])
28{
29	NTSTATUS nt_status;
30	struct smbd_server_connection *sconn = smbd_server_conn;
31
32	/* We might be called more than once, multiple negprots are
33	 * permitted */
34	if (sconn->smb1.negprot.auth_context) {
35		DEBUG(3, ("get challenge: is this a secondary negprot? "
36			  "sconn->negprot.auth_context is non-NULL!\n"));
37			sconn->smb1.negprot.auth_context->free(
38				&sconn->smb1.negprot.auth_context);
39	}
40
41	DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
42	nt_status = make_auth_context_subsystem(
43		&sconn->smb1.negprot.auth_context);
44	if (!NT_STATUS_IS_OK(nt_status)) {
45		DEBUG(0, ("make_auth_context_subsystem returned %s",
46			  nt_errstr(nt_status)));
47		smb_panic("cannot make_negprot_global_auth_context!");
48	}
49	DEBUG(10, ("get challenge: getting challenge\n"));
50	sconn->smb1.negprot.auth_context->get_ntlm_challenge(
51		sconn->smb1.negprot.auth_context, buff);
52}
53
54/****************************************************************************
55 Reply for the core protocol.
56****************************************************************************/
57
58static void reply_corep(struct smb_request *req, uint16 choice)
59{
60	reply_outbuf(req, 1, 0);
61	SSVAL(req->outbuf, smb_vwv0, choice);
62
63	set_Protocol(PROTOCOL_CORE);
64}
65
66/****************************************************************************
67 Reply for the coreplus protocol.
68****************************************************************************/
69
70static void reply_coreplus(struct smb_request *req, uint16 choice)
71{
72	int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
73
74	reply_outbuf(req, 13, 0);
75
76	SSVAL(req->outbuf,smb_vwv0,choice);
77	SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
78			readbraw and writebraw (possibly) */
79	/* Reply, SMBlockread, SMBwritelock supported. */
80	SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
81	SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
82					  * encrypt */
83	set_Protocol(PROTOCOL_COREPLUS);
84}
85
86/****************************************************************************
87 Reply for the lanman 1.0 protocol.
88****************************************************************************/
89
90static void reply_lanman1(struct smb_request *req, uint16 choice)
91{
92	int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
93	int secword=0;
94	time_t t = time(NULL);
95	struct smbd_server_connection *sconn = smbd_server_conn;
96
97	sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
98
99	if (lp_security()>=SEC_USER) {
100		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
101	}
102	if (sconn->smb1.negprot.encrypted_passwords) {
103		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
104	}
105
106	reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
107
108	SSVAL(req->outbuf,smb_vwv0,choice);
109	SSVAL(req->outbuf,smb_vwv1,secword);
110	/* Create a token value and add it to the outgoing packet. */
111	if (sconn->smb1.negprot.encrypted_passwords) {
112		get_challenge((uint8 *)smb_buf(req->outbuf));
113		SSVAL(req->outbuf,smb_vwv11, 8);
114	}
115
116	set_Protocol(PROTOCOL_LANMAN1);
117
118	/* Reply, SMBlockread, SMBwritelock supported. */
119	SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
120	SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
121	SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
122	SSVAL(req->outbuf,smb_vwv4,1);
123	SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
124		readbraw writebraw (possibly) */
125	SIVAL(req->outbuf,smb_vwv6,sys_getpid());
126	SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
127
128	srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
129
130	return;
131}
132
133/****************************************************************************
134 Reply for the lanman 2.0 protocol.
135****************************************************************************/
136
137static void reply_lanman2(struct smb_request *req, uint16 choice)
138{
139	int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
140	int secword=0;
141	time_t t = time(NULL);
142	struct smbd_server_connection *sconn = smbd_server_conn;
143
144	sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
145
146	if (lp_security()>=SEC_USER) {
147		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
148	}
149	if (sconn->smb1.negprot.encrypted_passwords) {
150		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
151	}
152
153	reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
154
155	SSVAL(req->outbuf,smb_vwv0,choice);
156	SSVAL(req->outbuf,smb_vwv1,secword);
157	SIVAL(req->outbuf,smb_vwv6,sys_getpid());
158
159	/* Create a token value and add it to the outgoing packet. */
160	if (sconn->smb1.negprot.encrypted_passwords) {
161		get_challenge((uint8 *)smb_buf(req->outbuf));
162		SSVAL(req->outbuf,smb_vwv11, 8);
163	}
164
165	set_Protocol(PROTOCOL_LANMAN2);
166
167	/* Reply, SMBlockread, SMBwritelock supported. */
168	SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
169	SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
170	SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
171	SSVAL(req->outbuf,smb_vwv4,1);
172	SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
173	SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
174	srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
175}
176
177/****************************************************************************
178 Generate the spnego negprot reply blob. Return the number of bytes used.
179****************************************************************************/
180
181DATA_BLOB negprot_spnego(void)
182{
183	DATA_BLOB blob;
184	nstring dos_name;
185	fstring unix_name;
186#ifdef DEVELOPER
187	size_t slen;
188#endif
189	char guid[17];
190	const char *OIDs_krb5[] = {OID_KERBEROS5,
191				   OID_KERBEROS5_OLD,
192				   OID_NTLMSSP,
193				   NULL};
194	const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
195	struct smbd_server_connection *sconn = smbd_server_conn;
196
197	sconn->smb1.negprot.spnego = true;
198
199	memset(guid, '\0', sizeof(guid));
200
201	safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
202	strlower_m(unix_name);
203	push_ascii_nstring(dos_name, unix_name);
204	safe_strcpy(guid, dos_name, sizeof(guid)-1);
205
206#ifdef DEVELOPER
207	/* Fix valgrind 'uninitialized bytes' issue. */
208	slen = strlen(dos_name);
209	if (slen < sizeof(guid)) {
210		memset(guid+slen, '\0', sizeof(guid) - slen);
211	}
212#endif
213
214	/* strangely enough, NT does not sent the single OID NTLMSSP when
215	   not a ADS member, it sends no OIDs at all
216
217	   OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
218		   about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
219
220	   Our sessionsetup code now handles raw NTLMSSP connects, so we can go
221	   back to doing what W2K3 does here. This is needed to make PocketPC 2003
222	   CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
223	   for details. JRA.
224
225	*/
226
227	if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
228#if 0
229		/* Code for PocketPC client */
230		blob = data_blob(guid, 16);
231#else
232		/* Code for standalone WXP client */
233		blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
234#endif
235	} else {
236		fstring myname;
237		char *host_princ_s = NULL;
238		name_to_fqdn(myname, global_myname());
239		strlower_m(myname);
240		if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm())
241		    == -1) {
242			return data_blob_null;
243		}
244		blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
245		SAFE_FREE(host_princ_s);
246	}
247
248	return blob;
249}
250
251/****************************************************************************
252 Reply for the nt protocol.
253****************************************************************************/
254
255static void reply_nt1(struct smb_request *req, uint16 choice)
256{
257	/* dual names + lock_and_read + nt SMBs + remote API calls */
258	int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
259		CAP_LEVEL_II_OPLOCKS;
260
261	int secword=0;
262	char *p, *q;
263	bool negotiate_spnego = False;
264	time_t t = time(NULL);
265	ssize_t ret;
266	struct smbd_server_connection *sconn = smbd_server_conn;
267
268	sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
269
270	/* Check the flags field to see if this is Vista.
271	   WinXP sets it and Vista does not. But we have to
272	   distinguish from NT which doesn't set it either. */
273
274	if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
275		((req->flags2 & FLAGS2_UNKNOWN_BIT4) == 0) )
276	{
277		if (get_remote_arch() != RA_SAMBA) {
278			set_remote_arch( RA_VISTA );
279		}
280	}
281
282	reply_outbuf(req,17,0);
283
284	/* do spnego in user level security if the client
285	   supports it and we can do encrypted passwords */
286
287	if (sconn->smb1.negprot.encrypted_passwords &&
288	    (lp_security() != SEC_SHARE) &&
289	    lp_use_spnego() &&
290	    (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
291		negotiate_spnego = True;
292		capabilities |= CAP_EXTENDED_SECURITY;
293		add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
294		/* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
295		   (already partially constructed. */
296		SSVAL(req->outbuf, smb_flg2,
297		      req->flags2 | FLAGS2_EXTENDED_SECURITY);
298	}
299
300	capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
301
302	if (lp_unix_extensions()) {
303		capabilities |= CAP_UNIX;
304	}
305
306	if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
307		capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
308
309	if (SMB_OFF_T_BITS == 64)
310		capabilities |= CAP_LARGE_FILES;
311
312	if (lp_readraw() && lp_writeraw())
313		capabilities |= CAP_RAW_MODE;
314
315	if (lp_nt_status_support())
316		capabilities |= CAP_STATUS32;
317
318	if (lp_host_msdfs())
319		capabilities |= CAP_DFS;
320
321	if (lp_security() >= SEC_USER) {
322		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
323	}
324	if (sconn->smb1.negprot.encrypted_passwords) {
325		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
326	}
327
328	if (lp_server_signing()) {
329	       	if (lp_security() >= SEC_USER) {
330			secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
331			/* No raw mode with smb signing. */
332			capabilities &= ~CAP_RAW_MODE;
333			if (lp_server_signing() == Required)
334				secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
335			srv_set_signing_negotiated(smbd_server_conn);
336		} else {
337			DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
338			if (lp_server_signing() == Required) {
339				exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
340			}
341		}
342	}
343
344	SSVAL(req->outbuf,smb_vwv0,choice);
345	SCVAL(req->outbuf,smb_vwv1,secword);
346
347	set_Protocol(PROTOCOL_NT1);
348
349	SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
350	SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
351	SIVAL(req->outbuf,smb_vwv3+1,
352	      sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
353	SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
354	SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
355	SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
356	put_long_date((char *)req->outbuf+smb_vwv11+1,t);
357	SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
358
359	p = q = smb_buf(req->outbuf);
360	if (!negotiate_spnego) {
361		/* Create a token value and add it to the outgoing packet. */
362		if (sconn->smb1.negprot.encrypted_passwords) {
363			uint8 chal[8];
364			/* note that we do not send a challenge at all if
365			   we are using plaintext */
366			get_challenge(chal);
367			ret = message_push_blob(
368				&req->outbuf, data_blob_const(chal, sizeof(chal)));
369			if (ret == -1) {
370				DEBUG(0, ("Could not push challenge\n"));
371				reply_nterror(req, NT_STATUS_NO_MEMORY);
372				return;
373			}
374			SCVAL(req->outbuf, smb_vwv16+1, ret);
375			p += ret;
376		}
377		ret = message_push_string(&req->outbuf, lp_workgroup(),
378					  STR_UNICODE|STR_TERMINATE
379					  |STR_NOALIGN);
380		if (ret == -1) {
381			DEBUG(0, ("Could not push challenge\n"));
382			reply_nterror(req, NT_STATUS_NO_MEMORY);
383			return;
384		}
385		DEBUG(3,("not using SPNEGO\n"));
386	} else {
387		DATA_BLOB spnego_blob = negprot_spnego();
388
389		if (spnego_blob.data == NULL) {
390			reply_nterror(req, NT_STATUS_NO_MEMORY);
391			return;
392		}
393
394		ret = message_push_blob(&req->outbuf, spnego_blob);
395		if (ret == -1) {
396			DEBUG(0, ("Could not push spnego blob\n"));
397			reply_nterror(req, NT_STATUS_NO_MEMORY);
398			return;
399		}
400		p += ret;
401		data_blob_free(&spnego_blob);
402
403		SCVAL(req->outbuf,smb_vwv16+1, 0);
404		DEBUG(3,("using SPNEGO\n"));
405	}
406
407	SSVAL(req->outbuf,smb_vwv17, p - q); /* length of challenge+domain
408					      * strings */
409
410	return;
411}
412
413/* these are the protocol lists used for auto architecture detection:
414
415WinNT 3.51:
416protocol [PC NETWORK PROGRAM 1.0]
417protocol [XENIX CORE]
418protocol [MICROSOFT NETWORKS 1.03]
419protocol [LANMAN1.0]
420protocol [Windows for Workgroups 3.1a]
421protocol [LM1.2X002]
422protocol [LANMAN2.1]
423protocol [NT LM 0.12]
424
425Win95:
426protocol [PC NETWORK PROGRAM 1.0]
427protocol [XENIX CORE]
428protocol [MICROSOFT NETWORKS 1.03]
429protocol [LANMAN1.0]
430protocol [Windows for Workgroups 3.1a]
431protocol [LM1.2X002]
432protocol [LANMAN2.1]
433protocol [NT LM 0.12]
434
435Win2K:
436protocol [PC NETWORK PROGRAM 1.0]
437protocol [LANMAN1.0]
438protocol [Windows for Workgroups 3.1a]
439protocol [LM1.2X002]
440protocol [LANMAN2.1]
441protocol [NT LM 0.12]
442
443Vista:
444protocol [PC NETWORK PROGRAM 1.0]
445protocol [LANMAN1.0]
446protocol [Windows for Workgroups 3.1a]
447protocol [LM1.2X002]
448protocol [LANMAN2.1]
449protocol [NT LM 0.12]
450protocol [SMB 2.001]
451
452OS/2:
453protocol [PC NETWORK PROGRAM 1.0]
454protocol [XENIX CORE]
455protocol [LANMAN1.0]
456protocol [LM1.2X002]
457protocol [LANMAN2.1]
458*/
459
460/*
461  * Modified to recognize the architecture of the remote machine better.
462  *
463  * This appears to be the matrix of which protocol is used by which
464  * MS product.
465       Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
466       PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
467       XENIX CORE                                      2             2
468       MICROSOFT NETWORKS 3.0          2       2
469       DOS LM1.2X002                   3       3
470       MICROSOFT NETWORKS 1.03                         3
471       DOS LANMAN2.1                   4       4
472       LANMAN1.0                                       4      2      3     2
473       Windows for Workgroups 3.1a     5       5       5      3            3
474       LM1.2X002                                       6      4      4     4
475       LANMAN2.1                                       7      5      5     5
476       NT LM 0.12                              6       8      6            6
477       SMB 2.001                                                           7
478  *
479  *  tim@fsg.com 09/29/95
480  *  Win2K added by matty 17/7/99
481  */
482
483#define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
484#define ARCH_WIN95    0x2
485#define ARCH_WINNT    0x4
486#define ARCH_WIN2K    0xC      /* Win2K is like NT */
487#define ARCH_OS2      0x14     /* Again OS/2 is like NT */
488#define ARCH_SAMBA    0x20
489#define ARCH_CIFSFS   0x40
490#define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
491
492#define ARCH_ALL      0x7F
493
494/* List of supported protocols, most desired first */
495static const struct {
496	const char *proto_name;
497	const char *short_name;
498	void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
499	int protocol_level;
500} supported_protocols[] = {
501	{"SMB 2.002",               "SMB2",     reply_smb2002,  PROTOCOL_SMB2},
502	{"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
503	{"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
504	{"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
505	{"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
506	{"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
507	{"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
508	{"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
509	{"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
510	{"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
511	{"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
512	{"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE},
513	{NULL,NULL,NULL,0},
514};
515
516/****************************************************************************
517 Reply to a negprot.
518 conn POINTER CAN BE NULL HERE !
519****************************************************************************/
520
521void reply_negprot(struct smb_request *req)
522{
523	int choice= -1;
524	int protocol;
525	const char *p;
526	int arch = ARCH_ALL;
527	int num_cliprotos;
528	char **cliprotos;
529	int i;
530	size_t converted_size;
531	struct smbd_server_connection *sconn = smbd_server_conn;
532
533	START_PROFILE(SMBnegprot);
534
535	if (sconn->smb1.negprot.done) {
536		END_PROFILE(SMBnegprot);
537		exit_server_cleanly("multiple negprot's are not permitted");
538	}
539	sconn->smb1.negprot.done = true;
540
541	if (req->buflen == 0) {
542		DEBUG(0, ("negprot got no protocols\n"));
543		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
544		END_PROFILE(SMBnegprot);
545		return;
546	}
547
548	if (req->buf[req->buflen-1] != '\0') {
549		DEBUG(0, ("negprot protocols not 0-terminated\n"));
550		reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
551		END_PROFILE(SMBnegprot);
552		return;
553	}
554
555	p = (const char *)req->buf + 1;
556
557	num_cliprotos = 0;
558	cliprotos = NULL;
559
560	while (smbreq_bufrem(req, p) > 0) {
561
562		char **tmp;
563
564		tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), cliprotos, char *,
565					   num_cliprotos+1);
566		if (tmp == NULL) {
567			DEBUG(0, ("talloc failed\n"));
568			TALLOC_FREE(cliprotos);
569			reply_nterror(req, NT_STATUS_NO_MEMORY);
570			END_PROFILE(SMBnegprot);
571			return;
572		}
573
574		cliprotos = tmp;
575
576		if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
577				       &converted_size)) {
578			DEBUG(0, ("pull_ascii_talloc failed\n"));
579			TALLOC_FREE(cliprotos);
580			reply_nterror(req, NT_STATUS_NO_MEMORY);
581			END_PROFILE(SMBnegprot);
582			return;
583		}
584
585		DEBUG(3, ("Requested protocol [%s]\n",
586			  cliprotos[num_cliprotos]));
587
588		num_cliprotos += 1;
589		p += strlen(p) + 2;
590	}
591
592	for (i=0; i<num_cliprotos; i++) {
593		if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
594			arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
595				  | ARCH_WIN2K );
596		else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
597			arch &= ( ARCH_WFWG | ARCH_WIN95 );
598		else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
599			arch &= ( ARCH_WFWG | ARCH_WIN95 );
600		else if (strcsequal(cliprotos[i], "NT LM 0.12"))
601			arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
602				  | ARCH_CIFSFS);
603		else if (strcsequal(cliprotos[i], "SMB 2.001"))
604			arch = ARCH_VISTA;
605		else if (strcsequal(cliprotos[i], "LANMAN2.1"))
606			arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
607		else if (strcsequal(cliprotos[i], "LM1.2X002"))
608			arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
609		else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
610			arch &= ARCH_WINNT;
611		else if (strcsequal(cliprotos[i], "XENIX CORE"))
612			arch &= ( ARCH_WINNT | ARCH_OS2 );
613		else if (strcsequal(cliprotos[i], "Samba")) {
614			arch = ARCH_SAMBA;
615			break;
616		} else if (strcsequal(cliprotos[i], "POSIX 2")) {
617			arch = ARCH_CIFSFS;
618			break;
619		}
620	}
621
622	/* CIFSFS can send one arch only, NT LM 0.12. */
623	if (i == 1 && (arch & ARCH_CIFSFS)) {
624		arch = ARCH_CIFSFS;
625	}
626
627	switch ( arch ) {
628		case ARCH_CIFSFS:
629			set_remote_arch(RA_CIFSFS);
630			break;
631		case ARCH_SAMBA:
632			set_remote_arch(RA_SAMBA);
633			break;
634		case ARCH_WFWG:
635			set_remote_arch(RA_WFWG);
636			break;
637		case ARCH_WIN95:
638			set_remote_arch(RA_WIN95);
639			break;
640		case ARCH_WINNT:
641			if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
642				set_remote_arch(RA_WIN2K);
643			else
644				set_remote_arch(RA_WINNT);
645			break;
646		case ARCH_WIN2K:
647			/* Vista may have been set in the negprot so don't
648			   override it here */
649			if ( get_remote_arch() != RA_VISTA )
650				set_remote_arch(RA_WIN2K);
651			break;
652		case ARCH_VISTA:
653			set_remote_arch(RA_VISTA);
654			break;
655		case ARCH_OS2:
656			set_remote_arch(RA_OS2);
657			break;
658		default:
659			set_remote_arch(RA_UNKNOWN);
660		break;
661	}
662
663	/* possibly reload - change of architecture */
664	reload_services(True);
665
666	/* moved from the netbios session setup code since we don't have that
667	   when the client connects to port 445.  Of course there is a small
668	   window where we are listening to messages   -- jerry */
669
670	claim_connection(
671		NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
672
673	/* Check for protocols, most desirable first */
674	for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
675		i = 0;
676		if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
677				(supported_protocols[protocol].protocol_level >= lp_minprotocol()))
678			while (i < num_cliprotos) {
679				if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
680					choice = i;
681				i++;
682			}
683		if(choice != -1)
684			break;
685	}
686
687	if(choice != -1) {
688		fstrcpy(remote_proto,supported_protocols[protocol].short_name);
689		reload_services(True);
690		supported_protocols[protocol].proto_reply_fn(req, choice);
691		DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
692	} else {
693		DEBUG(0,("No protocol supported !\n"));
694		reply_outbuf(req, 1, 0);
695		SSVAL(req->outbuf, smb_vwv0, choice);
696	}
697
698	DEBUG( 5, ( "negprot index=%d\n", choice ) );
699
700	if ((lp_server_signing() == Required) && (get_Protocol() < PROTOCOL_NT1)) {
701		exit_server_cleanly("SMB signing is required and "
702			"client negotiated a downlevel protocol");
703	}
704
705	TALLOC_FREE(cliprotos);
706	END_PROFILE(SMBnegprot);
707	return;
708}
709