s3:smbd: release the share mode lock before calling exit_server() (bug #9191)
[kai/samba-autobuild/.git] / source3 / smbd / negprot.c
1 /* 
2    Unix SMB/CIFS implementation.
3    negprot reply code
4    Copyright (C) Andrew Tridgell 1992-1998
5    Copyright (C) Volker Lendecke 2007
6
7    This program is free software; you can redistribute it and/or modify
8    it under the terms of the GNU General Public License as published by
9    the Free Software Foundation; either version 3 of the License, or
10    (at your option) any later version.
11
12    This program is distributed in the hope that it will be useful,
13    but WITHOUT ANY WARRANTY; without even the implied warranty of
14    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
15    GNU General Public License for more details.
16
17    You should have received a copy of the GNU General Public License
18    along with this program.  If not, see <http://www.gnu.org/licenses/>.
19 */
20
21 #include "includes.h"
22 #include "smbd/smbd.h"
23 #include "smbd/globals.h"
24 #include "../libcli/auth/spnego.h"
25 #include "serverid.h"
26 #include "auth.h"
27 #include "messages.h"
28 #include "smbprofile.h"
29 #include "auth/gensec/gensec.h"
30 #include "../libcli/smb/smb_signing.h"
31
32 extern fstring remote_proto;
33
34 static void get_challenge(struct smbd_server_connection *sconn, uint8 buff[8])
35 {
36         NTSTATUS nt_status;
37
38         /* We might be called more than once, multiple negprots are
39          * permitted */
40         if (sconn->smb1.negprot.auth_context) {
41                 DEBUG(3, ("get challenge: is this a secondary negprot? "
42                           "sconn->negprot.auth_context is non-NULL!\n"));
43                         TALLOC_FREE(sconn->smb1.negprot.auth_context);
44         }
45
46         DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
47         nt_status = make_auth4_context(
48                 sconn, &sconn->smb1.negprot.auth_context);
49         if (!NT_STATUS_IS_OK(nt_status)) {
50                 DEBUG(0, ("make_auth_context_subsystem returned %s",
51                           nt_errstr(nt_status)));
52                 smb_panic("cannot make_negprot_global_auth_context!");
53         }
54         DEBUG(10, ("get challenge: getting challenge\n"));
55         sconn->smb1.negprot.auth_context->get_ntlm_challenge(
56                 sconn->smb1.negprot.auth_context, buff);
57 }
58
59 /****************************************************************************
60  Reply for the lanman 1.0 protocol.
61 ****************************************************************************/
62
63 static void reply_lanman1(struct smb_request *req, uint16 choice)
64 {
65         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
66         int secword=0;
67         time_t t = time(NULL);
68         struct smbd_server_connection *sconn = req->sconn;
69
70         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
71
72         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
73         if (sconn->smb1.negprot.encrypted_passwords) {
74                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
75         }
76
77         reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
78
79         SSVAL(req->outbuf,smb_vwv0,choice);
80         SSVAL(req->outbuf,smb_vwv1,secword);
81         /* Create a token value and add it to the outgoing packet. */
82         if (sconn->smb1.negprot.encrypted_passwords) {
83                 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
84                 SSVAL(req->outbuf,smb_vwv11, 8);
85         }
86
87         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN1);
88
89         /* Reply, SMBlockread, SMBwritelock supported. */
90         SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
91         SSVAL(req->outbuf,smb_vwv2, sconn->smb1.negprot.max_recv);
92         SSVAL(req->outbuf,smb_vwv3, lp_maxmux()); /* maxmux */
93         SSVAL(req->outbuf,smb_vwv4, 1);
94         SSVAL(req->outbuf,smb_vwv5, raw); /* tell redirector we support
95                 readbraw writebraw (possibly) */
96         SIVAL(req->outbuf,smb_vwv6, getpid());
97         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
98
99         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
100
101         return;
102 }
103
104 /****************************************************************************
105  Reply for the lanman 2.0 protocol.
106 ****************************************************************************/
107
108 static void reply_lanman2(struct smb_request *req, uint16 choice)
109 {
110         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
111         int secword=0;
112         time_t t = time(NULL);
113         struct smbd_server_connection *sconn = req->sconn;
114
115         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
116
117         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
118         if (sconn->smb1.negprot.encrypted_passwords) {
119                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
120         }
121
122         reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
123
124         SSVAL(req->outbuf,smb_vwv0, choice);
125         SSVAL(req->outbuf,smb_vwv1, secword);
126         SIVAL(req->outbuf,smb_vwv6, getpid());
127
128         /* Create a token value and add it to the outgoing packet. */
129         if (sconn->smb1.negprot.encrypted_passwords) {
130                 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
131                 SSVAL(req->outbuf,smb_vwv11, 8);
132         }
133
134         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN2);
135
136         /* Reply, SMBlockread, SMBwritelock supported. */
137         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
138         SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
139         SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
140         SSVAL(req->outbuf,smb_vwv4,1);
141         SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
142         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
143         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
144 }
145
146 /****************************************************************************
147  Generate the spnego negprot reply blob. Return the number of bytes used.
148 ****************************************************************************/
149
150 DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
151 {
152         DATA_BLOB blob = data_blob_null;
153         DATA_BLOB blob_out = data_blob_null;
154         nstring dos_name;
155         fstring unix_name;
156         NTSTATUS status;
157 #ifdef DEVELOPER
158         size_t slen;
159 #endif
160         struct gensec_security *gensec_security;
161
162         /* See if we can get an SPNEGO blob */
163         status = auth_generic_prepare(talloc_tos(),
164                                       sconn->remote_address,
165                                       &gensec_security);
166         if (NT_STATUS_IS_OK(status)) {
167                 status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
168                 if (NT_STATUS_IS_OK(status)) {
169                         status = gensec_update(gensec_security, ctx,
170                                                NULL, data_blob_null, &blob);
171                         /* If we get the list of OIDs, the 'OK' answer
172                          * is NT_STATUS_MORE_PROCESSING_REQUIRED */
173                         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
174                                 DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n"));
175                                 blob = data_blob_null;
176                         }
177                 }
178                 TALLOC_FREE(gensec_security);
179         }
180
181         sconn->smb1.negprot.spnego = true;
182
183         /* strangely enough, NT does not sent the single OID NTLMSSP when
184            not a ADS member, it sends no OIDs at all
185
186            OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
187                    about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
188
189            Our sessionsetup code now handles raw NTLMSSP connects, so we can go
190            back to doing what W2K3 does here. This is needed to make PocketPC 2003
191            CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
192            for details. JRA.
193
194         */
195
196         if (blob.length == 0 || blob.data == NULL) {
197                 return data_blob_null;
198         }
199
200         blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
201         if (blob_out.data == NULL) {
202                 data_blob_free(&blob);
203                 return data_blob_null;
204         }
205
206         memset(blob_out.data, '\0', 16);
207
208         checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
209         (void)strlower_m(unix_name);
210         push_ascii_nstring(dos_name, unix_name);
211         strlcpy((char *)blob_out.data, dos_name, 17);
212
213 #ifdef DEVELOPER
214         /* Fix valgrind 'uninitialized bytes' issue. */
215         slen = strlen(dos_name);
216         if (slen < 16) {
217                 memset(blob_out.data+slen, '\0', 16 - slen);
218         }
219 #endif
220
221         memcpy(&blob_out.data[16], blob.data, blob.length);
222
223         data_blob_free(&blob);
224
225         return blob_out;
226 }
227
228 /****************************************************************************
229  Reply for the nt protocol.
230 ****************************************************************************/
231
232 static void reply_nt1(struct smb_request *req, uint16 choice)
233 {
234         /* dual names + lock_and_read + nt SMBs + remote API calls */
235         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
236                 CAP_LEVEL_II_OPLOCKS;
237
238         int secword=0;
239         bool negotiate_spnego = False;
240         struct timespec ts;
241         ssize_t ret;
242         struct smbd_server_connection *sconn = req->sconn;
243         bool signing_enabled = false;
244         bool signing_required = false;
245
246         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
247
248         /* Check the flags field to see if this is Vista.
249            WinXP sets it and Vista does not. But we have to 
250            distinguish from NT which doesn't set it either. */
251
252         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
253                 ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
254         {
255                 if (get_remote_arch() != RA_SAMBA) {
256                         set_remote_arch( RA_VISTA );
257                 }
258         }
259
260         reply_outbuf(req,17,0);
261
262         /* do spnego in user level security if the client
263            supports it and we can do encrypted passwords */
264
265         if (sconn->smb1.negprot.encrypted_passwords &&
266             lp_use_spnego() &&
267             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
268                 negotiate_spnego = True;
269                 capabilities |= CAP_EXTENDED_SECURITY;
270                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
271                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
272                    (already partially constructed. */
273                 SSVAL(req->outbuf, smb_flg2,
274                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
275         }
276
277         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
278
279         if (lp_unicode()) {
280                 capabilities |= CAP_UNICODE;
281         }
282
283         if (lp_unix_extensions()) {
284                 capabilities |= CAP_UNIX;
285         }
286
287         if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
288                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
289
290         if (SMB_OFF_T_BITS == 64)
291                 capabilities |= CAP_LARGE_FILES;
292
293         if (lp_readraw() && lp_writeraw())
294                 capabilities |= CAP_RAW_MODE;
295
296         if (lp_nt_status_support())
297                 capabilities |= CAP_STATUS32;
298
299         if (lp_host_msdfs())
300                 capabilities |= CAP_DFS;
301
302         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
303         if (sconn->smb1.negprot.encrypted_passwords) {
304                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
305         }
306
307         signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state);
308         signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
309
310         if (signing_enabled) {
311                 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
312                 /* No raw mode with smb signing. */
313                 capabilities &= ~CAP_RAW_MODE;
314                 if (signing_required) {
315                         secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
316                 }
317         }
318
319         SSVAL(req->outbuf,smb_vwv0,choice);
320         SCVAL(req->outbuf,smb_vwv1,secword);
321
322         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1);
323
324         SSVAL(req->outbuf,smb_vwv1+1, lp_maxmux()); /* maxmpx */
325         SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
326         SIVAL(req->outbuf,smb_vwv3+1,
327               sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
328         SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */
329         SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */
330         SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */
331         clock_gettime(CLOCK_REALTIME,&ts);
332         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
333         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
334
335         if (!negotiate_spnego) {
336                 /* Create a token value and add it to the outgoing packet. */
337                 if (sconn->smb1.negprot.encrypted_passwords) {
338                         uint8 chal[8];
339                         /* note that we do not send a challenge at all if
340                            we are using plaintext */
341                         get_challenge(sconn, chal);
342                         ret = message_push_blob(
343                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
344                         if (ret == -1) {
345                                 DEBUG(0, ("Could not push challenge\n"));
346                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
347                                 return;
348                         }
349                         SCVAL(req->outbuf, smb_vwv16+1, ret);
350                 }
351                 ret = message_push_string(&req->outbuf, lp_workgroup(),
352                                           STR_UNICODE|STR_TERMINATE
353                                           |STR_NOALIGN);
354                 if (ret == -1) {
355                         DEBUG(0, ("Could not push workgroup string\n"));
356                         reply_nterror(req, NT_STATUS_NO_MEMORY);
357                         return;
358                 }
359                 ret = message_push_string(&req->outbuf, lp_netbios_name(),
360                                           STR_UNICODE|STR_TERMINATE
361                                           |STR_NOALIGN);
362                 if (ret == -1) {
363                         DEBUG(0, ("Could not push netbios name string\n"));
364                         reply_nterror(req, NT_STATUS_NO_MEMORY);
365                         return;
366                 }
367                 DEBUG(3,("not using SPNEGO\n"));
368         } else {
369                 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
370
371                 if (spnego_blob.data == NULL) {
372                         reply_nterror(req, NT_STATUS_NO_MEMORY);
373                         return;
374                 }
375
376                 ret = message_push_blob(&req->outbuf, spnego_blob);
377                 if (ret == -1) {
378                         DEBUG(0, ("Could not push spnego blob\n"));
379                         reply_nterror(req, NT_STATUS_NO_MEMORY);
380                         return;
381                 }
382                 data_blob_free(&spnego_blob);
383
384                 SCVAL(req->outbuf,smb_vwv16+1, 0);
385                 DEBUG(3,("using SPNEGO\n"));
386         }
387
388         return;
389 }
390
391 /* these are the protocol lists used for auto architecture detection:
392
393 WinNT 3.51:
394 protocol [PC NETWORK PROGRAM 1.0]
395 protocol [XENIX CORE]
396 protocol [MICROSOFT NETWORKS 1.03]
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 Win95:
404 protocol [PC NETWORK PROGRAM 1.0]
405 protocol [XENIX CORE]
406 protocol [MICROSOFT NETWORKS 1.03]
407 protocol [LANMAN1.0]
408 protocol [Windows for Workgroups 3.1a]
409 protocol [LM1.2X002]
410 protocol [LANMAN2.1]
411 protocol [NT LM 0.12]
412
413 Win2K:
414 protocol [PC NETWORK PROGRAM 1.0]
415 protocol [LANMAN1.0]
416 protocol [Windows for Workgroups 3.1a]
417 protocol [LM1.2X002]
418 protocol [LANMAN2.1]
419 protocol [NT LM 0.12]
420
421 Vista:
422 protocol [PC NETWORK PROGRAM 1.0]
423 protocol [LANMAN1.0]
424 protocol [Windows for Workgroups 3.1a]
425 protocol [LM1.2X002]
426 protocol [LANMAN2.1]
427 protocol [NT LM 0.12]
428 protocol [SMB 2.001]
429
430 OS/2:
431 protocol [PC NETWORK PROGRAM 1.0]
432 protocol [XENIX CORE]
433 protocol [LANMAN1.0]
434 protocol [LM1.2X002]
435 protocol [LANMAN2.1]
436 */
437
438 /*
439   * Modified to recognize the architecture of the remote machine better.
440   *
441   * This appears to be the matrix of which protocol is used by which
442   * MS product.
443        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
444        PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
445        XENIX CORE                                      2             2
446        MICROSOFT NETWORKS 3.0          2       2       
447        DOS LM1.2X002                   3       3       
448        MICROSOFT NETWORKS 1.03                         3
449        DOS LANMAN2.1                   4       4       
450        LANMAN1.0                                       4      2      3     2
451        Windows for Workgroups 3.1a     5       5       5      3            3
452        LM1.2X002                                       6      4      4     4
453        LANMAN2.1                                       7      5      5     5
454        NT LM 0.12                              6       8      6            6
455        SMB 2.001                                                           7
456   *
457   *  tim@fsg.com 09/29/95
458   *  Win2K added by matty 17/7/99
459   */
460
461 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
462 #define ARCH_WIN95    0x2
463 #define ARCH_WINNT    0x4
464 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
465 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
466 #define ARCH_SAMBA    0x20
467 #define ARCH_CIFSFS   0x40
468 #define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
469
470 #define ARCH_ALL      0x7F
471
472 /* List of supported protocols, most desired first */
473 static const struct {
474         const char *proto_name;
475         const char *short_name;
476         void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
477         int protocol_level;
478 } supported_protocols[] = {
479         {"SMB 2.???",               "SMB2_FF",  reply_smb20ff,  PROTOCOL_SMB2_10},
480         {"SMB 2.002",               "SMB2_02",  reply_smb2002,  PROTOCOL_SMB2_02},
481         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
482         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
483         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
484         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
485         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
486         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
487         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
488         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
489         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
490         {NULL,NULL,NULL,0},
491 };
492
493 /****************************************************************************
494  Reply to a negprot.
495  conn POINTER CAN BE NULL HERE !
496 ****************************************************************************/
497
498 void reply_negprot(struct smb_request *req)
499 {
500         int choice= -1;
501         int protocol;
502         const char *p;
503         int arch = ARCH_ALL;
504         int num_cliprotos;
505         char **cliprotos;
506         int i;
507         size_t converted_size;
508         struct smbd_server_connection *sconn = req->sconn;
509
510         START_PROFILE(SMBnegprot);
511
512         if (sconn->smb1.negprot.done) {
513                 END_PROFILE(SMBnegprot);
514                 exit_server_cleanly("multiple negprot's are not permitted");
515         }
516         sconn->smb1.negprot.done = true;
517
518         if (req->buflen == 0) {
519                 DEBUG(0, ("negprot got no protocols\n"));
520                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
521                 END_PROFILE(SMBnegprot);
522                 return;
523         }
524
525         if (req->buf[req->buflen-1] != '\0') {
526                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
527                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
528                 END_PROFILE(SMBnegprot);
529                 return;
530         }
531
532         p = (const char *)req->buf + 1;
533
534         num_cliprotos = 0;
535         cliprotos = NULL;
536
537         while (smbreq_bufrem(req, p) > 0) {
538
539                 char **tmp;
540
541                 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
542                                            num_cliprotos+1);
543                 if (tmp == NULL) {
544                         DEBUG(0, ("talloc failed\n"));
545                         TALLOC_FREE(cliprotos);
546                         reply_nterror(req, NT_STATUS_NO_MEMORY);
547                         END_PROFILE(SMBnegprot);
548                         return;
549                 }
550
551                 cliprotos = tmp;
552
553                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
554                                        &converted_size)) {
555                         DEBUG(0, ("pull_ascii_talloc failed\n"));
556                         TALLOC_FREE(cliprotos);
557                         reply_nterror(req, NT_STATUS_NO_MEMORY);
558                         END_PROFILE(SMBnegprot);
559                         return;
560                 }
561
562                 DEBUG(3, ("Requested protocol [%s]\n",
563                           cliprotos[num_cliprotos]));
564
565                 num_cliprotos += 1;
566                 p += strlen(p) + 2;
567         }
568
569         for (i=0; i<num_cliprotos; i++) {
570                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
571                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
572                                   | ARCH_WIN2K );
573                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
574                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
575                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
576                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
577                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
578                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
579                                   | ARCH_CIFSFS);
580                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
581                         arch = ARCH_VISTA;              
582                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
583                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
584                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
585                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
586                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
587                         arch &= ARCH_WINNT;
588                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
589                         arch &= ( ARCH_WINNT | ARCH_OS2 );
590                 else if (strcsequal(cliprotos[i], "Samba")) {
591                         arch = ARCH_SAMBA;
592                         break;
593                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
594                         arch = ARCH_CIFSFS;
595                         break;
596                 }
597         }
598
599         /* CIFSFS can send one arch only, NT LM 0.12. */
600         if (i == 1 && (arch & ARCH_CIFSFS)) {
601                 arch = ARCH_CIFSFS;
602         }
603
604         switch ( arch ) {
605                 case ARCH_CIFSFS:
606                         set_remote_arch(RA_CIFSFS);
607                         break;
608                 case ARCH_SAMBA:
609                         set_remote_arch(RA_SAMBA);
610                         break;
611                 case ARCH_WFWG:
612                         set_remote_arch(RA_WFWG);
613                         break;
614                 case ARCH_WIN95:
615                         set_remote_arch(RA_WIN95);
616                         break;
617                 case ARCH_WINNT:
618                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
619                                 set_remote_arch(RA_WIN2K);
620                         else
621                                 set_remote_arch(RA_WINNT);
622                         break;
623                 case ARCH_WIN2K:
624                         /* Vista may have been set in the negprot so don't 
625                            override it here */
626                         if ( get_remote_arch() != RA_VISTA )
627                                 set_remote_arch(RA_WIN2K);
628                         break;
629                 case ARCH_VISTA:
630                         set_remote_arch(RA_VISTA);
631                         break;
632                 case ARCH_OS2:
633                         set_remote_arch(RA_OS2);
634                         break;
635                 default:
636                         set_remote_arch(RA_UNKNOWN);
637                 break;
638         }
639
640         /* possibly reload - change of architecture */
641         reload_services(sconn, conn_snum_used, true);
642
643         /* moved from the netbios session setup code since we don't have that 
644            when the client connects to port 445.  Of course there is a small
645            window where we are listening to messages   -- jerry */
646
647         serverid_register(messaging_server_id(sconn->msg_ctx),
648                           FLAG_MSG_GENERAL|FLAG_MSG_SMBD
649                           |FLAG_MSG_PRINT_GENERAL);
650
651         /* Check for protocols, most desirable first */
652         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
653                 i = 0;
654                 if ((supported_protocols[protocol].protocol_level <= lp_srv_maxprotocol()) &&
655                                 (supported_protocols[protocol].protocol_level >= lp_srv_minprotocol()))
656                         while (i < num_cliprotos) {
657                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
658                                         choice = i;
659                                 i++;
660                         }
661                 if(choice != -1)
662                         break;
663         }
664
665         if(choice != -1) {
666                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
667                 reload_services(sconn, conn_snum_used, true);
668                 supported_protocols[protocol].proto_reply_fn(req, choice);
669                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
670         } else {
671                 DEBUG(0,("No protocol supported !\n"));
672                 reply_outbuf(req, 1, 0);
673                 SSVAL(req->outbuf, smb_vwv0, choice);
674         }
675
676         DEBUG( 5, ( "negprot index=%d\n", choice ) );
677
678         if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
679             && (get_Protocol() < PROTOCOL_NT1)) {
680                 exit_server_cleanly("SMB signing is required and "
681                         "client negotiated a downlevel protocol");
682         }
683
684         TALLOC_FREE(cliprotos);
685
686         if (lp_async_smb_echo_handler() && (get_Protocol() < PROTOCOL_SMB2_02) &&
687             !fork_echo_handler(sconn)) {
688                 exit_server("Failed to fork echo handler");
689         }
690
691         END_PROFILE(SMBnegprot);
692         return;
693 }