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