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