r24308: this needs a better fix that compiles...
[kai/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                 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
233                 if (host_princ_s == NULL) {
234                         blob = data_blob_null;
235                         return blob;
236                 }
237                 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
238                 SAFE_FREE(host_princ_s);
239         }
240
241         return blob;
242 }
243
244 /****************************************************************************
245  Reply for the nt protocol.
246 ****************************************************************************/
247
248 static void reply_nt1(struct smb_request *req, uint16 choice)
249 {
250         /* dual names + lock_and_read + nt SMBs + remote API calls */
251         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
252                 CAP_LEVEL_II_OPLOCKS;
253
254         int secword=0;
255         char *p, *q;
256         BOOL negotiate_spnego = False;
257         time_t t = time(NULL);
258         ssize_t ret;
259
260         global_encrypted_passwords_negotiated = lp_encrypted_passwords();
261
262         /* Check the flags field to see if this is Vista.
263            WinXP sets it and Vista does not. But we have to 
264            distinguish from NT which doesn't set it either. */
265
266         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
267                 ((req->flags2 & FLAGS2_UNKNOWN_BIT4) == 0) )
268         {
269                 if (get_remote_arch() != RA_SAMBA) {
270                         set_remote_arch( RA_VISTA );
271                 }
272         }
273
274         reply_outbuf(req,17,0);
275
276         /* do spnego in user level security if the client
277            supports it and we can do encrypted passwords */
278         
279         if (global_encrypted_passwords_negotiated && 
280             (lp_security() != SEC_SHARE) &&
281             lp_use_spnego() &&
282             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
283                 negotiate_spnego = True;
284                 capabilities |= CAP_EXTENDED_SECURITY;
285                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
286                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
287                    (already partially constructed. */
288                 SSVAL(req->outbuf, smb_flg2,
289                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
290         }
291         
292         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
293
294         if (lp_unix_extensions()) {
295                 capabilities |= CAP_UNIX;
296         }
297         
298         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
299                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
300         
301         if (SMB_OFF_T_BITS == 64)
302                 capabilities |= CAP_LARGE_FILES;
303
304         if (lp_readraw() && lp_writeraw())
305                 capabilities |= CAP_RAW_MODE;
306         
307         if (lp_nt_status_support())
308                 capabilities |= CAP_STATUS32;
309         
310         if (lp_host_msdfs())
311                 capabilities |= CAP_DFS;
312         
313         if (lp_security() >= SEC_USER)
314                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
315         if (global_encrypted_passwords_negotiated)
316                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
317         
318         if (lp_server_signing()) {
319                 if (lp_security() >= SEC_USER) {
320                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
321                         /* No raw mode with smb signing. */
322                         capabilities &= ~CAP_RAW_MODE;
323                         if (lp_server_signing() == Required)
324                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
325                         srv_set_signing_negotiated();
326                 } else {
327                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
328                         if (lp_server_signing() == Required) {
329                                 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
330                         }
331                 }
332         }
333
334         SSVAL(req->outbuf,smb_vwv0,choice);
335         SCVAL(req->outbuf,smb_vwv1,secword);
336         
337         Protocol = PROTOCOL_NT1;
338         
339         SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
340         SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
341         SIVAL(req->outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
342         SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
343         SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
344         SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
345         put_long_date((char *)req->outbuf+smb_vwv11+1,t);
346         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
347         
348         p = q = smb_buf(req->outbuf);
349         if (!negotiate_spnego) {
350                 /* Create a token value and add it to the outgoing packet. */
351                 if (global_encrypted_passwords_negotiated) {
352                         uint8 chal[8];
353                         /* note that we do not send a challenge at all if
354                            we are using plaintext */
355                         get_challenge(chal);
356                         ret = message_push_blob(
357                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
358                         if (ret == -1) {
359                                 DEBUG(0, ("Could not push challenge\n"));
360                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
361                                 return;
362                         }
363                         SCVAL(req->outbuf, smb_vwv16+1, ret);
364                         p += ret;
365                 }
366                 ret = message_push_string(&req->outbuf, lp_workgroup(),
367                                           STR_UNICODE|STR_TERMINATE
368                                           |STR_NOALIGN);
369                 if (ret == -1) {
370                         DEBUG(0, ("Could not push challenge\n"));
371                         reply_nterror(req, NT_STATUS_NO_MEMORY);
372                         return;
373                 }
374                 DEBUG(3,("not using SPNEGO\n"));
375         } else {
376                 DATA_BLOB spnego_blob = negprot_spnego();
377
378                 if (spnego_blob.data == NULL) {
379                         reply_nterror(req, NT_STATUS_NO_MEMORY);
380                         return;
381                 }
382
383                 ret = message_push_blob(&req->outbuf, spnego_blob);
384                 if (ret == -1) {
385                         DEBUG(0, ("Could not push spnego blob\n"));
386                         reply_nterror(req, NT_STATUS_NO_MEMORY);
387                         return;
388                 }
389                 p += ret;
390                 data_blob_free(&spnego_blob);
391
392                 SCVAL(req->outbuf,smb_vwv16+1, 0);
393                 DEBUG(3,("using SPNEGO\n"));
394         }
395         
396         SSVAL(req->outbuf,smb_vwv17, p - q); /* length of challenge+domain
397                                               * strings */
398
399         return;
400 }
401
402 /* these are the protocol lists used for auto architecture detection:
403
404 WinNT 3.51:
405 protocol [PC NETWORK PROGRAM 1.0]
406 protocol [XENIX CORE]
407 protocol [MICROSOFT NETWORKS 1.03]
408 protocol [LANMAN1.0]
409 protocol [Windows for Workgroups 3.1a]
410 protocol [LM1.2X002]
411 protocol [LANMAN2.1]
412 protocol [NT LM 0.12]
413
414 Win95:
415 protocol [PC NETWORK PROGRAM 1.0]
416 protocol [XENIX CORE]
417 protocol [MICROSOFT NETWORKS 1.03]
418 protocol [LANMAN1.0]
419 protocol [Windows for Workgroups 3.1a]
420 protocol [LM1.2X002]
421 protocol [LANMAN2.1]
422 protocol [NT LM 0.12]
423
424 Win2K:
425 protocol [PC NETWORK PROGRAM 1.0]
426 protocol [LANMAN1.0]
427 protocol [Windows for Workgroups 3.1a]
428 protocol [LM1.2X002]
429 protocol [LANMAN2.1]
430 protocol [NT LM 0.12]
431
432 Vista:
433 protocol [PC NETWORK PROGRAM 1.0]
434 protocol [LANMAN1.0]
435 protocol [Windows for Workgroups 3.1a]
436 protocol [LM1.2X002]
437 protocol [LANMAN2.1]
438 protocol [NT LM 0.12]
439 protocol [SMB 2.001]
440
441 OS/2:
442 protocol [PC NETWORK PROGRAM 1.0]
443 protocol [XENIX CORE]
444 protocol [LANMAN1.0]
445 protocol [LM1.2X002]
446 protocol [LANMAN2.1]
447 */
448
449 /*
450   * Modified to recognize the architecture of the remote machine better.
451   *
452   * This appears to be the matrix of which protocol is used by which
453   * MS product.
454        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
455        PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
456        XENIX CORE                                      2             2
457        MICROSOFT NETWORKS 3.0          2       2       
458        DOS LM1.2X002                   3       3       
459        MICROSOFT NETWORKS 1.03                         3
460        DOS LANMAN2.1                   4       4       
461        LANMAN1.0                                       4      2      3     2
462        Windows for Workgroups 3.1a     5       5       5      3            3
463        LM1.2X002                                       6      4      4     4
464        LANMAN2.1                                       7      5      5     5
465        NT LM 0.12                              6       8      6            6
466        SMB 2.001                                                           7
467   *
468   *  tim@fsg.com 09/29/95
469   *  Win2K added by matty 17/7/99
470   */
471   
472 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
473 #define ARCH_WIN95    0x2
474 #define ARCH_WINNT    0x4
475 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
476 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
477 #define ARCH_SAMBA    0x20
478 #define ARCH_CIFSFS   0x40
479 #define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
480  
481 #define ARCH_ALL      0x7F
482  
483 /* List of supported protocols, most desired first */
484 static const struct {
485         const char *proto_name;
486         const char *short_name;
487         void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
488         int protocol_level;
489 } supported_protocols[] = {
490         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
491         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
492         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
493         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
494         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
495         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
496         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
497         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
498         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
499         {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
500         {"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE}, 
501         {NULL,NULL,NULL,0},
502 };
503
504 /****************************************************************************
505  Reply to a negprot.
506  conn POINTER CAN BE NULL HERE !
507 ****************************************************************************/
508
509 void reply_negprot(connection_struct *conn, struct smb_request *req)
510 {
511         size_t size = smb_len(req->inbuf) + 4;
512         int choice= -1;
513         int protocol;
514         char *p;
515         int bcc = SVAL(smb_buf(req->inbuf),-2);
516         int arch = ARCH_ALL;
517         int num_cliprotos;
518         char **cliprotos;
519         int i;
520
521         static BOOL done_negprot = False;
522
523         START_PROFILE(SMBnegprot);
524
525         if (done_negprot) {
526                 END_PROFILE(SMBnegprot);
527                 exit_server_cleanly("multiple negprot's are not permitted");
528         }
529         done_negprot = True;
530
531         if (req->inbuf[size-1] != '\0') {
532                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
533                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
534                 END_PROFILE(SMBnegprot);
535                 return;
536         }
537
538         p = smb_buf(req->inbuf) + 1;
539
540         num_cliprotos = 0;
541         cliprotos = NULL;
542
543         while (p < (smb_buf(req->inbuf) + bcc)) { 
544
545                 char **tmp;
546
547                 tmp = TALLOC_REALLOC_ARRAY(tmp_talloc_ctx(), cliprotos, char *,
548                                            num_cliprotos+1);
549                 if (tmp == NULL) {
550                         DEBUG(0, ("talloc failed\n"));
551                         TALLOC_FREE(cliprotos);
552                         reply_nterror(req, NT_STATUS_NO_MEMORY);
553                         END_PROFILE(SMBnegprot);
554                         return;
555                 }
556
557                 cliprotos = tmp;
558
559                 if (pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p)
560                     == (size_t)-1) {
561                         DEBUG(0, ("pull_ascii_talloc failed\n"));
562                         TALLOC_FREE(cliprotos);
563                         reply_nterror(req, NT_STATUS_NO_MEMORY);
564                         END_PROFILE(SMBnegprot);
565                         return;
566                 }
567
568                 DEBUG(3, ("Requested protocol [%s]\n",
569                           cliprotos[num_cliprotos]));
570
571                 num_cliprotos += 1;
572                 p += strlen(p) + 2;
573         }
574
575         for (i=0; i<num_cliprotos; i++) {
576                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
577                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
578                                   | ARCH_WIN2K );
579                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
580                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
581                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
582                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
583                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
584                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
585                                   | ARCH_CIFSFS);
586                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
587                         arch = ARCH_VISTA;              
588                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
589                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
590                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
591                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
592                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
593                         arch &= ARCH_WINNT;
594                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
595                         arch &= ( ARCH_WINNT | ARCH_OS2 );
596                 else if (strcsequal(cliprotos[i], "Samba")) {
597                         arch = ARCH_SAMBA;
598                         break;
599                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
600                         arch = ARCH_CIFSFS;
601                         break;
602                 }
603         }
604
605         /* CIFSFS can send one arch only, NT LM 0.12. */
606         if (i == 1 && (arch & ARCH_CIFSFS)) {
607                 arch = ARCH_CIFSFS;
608         }
609
610         switch ( arch ) {
611                 case ARCH_CIFSFS:
612                         set_remote_arch(RA_CIFSFS);
613                         break;
614                 case ARCH_SAMBA:
615                         set_remote_arch(RA_SAMBA);
616                         break;
617                 case ARCH_WFWG:
618                         set_remote_arch(RA_WFWG);
619                         break;
620                 case ARCH_WIN95:
621                         set_remote_arch(RA_WIN95);
622                         break;
623                 case ARCH_WINNT:
624                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
625                                 set_remote_arch(RA_WIN2K);
626                         else
627                                 set_remote_arch(RA_WINNT);
628                         break;
629                 case ARCH_WIN2K:
630                         /* Vista may have been set in the negprot so don't 
631                            override it here */
632                         if ( get_remote_arch() != RA_VISTA )
633                                 set_remote_arch(RA_WIN2K);
634                         break;
635                 case ARCH_VISTA:
636                         set_remote_arch(RA_VISTA);
637                         break;
638                 case ARCH_OS2:
639                         set_remote_arch(RA_OS2);
640                         break;
641                 default:
642                         set_remote_arch(RA_UNKNOWN);
643                 break;
644         }
645  
646         /* possibly reload - change of architecture */
647         reload_services(True);      
648         
649         /* moved from the netbios session setup code since we don't have that 
650            when the client connects to port 445.  Of course there is a small
651            window where we are listening to messages   -- jerry */
652
653         claim_connection(
654                 NULL,"",FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
655     
656         /* Check for protocols, most desirable first */
657         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
658                 i = 0;
659                 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
660                                 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
661                         while (i < num_cliprotos) {
662                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
663                                         choice = i;
664                                 i++;
665                         }
666                 if(choice != -1)
667                         break;
668         }
669   
670         if(choice != -1) {
671                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
672                 reload_services(True);          
673                 supported_protocols[protocol].proto_reply_fn(req, choice);
674                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
675         } else {
676                 DEBUG(0,("No protocol supported !\n"));
677         }
678   
679         DEBUG( 5, ( "negprot index=%d\n", choice ) );
680
681         if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
682                 exit_server_cleanly("SMB signing is required and "
683                         "client negotiated a downlevel protocol");
684         }
685
686         TALLOC_FREE(cliprotos);
687         END_PROFILE(SMBnegprot);
688         return;
689 }