s3:smbd: move all globals and static variables in globals.[ch]
[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 #include "smbd/globals.h"
23
24 extern fstring remote_proto;
25 extern enum protocol_types Protocol;
26
27 static void get_challenge(uint8 buff[8])
28 {
29         NTSTATUS nt_status;
30         const uint8 *cryptkey;
31
32         /* We might be called more than once, multiple negprots are
33          * permitted */
34         if (negprot_global_auth_context) {
35                 DEBUG(3, ("get challenge: is this a secondary negprot?  negprot_global_auth_context is non-NULL!\n"));
36                 (negprot_global_auth_context->free)(&negprot_global_auth_context);
37         }
38
39         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
40         if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
41                 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
42                 smb_panic("cannot make_negprot_global_auth_context!");
43         }
44         DEBUG(10, ("get challenge: getting challenge\n"));
45         cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
46         memcpy(buff, cryptkey, 8);
47 }
48
49 /****************************************************************************
50  Reply for the core protocol.
51 ****************************************************************************/
52
53 static void reply_corep(struct smb_request *req, uint16 choice)
54 {
55         reply_outbuf(req, 1, 0);
56         SSVAL(req->outbuf, smb_vwv0, choice);
57
58         Protocol = PROTOCOL_CORE;
59 }
60
61 /****************************************************************************
62  Reply for the coreplus protocol.
63 ****************************************************************************/
64
65 static void reply_coreplus(struct smb_request *req, uint16 choice)
66 {
67         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
68
69         reply_outbuf(req, 13, 0);
70
71         SSVAL(req->outbuf,smb_vwv0,choice);
72         SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
73                         readbraw and writebraw (possibly) */
74         /* Reply, SMBlockread, SMBwritelock supported. */
75         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
76         SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
77                                           * encrypt */
78         Protocol = PROTOCOL_COREPLUS;
79 }
80
81 /****************************************************************************
82  Reply for the lanman 1.0 protocol.
83 ****************************************************************************/
84
85 static void reply_lanman1(struct smb_request *req, uint16 choice)
86 {
87         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
88         int secword=0;
89         time_t t = time(NULL);
90
91         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
92
93         if (lp_security()>=SEC_USER)
94                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
95         if (global_encrypted_passwords_negotiated)
96                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
97
98         reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0);
99
100         SSVAL(req->outbuf,smb_vwv0,choice);
101         SSVAL(req->outbuf,smb_vwv1,secword);
102         /* Create a token value and add it to the outgoing packet. */
103         if (global_encrypted_passwords_negotiated) {
104                 get_challenge((uint8 *)smb_buf(req->outbuf));
105                 SSVAL(req->outbuf,smb_vwv11, 8);
106         }
107
108         Protocol = PROTOCOL_LANMAN1;
109
110         /* Reply, SMBlockread, SMBwritelock supported. */
111         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
112         SSVAL(req->outbuf,smb_vwv2,max_recv);
113         SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
114         SSVAL(req->outbuf,smb_vwv4,1);
115         SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
116                 readbraw writebraw (possibly) */
117         SIVAL(req->outbuf,smb_vwv6,sys_getpid());
118         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
119
120         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
121
122         return;
123 }
124
125 /****************************************************************************
126  Reply for the lanman 2.0 protocol.
127 ****************************************************************************/
128
129 static void reply_lanman2(struct smb_request *req, uint16 choice)
130 {
131         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
132         int secword=0;
133         time_t t = time(NULL);
134
135         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
136   
137         if (lp_security()>=SEC_USER)
138                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
139         if (global_encrypted_passwords_negotiated)
140                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
141
142         reply_outbuf(req, 13, global_encrypted_passwords_negotiated?8:0);
143
144         SSVAL(req->outbuf,smb_vwv0,choice);
145         SSVAL(req->outbuf,smb_vwv1,secword);
146         SIVAL(req->outbuf,smb_vwv6,sys_getpid());
147
148         /* Create a token value and add it to the outgoing packet. */
149         if (global_encrypted_passwords_negotiated) {
150                 get_challenge((uint8 *)smb_buf(req->outbuf));
151                 SSVAL(req->outbuf,smb_vwv11, 8);
152         }
153
154         Protocol = PROTOCOL_LANMAN2;
155
156         /* Reply, SMBlockread, SMBwritelock supported. */
157         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
158         SSVAL(req->outbuf,smb_vwv2,max_recv);
159         SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
160         SSVAL(req->outbuf,smb_vwv4,1);
161         SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
162         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
163         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
164 }
165
166 /****************************************************************************
167  Generate the spnego negprot reply blob. Return the number of bytes used.
168 ****************************************************************************/
169
170 static DATA_BLOB negprot_spnego(void)
171 {
172         DATA_BLOB blob;
173         nstring dos_name;
174         fstring unix_name;
175 #ifdef DEVELOPER
176         size_t slen;
177 #endif
178         char guid[17];
179         const char *OIDs_krb5[] = {OID_KERBEROS5,
180                                    OID_KERBEROS5_OLD,
181                                    OID_NTLMSSP,
182                                    NULL};
183         const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
184
185         global_spnego_negotiated = True;
186
187         memset(guid, '\0', sizeof(guid));
188
189         safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
190         strlower_m(unix_name);
191         push_ascii_nstring(dos_name, unix_name);
192         safe_strcpy(guid, dos_name, sizeof(guid)-1);
193
194 #ifdef DEVELOPER
195         /* Fix valgrind 'uninitialized bytes' issue. */
196         slen = strlen(dos_name);
197         if (slen < sizeof(guid)) {
198                 memset(guid+slen, '\0', sizeof(guid) - slen);
199         }
200 #endif
201
202         /* strangely enough, NT does not sent the single OID NTLMSSP when
203            not a ADS member, it sends no OIDs at all
204
205            OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
206                    about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
207
208            Our sessionsetup code now handles raw NTLMSSP connects, so we can go
209            back to doing what W2K3 does here. This is needed to make PocketPC 2003
210            CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
211            for details. JRA.
212
213         */
214
215         if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
216 #if 0
217                 /* Code for PocketPC client */
218                 blob = data_blob(guid, 16);
219 #else
220                 /* Code for standalone WXP client */
221                 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
222 #endif
223         } else {
224                 fstring myname;
225                 char *host_princ_s = NULL;
226                 name_to_fqdn(myname, global_myname());
227                 strlower_m(myname);
228                 if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm())
229                     == -1) {
230                         return data_blob_null;
231                 }
232                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
233                 SAFE_FREE(host_princ_s);
234         }
235
236         return blob;
237 }
238
239 /****************************************************************************
240  Reply for the nt protocol.
241 ****************************************************************************/
242
243 static void reply_nt1(struct smb_request *req, uint16 choice)
244 {
245         /* dual names + lock_and_read + nt SMBs + remote API calls */
246         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
247                 CAP_LEVEL_II_OPLOCKS;
248
249         int secword=0;
250         char *p, *q;
251         bool negotiate_spnego = False;
252         time_t t = time(NULL);
253         ssize_t ret;
254
255         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
256
257         /* Check the flags field to see if this is Vista.
258            WinXP sets it and Vista does not. But we have to 
259            distinguish from NT which doesn't set it either. */
260
261         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
262                 ((req->flags2 & FLAGS2_UNKNOWN_BIT4) == 0) )
263         {
264                 if (get_remote_arch() != RA_SAMBA) {
265                         set_remote_arch( RA_VISTA );
266                 }
267         }
268
269         reply_outbuf(req,17,0);
270
271         /* do spnego in user level security if the client
272            supports it and we can do encrypted passwords */
273         
274         if (global_encrypted_passwords_negotiated && 
275             (lp_security() != SEC_SHARE) &&
276             lp_use_spnego() &&
277             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
278                 negotiate_spnego = True;
279                 capabilities |= CAP_EXTENDED_SECURITY;
280                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
281                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
282                    (already partially constructed. */
283                 SSVAL(req->outbuf, smb_flg2,
284                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
285         }
286         
287         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
288
289         if (lp_unix_extensions()) {
290                 capabilities |= CAP_UNIX;
291         }
292         
293         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
294                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
295         
296         if (SMB_OFF_T_BITS == 64)
297                 capabilities |= CAP_LARGE_FILES;
298
299         if (lp_readraw() && lp_writeraw())
300                 capabilities |= CAP_RAW_MODE;
301         
302         if (lp_nt_status_support())
303                 capabilities |= CAP_STATUS32;
304         
305         if (lp_host_msdfs())
306                 capabilities |= CAP_DFS;
307         
308         if (lp_security() >= SEC_USER)
309                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
310         if (global_encrypted_passwords_negotiated)
311                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
312         
313         if (lp_server_signing()) {
314                 if (lp_security() >= SEC_USER) {
315                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
316                         /* No raw mode with smb signing. */
317                         capabilities &= ~CAP_RAW_MODE;
318                         if (lp_server_signing() == Required)
319                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
320                         srv_set_signing_negotiated();
321                 } else {
322                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
323                         if (lp_server_signing() == Required) {
324                                 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
325                         }
326                 }
327         }
328
329         SSVAL(req->outbuf,smb_vwv0,choice);
330         SCVAL(req->outbuf,smb_vwv1,secword);
331         
332         Protocol = PROTOCOL_NT1;
333         
334         SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
335         SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
336         SIVAL(req->outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
337         SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
338         SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
339         SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
340         put_long_date((char *)req->outbuf+smb_vwv11+1,t);
341         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
342         
343         p = q = smb_buf(req->outbuf);
344         if (!negotiate_spnego) {
345                 /* Create a token value and add it to the outgoing packet. */
346                 if (global_encrypted_passwords_negotiated) {
347                         uint8 chal[8];
348                         /* note that we do not send a challenge at all if
349                            we are using plaintext */
350                         get_challenge(chal);
351                         ret = message_push_blob(
352                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
353                         if (ret == -1) {
354                                 DEBUG(0, ("Could not push challenge\n"));
355                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
356                                 return;
357                         }
358                         SCVAL(req->outbuf, smb_vwv16+1, ret);
359                         p += ret;
360                 }
361                 ret = message_push_string(&req->outbuf, lp_workgroup(),
362                                           STR_UNICODE|STR_TERMINATE
363                                           |STR_NOALIGN);
364                 if (ret == -1) {
365                         DEBUG(0, ("Could not push challenge\n"));
366                         reply_nterror(req, NT_STATUS_NO_MEMORY);
367                         return;
368                 }
369                 DEBUG(3,("not using SPNEGO\n"));
370         } else {
371                 DATA_BLOB spnego_blob = negprot_spnego();
372
373                 if (spnego_blob.data == NULL) {
374                         reply_nterror(req, NT_STATUS_NO_MEMORY);
375                         return;
376                 }
377
378                 ret = message_push_blob(&req->outbuf, spnego_blob);
379                 if (ret == -1) {
380                         DEBUG(0, ("Could not push spnego blob\n"));
381                         reply_nterror(req, NT_STATUS_NO_MEMORY);
382                         return;
383                 }
384                 p += ret;
385                 data_blob_free(&spnego_blob);
386
387                 SCVAL(req->outbuf,smb_vwv16+1, 0);
388                 DEBUG(3,("using SPNEGO\n"));
389         }
390         
391         SSVAL(req->outbuf,smb_vwv17, p - q); /* length of challenge+domain
392                                               * strings */
393
394         return;
395 }
396
397 /* these are the protocol lists used for auto architecture detection:
398
399 WinNT 3.51:
400 protocol [PC NETWORK PROGRAM 1.0]
401 protocol [XENIX CORE]
402 protocol [MICROSOFT NETWORKS 1.03]
403 protocol [LANMAN1.0]
404 protocol [Windows for Workgroups 3.1a]
405 protocol [LM1.2X002]
406 protocol [LANMAN2.1]
407 protocol [NT LM 0.12]
408
409 Win95:
410 protocol [PC NETWORK PROGRAM 1.0]
411 protocol [XENIX CORE]
412 protocol [MICROSOFT NETWORKS 1.03]
413 protocol [LANMAN1.0]
414 protocol [Windows for Workgroups 3.1a]
415 protocol [LM1.2X002]
416 protocol [LANMAN2.1]
417 protocol [NT LM 0.12]
418
419 Win2K:
420 protocol [PC NETWORK PROGRAM 1.0]
421 protocol [LANMAN1.0]
422 protocol [Windows for Workgroups 3.1a]
423 protocol [LM1.2X002]
424 protocol [LANMAN2.1]
425 protocol [NT LM 0.12]
426
427 Vista:
428 protocol [PC NETWORK PROGRAM 1.0]
429 protocol [LANMAN1.0]
430 protocol [Windows for Workgroups 3.1a]
431 protocol [LM1.2X002]
432 protocol [LANMAN2.1]
433 protocol [NT LM 0.12]
434 protocol [SMB 2.001]
435
436 OS/2:
437 protocol [PC NETWORK PROGRAM 1.0]
438 protocol [XENIX CORE]
439 protocol [LANMAN1.0]
440 protocol [LM1.2X002]
441 protocol [LANMAN2.1]
442 */
443
444 /*
445   * Modified to recognize the architecture of the remote machine better.
446   *
447   * This appears to be the matrix of which protocol is used by which
448   * MS product.
449        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
450        PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
451        XENIX CORE                                      2             2
452        MICROSOFT NETWORKS 3.0          2       2       
453        DOS LM1.2X002                   3       3       
454        MICROSOFT NETWORKS 1.03                         3
455        DOS LANMAN2.1                   4       4       
456        LANMAN1.0                                       4      2      3     2
457        Windows for Workgroups 3.1a     5       5       5      3            3
458        LM1.2X002                                       6      4      4     4
459        LANMAN2.1                                       7      5      5     5
460        NT LM 0.12                              6       8      6            6
461        SMB 2.001                                                           7
462   *
463   *  tim@fsg.com 09/29/95
464   *  Win2K added by matty 17/7/99
465   */
466   
467 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
468 #define ARCH_WIN95    0x2
469 #define ARCH_WINNT    0x4
470 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
471 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
472 #define ARCH_SAMBA    0x20
473 #define ARCH_CIFSFS   0x40
474 #define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
475  
476 #define ARCH_ALL      0x7F
477  
478 /* List of supported protocols, most desired first */
479 static const struct {
480         const char *proto_name;
481         const char *short_name;
482         void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
483         int protocol_level;
484 } supported_protocols[] = {
485         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
486         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
487         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
488         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
489         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
490         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
491         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
492         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
493         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
494         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
495         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
496         {NULL,NULL,NULL,0},
497 };
498
499 /****************************************************************************
500  Reply to a negprot.
501  conn POINTER CAN BE NULL HERE !
502 ****************************************************************************/
503
504 void reply_negprot(struct smb_request *req)
505 {
506         int choice= -1;
507         int protocol;
508         const char *p;
509         int arch = ARCH_ALL;
510         int num_cliprotos;
511         char **cliprotos;
512         int i;
513         size_t converted_size;
514
515         START_PROFILE(SMBnegprot);
516
517         if (done_negprot) {
518                 END_PROFILE(SMBnegprot);
519                 exit_server_cleanly("multiple negprot's are not permitted");
520         }
521         done_negprot = True;
522
523         if (req->buflen == 0) {
524                 DEBUG(0, ("negprot got no protocols\n"));
525                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
526                 END_PROFILE(SMBnegprot);
527                 return;
528         }
529
530         if (req->buf[req->buflen-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 (smbreq_bufrem(req, 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 }