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