param: rename lp function and variable from "encrypted_passwords" to "encrypt_passwords"
[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_encrypt_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_max_mux()); /* 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_encrypt_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_max_mux());
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_encrypt_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())
288                 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
289
290         capabilities |= CAP_LARGE_FILES;
291
292         if (lp_readraw() && lp_writeraw())
293                 capabilities |= CAP_RAW_MODE;
294
295         if (lp_nt_status_support())
296                 capabilities |= CAP_STATUS32;
297
298         if (lp_host_msdfs())
299                 capabilities |= CAP_DFS;
300
301         secword |= NEGOTIATE_SECURITY_USER_LEVEL;
302         if (sconn->smb1.negprot.encrypted_passwords) {
303                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
304         }
305
306         signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state);
307         signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
308
309         if (signing_enabled) {
310                 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
311                 /* No raw mode with smb signing. */
312                 capabilities &= ~CAP_RAW_MODE;
313                 if (signing_required) {
314                         secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
315                 }
316         }
317
318         SSVAL(req->outbuf,smb_vwv0,choice);
319         SCVAL(req->outbuf,smb_vwv1,secword);
320
321         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1);
322
323         SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */
324         SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
325         SIVAL(req->outbuf,smb_vwv3+1,
326               sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
327         SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */
328         SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */
329         SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */
330         clock_gettime(CLOCK_REALTIME,&ts);
331         put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
332         SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
333
334         if (!negotiate_spnego) {
335                 /* Create a token value and add it to the outgoing packet. */
336                 if (sconn->smb1.negprot.encrypted_passwords) {
337                         uint8 chal[8];
338                         /* note that we do not send a challenge at all if
339                            we are using plaintext */
340                         get_challenge(sconn, chal);
341                         ret = message_push_blob(
342                                 &req->outbuf, data_blob_const(chal, sizeof(chal)));
343                         if (ret == -1) {
344                                 DEBUG(0, ("Could not push challenge\n"));
345                                 reply_nterror(req, NT_STATUS_NO_MEMORY);
346                                 return;
347                         }
348                         SCVAL(req->outbuf, smb_vwv16+1, ret);
349                 }
350                 ret = message_push_string(&req->outbuf, lp_workgroup(),
351                                           STR_UNICODE|STR_TERMINATE
352                                           |STR_NOALIGN);
353                 if (ret == -1) {
354                         DEBUG(0, ("Could not push workgroup string\n"));
355                         reply_nterror(req, NT_STATUS_NO_MEMORY);
356                         return;
357                 }
358                 ret = message_push_string(&req->outbuf, lp_netbios_name(),
359                                           STR_UNICODE|STR_TERMINATE
360                                           |STR_NOALIGN);
361                 if (ret == -1) {
362                         DEBUG(0, ("Could not push netbios name string\n"));
363                         reply_nterror(req, NT_STATUS_NO_MEMORY);
364                         return;
365                 }
366                 DEBUG(3,("not using SPNEGO\n"));
367         } else {
368                 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
369
370                 if (spnego_blob.data == NULL) {
371                         reply_nterror(req, NT_STATUS_NO_MEMORY);
372                         return;
373                 }
374
375                 ret = message_push_blob(&req->outbuf, spnego_blob);
376                 if (ret == -1) {
377                         DEBUG(0, ("Could not push spnego blob\n"));
378                         reply_nterror(req, NT_STATUS_NO_MEMORY);
379                         return;
380                 }
381                 data_blob_free(&spnego_blob);
382
383                 SCVAL(req->outbuf,smb_vwv16+1, 0);
384                 DEBUG(3,("using SPNEGO\n"));
385         }
386
387         return;
388 }
389
390 /* these are the protocol lists used for auto architecture detection:
391
392 WinNT 3.51:
393 protocol [PC NETWORK PROGRAM 1.0]
394 protocol [XENIX CORE]
395 protocol [MICROSOFT NETWORKS 1.03]
396 protocol [LANMAN1.0]
397 protocol [Windows for Workgroups 3.1a]
398 protocol [LM1.2X002]
399 protocol [LANMAN2.1]
400 protocol [NT LM 0.12]
401
402 Win95:
403 protocol [PC NETWORK PROGRAM 1.0]
404 protocol [XENIX CORE]
405 protocol [MICROSOFT NETWORKS 1.03]
406 protocol [LANMAN1.0]
407 protocol [Windows for Workgroups 3.1a]
408 protocol [LM1.2X002]
409 protocol [LANMAN2.1]
410 protocol [NT LM 0.12]
411
412 Win2K:
413 protocol [PC NETWORK PROGRAM 1.0]
414 protocol [LANMAN1.0]
415 protocol [Windows for Workgroups 3.1a]
416 protocol [LM1.2X002]
417 protocol [LANMAN2.1]
418 protocol [NT LM 0.12]
419
420 Vista:
421 protocol [PC NETWORK PROGRAM 1.0]
422 protocol [LANMAN1.0]
423 protocol [Windows for Workgroups 3.1a]
424 protocol [LM1.2X002]
425 protocol [LANMAN2.1]
426 protocol [NT LM 0.12]
427 protocol [SMB 2.001]
428
429 OS/2:
430 protocol [PC NETWORK PROGRAM 1.0]
431 protocol [XENIX CORE]
432 protocol [LANMAN1.0]
433 protocol [LM1.2X002]
434 protocol [LANMAN2.1]
435 */
436
437 /*
438   * Modified to recognize the architecture of the remote machine better.
439   *
440   * This appears to be the matrix of which protocol is used by which
441   * MS product.
442        Protocol                       WfWg    Win95   WinNT  Win2K  OS/2 Vista
443        PC NETWORK PROGRAM 1.0          1       1       1      1      1     1
444        XENIX CORE                                      2             2
445        MICROSOFT NETWORKS 3.0          2       2       
446        DOS LM1.2X002                   3       3       
447        MICROSOFT NETWORKS 1.03                         3
448        DOS LANMAN2.1                   4       4       
449        LANMAN1.0                                       4      2      3     2
450        Windows for Workgroups 3.1a     5       5       5      3            3
451        LM1.2X002                                       6      4      4     4
452        LANMAN2.1                                       7      5      5     5
453        NT LM 0.12                              6       8      6            6
454        SMB 2.001                                                           7
455   *
456   *  tim@fsg.com 09/29/95
457   *  Win2K added by matty 17/7/99
458   */
459
460 #define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
461 #define ARCH_WIN95    0x2
462 #define ARCH_WINNT    0x4
463 #define ARCH_WIN2K    0xC      /* Win2K is like NT */
464 #define ARCH_OS2      0x14     /* Again OS/2 is like NT */
465 #define ARCH_SAMBA    0x20
466 #define ARCH_CIFSFS   0x40
467 #define ARCH_VISTA    0x8C     /* Vista is like XP/2K */
468
469 #define ARCH_ALL      0x7F
470
471 /* List of supported protocols, most desired first */
472 static const struct {
473         const char *proto_name;
474         const char *short_name;
475         void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
476         int protocol_level;
477 } supported_protocols[] = {
478         {"SMB 2.???",               "SMB2_FF",  reply_smb20ff,  PROTOCOL_SMB2_10},
479         {"SMB 2.002",               "SMB2_02",  reply_smb2002,  PROTOCOL_SMB2_02},
480         {"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
481         {"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
482         {"POSIX 2",                 "NT1",      reply_nt1,      PROTOCOL_NT1},
483         {"LANMAN2.1",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
484         {"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
485         {"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
486         {"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
487         {"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
488         {"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
489         {NULL,NULL,NULL,0},
490 };
491
492 /****************************************************************************
493  Reply to a negprot.
494  conn POINTER CAN BE NULL HERE !
495 ****************************************************************************/
496
497 void reply_negprot(struct smb_request *req)
498 {
499         int choice= -1;
500         int chosen_level = -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_server_max_protocol()) &&
655                                 (supported_protocols[protocol].protocol_level >= lp_server_min_protocol()))
656                         while (i < num_cliprotos) {
657                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name)) {
658                                         choice = i;
659                                         chosen_level = supported_protocols[protocol].protocol_level;
660                                 }
661                                 i++;
662                         }
663                 if(choice != -1)
664                         break;
665         }
666
667         if(choice != -1) {
668                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
669                 reload_services(sconn, conn_snum_used, true);
670                 supported_protocols[protocol].proto_reply_fn(req, choice);
671                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
672         } else {
673                 DEBUG(0,("No protocol supported !\n"));
674                 reply_outbuf(req, 1, 0);
675                 SSVAL(req->outbuf, smb_vwv0, choice);
676         }
677
678         DEBUG( 5, ( "negprot index=%d\n", choice ) );
679
680         if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
681             && (chosen_level < PROTOCOL_NT1)) {
682                 exit_server_cleanly("SMB signing is required and "
683                         "client negotiated a downlevel protocol");
684         }
685
686         TALLOC_FREE(cliprotos);
687
688         if (lp_async_smb_echo_handler() && (chosen_level < PROTOCOL_SMB2_02) &&
689             !fork_echo_handler(sconn)) {
690                 exit_server("Failed to fork echo handler");
691         }
692
693         END_PROFILE(SMBnegprot);
694         return;
695 }