Merge branch 'master' of ssh://git.samba.org/data/git/samba
[ddiss/samba.git] / source3 / smbd / negprot.c
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
23 extern fstring remote_proto;
24 extern enum protocol_types Protocol;
25 extern int max_recv;
26
27 bool global_encrypted_passwords_negotiated = False;
28 bool global_spnego_negotiated = False;
29 struct auth_context *negprot_global_auth_context = NULL;
30
31 static void get_challenge(uint8 buff[8])
32 {
33         NTSTATUS nt_status;
34         const uint8 *cryptkey;
35
36         /* We might be called more than once, multiple negprots are
37          * permitted */
38         if (negprot_global_auth_context) {
39                 DEBUG(3, ("get challenge: is this a secondary negprot?  negprot_global_auth_context is non-NULL!\n"));
40                 (negprot_global_auth_context->free)(&negprot_global_auth_context);
41         }
42
43         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
44         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
45                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
46                 smb_panic("cannot make_negprot_global_auth_context!");
47         }
48         DEBUG(10, ("get challenge: getting challenge\n"));
49         cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
50         memcpy(buff, cryptkey, 8);
51 }
52
53 /****************************************************************************
54  Reply for the core protocol.
55 ****************************************************************************/
56
57 static void reply_corep(struct smb_request *req, uint16 choice)
58 {
59         reply_outbuf(req, 1, 0);
60         SSVAL(req->outbuf, smb_vwv0, choice);
61
62         Protocol = PROTOCOL_CORE;
63 }
64
65 /****************************************************************************
66  Reply for the coreplus protocol.
67 ****************************************************************************/
68
69 static void reply_coreplus(struct smb_request *req, uint16 choice)
70 {
71         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
72
73         reply_outbuf(req, 13, 0);
74
75         SSVAL(req->outbuf,smb_vwv0,choice);
76         SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
77                         readbraw and writebraw (possibly) */
78         /* Reply, SMBlockread, SMBwritelock supported. */
79         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
80         SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
81                                           * encrypt */
82         Protocol = PROTOCOL_COREPLUS;
83 }
84
85 /****************************************************************************
86  Reply for the lanman 1.0 protocol.
87 ****************************************************************************/
88
89 static void reply_lanman1(struct smb_request *req, uint16 choice)
90 {
91         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
92         int secword=0;
93         time_t t = time(NULL);
94
95         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
96
97         if (lp_security()>=SEC_USER)
98                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
99         if (global_encrypted_passwords_negotiated)
100                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
101
102         reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0);
103
104         SSVAL(req->outbuf,smb_vwv0,choice);
105         SSVAL(req->outbuf,smb_vwv1,secword);
106         /* Create a token value and add it to the outgoing packet. */
107         if (global_encrypted_passwords_negotiated) {
108                 get_challenge((uint8 *)smb_buf(req->outbuf));
109                 SSVAL(req->outbuf,smb_vwv11, 8);
110         }
111
112         Protocol = PROTOCOL_LANMAN1;
113
114         /* Reply, SMBlockread, SMBwritelock supported. */
115         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
116         SSVAL(req->outbuf,smb_vwv2,max_recv);
117         SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
118         SSVAL(req->outbuf,smb_vwv4,1);
119         SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
120                 readbraw writebraw (possibly) */
121         SIVAL(req->outbuf,smb_vwv6,sys_getpid());
122         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
123
124         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
125
126         return;
127 }
128
129 /****************************************************************************
130  Reply for the lanman 2.0 protocol.
131 ****************************************************************************/
132
133 static void reply_lanman2(struct smb_request *req, uint16 choice)
134 {
135         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
136         int secword=0;
137         time_t t = time(NULL);
138
139         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
140   
141         if (lp_security()>=SEC_USER)
142                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
143         if (global_encrypted_passwords_negotiated)
144                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
145
146         reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0);
147
148         SSVAL(req->outbuf,smb_vwv0,choice);
149         SSVAL(req->outbuf,smb_vwv1,secword);
150         SIVAL(req->outbuf,smb_vwv6,sys_getpid());
151
152         /* Create a token value and add it to the outgoing packet. */
153         if (global_encrypted_passwords_negotiated) {
154                 get_challenge((uint8 *)smb_buf(req->outbuf));
155                 SSVAL(req->outbuf,smb_vwv11, 8);
156         }
157
158         Protocol = PROTOCOL_LANMAN2;
159
160         /* Reply, SMBlockread, SMBwritelock supported. */
161         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
162         SSVAL(req->outbuf,smb_vwv2,max_recv);
163         SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
164         SSVAL(req->outbuf,smb_vwv4,1);
165         SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
166         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
167         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
168 }
169
170 /****************************************************************************
171  Generate the spnego negprot reply blob. Return the number of bytes used.
172 ****************************************************************************/
173
174 static DATA_BLOB negprot_spnego(void)
175 {
176         DATA_BLOB blob;
177         nstring dos_name;
178         fstring unix_name;
179 #ifdef DEVELOPER
180         size_t slen;
181 #endif
182         char guid[17];
183         const char *OIDs_krb5[] = {OID_KERBEROS5,
184                                    OID_KERBEROS5_OLD,
185                                    OID_NTLMSSP,
186                                    NULL};
187         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
188
189         global_spnego_negotiated = True;
190
191         memset(guid, '\0', sizeof(guid));
192
193         safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
194         strlower_m(unix_name);
195         push_ascii_nstring(dos_name, unix_name);
196         safe_strcpy(guid, dos_name, sizeof(guid)-1);
197
198 #ifdef DEVELOPER
199         /* Fix valgrind 'uninitialized bytes' issue. */
200         slen = strlen(dos_name);
201         if (slen < sizeof(guid)) {
202                 memset(guid+slen, '\0', sizeof(guid) - slen);
203         }
204 #endif
205
206         /* strangely enough, NT does not sent the single OID NTLMSSP when
207            not a ADS member, it sends no OIDs at all
208
209            OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
210                    about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
211
212            Our sessionsetup code now handles raw NTLMSSP connects, so we can go
213            back to doing what W2K3 does here. This is needed to make PocketPC 2003
214            CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
215            for details. JRA.
216
217         */
218
219         if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
220 #if 0
221                 /* Code for PocketPC client */
222                 blob = data_blob(guid, 16);
223 #else
224                 /* Code for standalone WXP client */
225                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
226 #endif
227         } else {
228                 fstring myname;
229                 char *host_princ_s = NULL;
230                 name_to_fqdn(myname, global_myname());
231                 strlower_m(myname);
232                 if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm())
233                     == -1) {
234                         return data_blob_null;
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(struct smb_request *req)
509 {
510         int choice= -1;
511         int protocol;
512         const char *p;
513         int arch = ARCH_ALL;
514         int num_cliprotos;
515         char **cliprotos;
516         int i;
517         size_t converted_size;
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->buflen == 0) {
530                 DEBUG(0, ("negprot got no protocols\n"));
531                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
532                 END_PROFILE(SMBnegprot);
533                 return;
534         }
535
536         if (req->buf[req->buflen-1] != '\0') {
537                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
538                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
539                 END_PROFILE(SMBnegprot);
540                 return;
541         }
542
543         p = (const char *)req->buf + 1;
544
545         num_cliprotos = 0;
546         cliprotos = NULL;
547
548         while (smbreq_bufrem(req, p) > 0) {
549
550                 char **tmp;
551
552                 tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), cliprotos, char *,
553                                            num_cliprotos+1);
554                 if (tmp == NULL) {
555                         DEBUG(0, ("talloc failed\n"));
556                         TALLOC_FREE(cliprotos);
557                         reply_nterror(req, NT_STATUS_NO_MEMORY);
558                         END_PROFILE(SMBnegprot);
559                         return;
560                 }
561
562                 cliprotos = tmp;
563
564                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
565                                        &converted_size)) {
566                         DEBUG(0, ("pull_ascii_talloc failed\n"));
567                         TALLOC_FREE(cliprotos);
568                         reply_nterror(req, NT_STATUS_NO_MEMORY);
569                         END_PROFILE(SMBnegprot);
570                         return;
571                 }
572
573                 DEBUG(3, ("Requested protocol [%s]\n",
574                           cliprotos[num_cliprotos]));
575
576                 num_cliprotos += 1;
577                 p += strlen(p) + 2;
578         }
579
580         for (i=0; i<num_cliprotos; i++) {
581                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
582                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
583                                   | ARCH_WIN2K );
584                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
585                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
586                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
587                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
588                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
589                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
590                                   | ARCH_CIFSFS);
591                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
592                         arch = ARCH_VISTA;              
593                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
594                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
595                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
596                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
597                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
598                         arch &= ARCH_WINNT;
599                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
600                         arch &= ( ARCH_WINNT | ARCH_OS2 );
601                 else if (strcsequal(cliprotos[i], "Samba")) {
602                         arch = ARCH_SAMBA;
603                         break;
604                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
605                         arch = ARCH_CIFSFS;
606                         break;
607                 }
608         }
609
610         /* CIFSFS can send one arch only, NT LM 0.12. */
611         if (i == 1 && (arch & ARCH_CIFSFS)) {
612                 arch = ARCH_CIFSFS;
613         }
614
615         switch ( arch ) {
616                 case ARCH_CIFSFS:
617                         set_remote_arch(RA_CIFSFS);
618                         break;
619                 case ARCH_SAMBA:
620                         set_remote_arch(RA_SAMBA);
621                         break;
622                 case ARCH_WFWG:
623                         set_remote_arch(RA_WFWG);
624                         break;
625                 case ARCH_WIN95:
626                         set_remote_arch(RA_WIN95);
627                         break;
628                 case ARCH_WINNT:
629                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
630                                 set_remote_arch(RA_WIN2K);
631                         else
632                                 set_remote_arch(RA_WINNT);
633                         break;
634                 case ARCH_WIN2K:
635                         /* Vista may have been set in the negprot so don't 
636                            override it here */
637                         if ( get_remote_arch() != RA_VISTA )
638                                 set_remote_arch(RA_WIN2K);
639                         break;
640                 case ARCH_VISTA:
641                         set_remote_arch(RA_VISTA);
642                         break;
643                 case ARCH_OS2:
644                         set_remote_arch(RA_OS2);
645                         break;
646                 default:
647                         set_remote_arch(RA_UNKNOWN);
648                 break;
649         }
650  
651         /* possibly reload - change of architecture */
652         reload_services(True);      
653         
654         /* moved from the netbios session setup code since we don't have that 
655            when the client connects to port 445.  Of course there is a small
656            window where we are listening to messages   -- jerry */
657
658         claim_connection(
659                 NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
660     
661         /* Check for protocols, most desirable first */
662         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
663                 i = 0;
664                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
665                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
666                         while (i < num_cliprotos) {
667                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
668                                         choice = i;
669                                 i++;
670                         }
671                 if(choice != -1)
672                         break;
673         }
674   
675         if(choice != -1) {
676                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
677                 reload_services(True);          
678                 supported_protocols[protocol].proto_reply_fn(req, choice);
679                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
680         } else {
681                 DEBUG(0,("No protocol supported !\n"));
682                 reply_outbuf(req, 1, 0);
683                 SSVAL(req->outbuf, smb_vwv0, choice);
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 }