Remove a bunch of direct inbuf references by adding "buf" to smb_request
[nivanova/samba-autobuild/.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         size_t size = smb_len(req->inbuf) + 4;
511         int choice= -1;
512         int protocol;
513         const char *p;
514         int arch = ARCH_ALL;
515         int num_cliprotos;
516         char **cliprotos;
517         int i;
518         size_t converted_size;
519
520         static bool done_negprot = False;
521
522         START_PROFILE(SMBnegprot);
523
524         if (done_negprot) {
525                 END_PROFILE(SMBnegprot);
526                 exit_server_cleanly("multiple negprot's are not permitted");
527         }
528         done_negprot = True;
529
530         if (req->inbuf[size-1] != '\0') {
531                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
532                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
533                 END_PROFILE(SMBnegprot);
534                 return;
535         }
536
537         p = (const char *)req->buf + 1;
538
539         num_cliprotos = 0;
540         cliprotos = NULL;
541
542         while (smb_bufrem(req->inbuf, p) > 0) {
543
544                 char **tmp;
545
546                 tmp = TALLOC_REALLOC_ARRAY(talloc_tos(), cliprotos, char *,
547                                            num_cliprotos+1);
548                 if (tmp == NULL) {
549                         DEBUG(0, ("talloc failed\n"));
550                         TALLOC_FREE(cliprotos);
551                         reply_nterror(req, NT_STATUS_NO_MEMORY);
552                         END_PROFILE(SMBnegprot);
553                         return;
554                 }
555
556                 cliprotos = tmp;
557
558                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
559                                        &converted_size)) {
560                         DEBUG(0, ("pull_ascii_talloc failed\n"));
561                         TALLOC_FREE(cliprotos);
562                         reply_nterror(req, NT_STATUS_NO_MEMORY);
563                         END_PROFILE(SMBnegprot);
564                         return;
565                 }
566
567                 DEBUG(3, ("Requested protocol [%s]\n",
568                           cliprotos[num_cliprotos]));
569
570                 num_cliprotos += 1;
571                 p += strlen(p) + 2;
572         }
573
574         for (i=0; i<num_cliprotos; i++) {
575                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
576                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
577                                   | ARCH_WIN2K );
578                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
579                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
580                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
581                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
582                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
583                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
584                                   | ARCH_CIFSFS);
585                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
586                         arch = ARCH_VISTA;              
587                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
588                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
589                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
590                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
591                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
592                         arch &= ARCH_WINNT;
593                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
594                         arch &= ( ARCH_WINNT | ARCH_OS2 );
595                 else if (strcsequal(cliprotos[i], "Samba")) {
596                         arch = ARCH_SAMBA;
597                         break;
598                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
599                         arch = ARCH_CIFSFS;
600                         break;
601                 }
602         }
603
604         /* CIFSFS can send one arch only, NT LM 0.12. */
605         if (i == 1 && (arch & ARCH_CIFSFS)) {
606                 arch = ARCH_CIFSFS;
607         }
608
609         switch ( arch ) {
610                 case ARCH_CIFSFS:
611                         set_remote_arch(RA_CIFSFS);
612                         break;
613                 case ARCH_SAMBA:
614                         set_remote_arch(RA_SAMBA);
615                         break;
616                 case ARCH_WFWG:
617                         set_remote_arch(RA_WFWG);
618                         break;
619                 case ARCH_WIN95:
620                         set_remote_arch(RA_WIN95);
621                         break;
622                 case ARCH_WINNT:
623                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
624                                 set_remote_arch(RA_WIN2K);
625                         else
626                                 set_remote_arch(RA_WINNT);
627                         break;
628                 case ARCH_WIN2K:
629                         /* Vista may have been set in the negprot so don't 
630                            override it here */
631                         if ( get_remote_arch() != RA_VISTA )
632                                 set_remote_arch(RA_WIN2K);
633                         break;
634                 case ARCH_VISTA:
635                         set_remote_arch(RA_VISTA);
636                         break;
637                 case ARCH_OS2:
638                         set_remote_arch(RA_OS2);
639                         break;
640                 default:
641                         set_remote_arch(RA_UNKNOWN);
642                 break;
643         }
644  
645         /* possibly reload - change of architecture */
646         reload_services(True);      
647         
648         /* moved from the netbios session setup code since we don't have that 
649            when the client connects to port 445.  Of course there is a small
650            window where we are listening to messages   -- jerry */
651
652         claim_connection(
653                 NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
654     
655         /* Check for protocols, most desirable first */
656         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
657                 i = 0;
658                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
659                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
660                         while (i < num_cliprotos) {
661                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
662                                         choice = i;
663                                 i++;
664                         }
665                 if(choice != -1)
666                         break;
667         }
668   
669         if(choice != -1) {
670                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
671                 reload_services(True);          
672                 supported_protocols[protocol].proto_reply_fn(req, choice);
673                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
674         } else {
675                 DEBUG(0,("No protocol supported !\n"));
676                 reply_outbuf(req, 1, 0);
677                 SSVAL(req->outbuf, smb_vwv0, choice);
678         }
679   
680         DEBUG( 5, ( "negprot index=%d\n", choice ) );
681
682         if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
683                 exit_server_cleanly("SMB signing is required and "
684                         "client negotiated a downlevel protocol");
685         }
686
687         TALLOC_FREE(cliprotos);
688         END_PROFILE(SMBnegprot);
689         return;
690 }