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