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