s3-smbd: Remove support for protocols before LANMAN1
[sfrench/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         if (lp_security()>=SEC_USER) {
73                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
74         }
75         if (sconn->smb1.negprot.encrypted_passwords) {
76                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
77         }
78
79         reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
80
81         SSVAL(req->outbuf,smb_vwv0,choice);
82         SSVAL(req->outbuf,smb_vwv1,secword);
83         /* Create a token value and add it to the outgoing packet. */
84         if (sconn->smb1.negprot.encrypted_passwords) {
85                 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
86                 SSVAL(req->outbuf,smb_vwv11, 8);
87         }
88
89         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN1);
90
91         /* Reply, SMBlockread, SMBwritelock supported. */
92         SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
93         SSVAL(req->outbuf,smb_vwv2, sconn->smb1.negprot.max_recv);
94         SSVAL(req->outbuf,smb_vwv3, lp_maxmux()); /* maxmux */
95         SSVAL(req->outbuf,smb_vwv4, 1);
96         SSVAL(req->outbuf,smb_vwv5, raw); /* tell redirector we support
97                 readbraw writebraw (possibly) */
98         SIVAL(req->outbuf,smb_vwv6, getpid());
99         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
100
101         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
102
103         return;
104 }
105
106 /****************************************************************************
107  Reply for the lanman 2.0 protocol.
108 ****************************************************************************/
109
110 static void reply_lanman2(struct smb_request *req, uint16 choice)
111 {
112         int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
113         int secword=0;
114         time_t t = time(NULL);
115         struct smbd_server_connection *sconn = req->sconn;
116
117         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
118
119         if (lp_security()>=SEC_USER) {
120                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
121         }
122         if (sconn->smb1.negprot.encrypted_passwords) {
123                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
124         }
125
126         reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
127
128         SSVAL(req->outbuf,smb_vwv0, choice);
129         SSVAL(req->outbuf,smb_vwv1, secword);
130         SIVAL(req->outbuf,smb_vwv6, getpid());
131
132         /* Create a token value and add it to the outgoing packet. */
133         if (sconn->smb1.negprot.encrypted_passwords) {
134                 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
135                 SSVAL(req->outbuf,smb_vwv11, 8);
136         }
137
138         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_LANMAN2);
139
140         /* Reply, SMBlockread, SMBwritelock supported. */
141         SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
142         SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
143         SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
144         SSVAL(req->outbuf,smb_vwv4,1);
145         SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
146         SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
147         srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
148 }
149
150 /****************************************************************************
151  Generate the spnego negprot reply blob. Return the number of bytes used.
152 ****************************************************************************/
153
154 DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
155 {
156         DATA_BLOB blob = data_blob_null;
157         DATA_BLOB blob_out = data_blob_null;
158         nstring dos_name;
159         fstring unix_name;
160         NTSTATUS status;
161 #ifdef DEVELOPER
162         size_t slen;
163 #endif
164         struct gensec_security *gensec_security;
165
166         /* See if we can get an SPNEGO blob */
167         status = auth_generic_prepare(talloc_tos(),
168                                       sconn->remote_address,
169                                       &gensec_security);
170         if (NT_STATUS_IS_OK(status)) {
171                 status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
172                 if (NT_STATUS_IS_OK(status)) {
173                         status = gensec_update(gensec_security, ctx,
174                                                NULL, data_blob_null, &blob);
175                         /* If we get the list of OIDs, the 'OK' answer
176                          * is NT_STATUS_MORE_PROCESSING_REQUIRED */
177                         if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
178                                 DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n"));
179                                 blob = data_blob_null;
180                         }
181                 }
182                 TALLOC_FREE(gensec_security);
183         }
184
185         sconn->smb1.negprot.spnego = true;
186
187         /* strangely enough, NT does not sent the single OID NTLMSSP when
188            not a ADS member, it sends no OIDs at all
189
190            OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
191                    about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
192
193            Our sessionsetup code now handles raw NTLMSSP connects, so we can go
194            back to doing what W2K3 does here. This is needed to make PocketPC 2003
195            CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
196            for details. JRA.
197
198         */
199
200         if (blob.length == 0 || blob.data == NULL) {
201                 return data_blob_null;
202         }
203
204         blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
205         if (blob_out.data == NULL) {
206                 data_blob_free(&blob);
207                 return data_blob_null;
208         }
209
210         memset(blob_out.data, '\0', 16);
211
212         checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
213         strlower_m(unix_name);
214         push_ascii_nstring(dos_name, unix_name);
215         strlcpy((char *)blob_out.data, dos_name, 17);
216
217 #ifdef DEVELOPER
218         /* Fix valgrind 'uninitialized bytes' issue. */
219         slen = strlen(dos_name);
220         if (slen < 16) {
221                 memset(blob_out.data+slen, '\0', 16 - slen);
222         }
223 #endif
224
225         memcpy(&blob_out.data[16], blob.data, blob.length);
226
227         data_blob_free(&blob);
228
229         return blob_out;
230 }
231
232 /****************************************************************************
233  Reply for the nt protocol.
234 ****************************************************************************/
235
236 static void reply_nt1(struct smb_request *req, uint16 choice)
237 {
238         /* dual names + lock_and_read + nt SMBs + remote API calls */
239         int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
240                 CAP_LEVEL_II_OPLOCKS;
241
242         int secword=0;
243         bool negotiate_spnego = False;
244         struct timespec ts;
245         ssize_t ret;
246         struct smbd_server_connection *sconn = req->sconn;
247         bool signing_enabled = false;
248         bool signing_required = false;
249
250         sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
251
252         /* Check the flags field to see if this is Vista.
253            WinXP sets it and Vista does not. But we have to 
254            distinguish from NT which doesn't set it either. */
255
256         if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
257                 ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
258         {
259                 if (get_remote_arch() != RA_SAMBA) {
260                         set_remote_arch( RA_VISTA );
261                 }
262         }
263
264         reply_outbuf(req,17,0);
265
266         /* do spnego in user level security if the client
267            supports it and we can do encrypted passwords */
268
269         if (sconn->smb1.negprot.encrypted_passwords &&
270             lp_use_spnego() &&
271             (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
272                 negotiate_spnego = True;
273                 capabilities |= CAP_EXTENDED_SECURITY;
274                 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
275                 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
276                    (already partially constructed. */
277                 SSVAL(req->outbuf, smb_flg2,
278                       req->flags2 | FLAGS2_EXTENDED_SECURITY);
279         }
280
281         capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
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         if (lp_security() >= SEC_USER) {
303                 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
304         }
305         if (sconn->smb1.negprot.encrypted_passwords) {
306                 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
307         }
308
309         signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state);
310         signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
311
312         if (signing_enabled) {
313                 if (lp_security() >= SEC_USER) {
314                         secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
315                         /* No raw mode with smb signing. */
316                         capabilities &= ~CAP_RAW_MODE;
317                         if (signing_required) {
318                                 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
319                         }
320                 } else {
321                         DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
322                         if (signing_required) {
323                                 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
324                         }
325                 }
326         }
327
328         SSVAL(req->outbuf,smb_vwv0,choice);
329         SCVAL(req->outbuf,smb_vwv1,secword);
330
331         smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1);
332
333         SSVAL(req->outbuf,smb_vwv1+1, lp_maxmux()); /* maxmpx */
334         SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
335         SIVAL(req->outbuf,smb_vwv3+1,
336               sconn->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 (sconn->smb1.negprot.encrypted_passwords) {
347                         uint8 chal[8];
348                         /* note that we do not send a challenge at all if
349                            we are using plaintext */
350                         get_challenge(sconn, 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, req->sconn);
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 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 protocol;
511         const char *p;
512         int arch = ARCH_ALL;
513         int num_cliprotos;
514         char **cliprotos;
515         int i;
516         size_t converted_size;
517         struct smbd_server_connection *sconn = req->sconn;
518
519         START_PROFILE(SMBnegprot);
520
521         if (sconn->smb1.negprot.done) {
522                 END_PROFILE(SMBnegprot);
523                 exit_server_cleanly("multiple negprot's are not permitted");
524         }
525         sconn->smb1.negprot.done = true;
526
527         if (req->buflen == 0) {
528                 DEBUG(0, ("negprot got no protocols\n"));
529                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
530                 END_PROFILE(SMBnegprot);
531                 return;
532         }
533
534         if (req->buf[req->buflen-1] != '\0') {
535                 DEBUG(0, ("negprot protocols not 0-terminated\n"));
536                 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
537                 END_PROFILE(SMBnegprot);
538                 return;
539         }
540
541         p = (const char *)req->buf + 1;
542
543         num_cliprotos = 0;
544         cliprotos = NULL;
545
546         while (smbreq_bufrem(req, p) > 0) {
547
548                 char **tmp;
549
550                 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
551                                            num_cliprotos+1);
552                 if (tmp == NULL) {
553                         DEBUG(0, ("talloc failed\n"));
554                         TALLOC_FREE(cliprotos);
555                         reply_nterror(req, NT_STATUS_NO_MEMORY);
556                         END_PROFILE(SMBnegprot);
557                         return;
558                 }
559
560                 cliprotos = tmp;
561
562                 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
563                                        &converted_size)) {
564                         DEBUG(0, ("pull_ascii_talloc failed\n"));
565                         TALLOC_FREE(cliprotos);
566                         reply_nterror(req, NT_STATUS_NO_MEMORY);
567                         END_PROFILE(SMBnegprot);
568                         return;
569                 }
570
571                 DEBUG(3, ("Requested protocol [%s]\n",
572                           cliprotos[num_cliprotos]));
573
574                 num_cliprotos += 1;
575                 p += strlen(p) + 2;
576         }
577
578         for (i=0; i<num_cliprotos; i++) {
579                 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
580                         arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
581                                   | ARCH_WIN2K );
582                 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
583                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
584                 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
585                         arch &= ( ARCH_WFWG | ARCH_WIN95 );
586                 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
587                         arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
588                                   | ARCH_CIFSFS);
589                 else if (strcsequal(cliprotos[i], "SMB 2.001"))
590                         arch = ARCH_VISTA;              
591                 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
592                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
593                 else if (strcsequal(cliprotos[i], "LM1.2X002"))
594                         arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
595                 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
596                         arch &= ARCH_WINNT;
597                 else if (strcsequal(cliprotos[i], "XENIX CORE"))
598                         arch &= ( ARCH_WINNT | ARCH_OS2 );
599                 else if (strcsequal(cliprotos[i], "Samba")) {
600                         arch = ARCH_SAMBA;
601                         break;
602                 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
603                         arch = ARCH_CIFSFS;
604                         break;
605                 }
606         }
607
608         /* CIFSFS can send one arch only, NT LM 0.12. */
609         if (i == 1 && (arch & ARCH_CIFSFS)) {
610                 arch = ARCH_CIFSFS;
611         }
612
613         switch ( arch ) {
614                 case ARCH_CIFSFS:
615                         set_remote_arch(RA_CIFSFS);
616                         break;
617                 case ARCH_SAMBA:
618                         set_remote_arch(RA_SAMBA);
619                         break;
620                 case ARCH_WFWG:
621                         set_remote_arch(RA_WFWG);
622                         break;
623                 case ARCH_WIN95:
624                         set_remote_arch(RA_WIN95);
625                         break;
626                 case ARCH_WINNT:
627                         if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
628                                 set_remote_arch(RA_WIN2K);
629                         else
630                                 set_remote_arch(RA_WINNT);
631                         break;
632                 case ARCH_WIN2K:
633                         /* Vista may have been set in the negprot so don't 
634                            override it here */
635                         if ( get_remote_arch() != RA_VISTA )
636                                 set_remote_arch(RA_WIN2K);
637                         break;
638                 case ARCH_VISTA:
639                         set_remote_arch(RA_VISTA);
640                         break;
641                 case ARCH_OS2:
642                         set_remote_arch(RA_OS2);
643                         break;
644                 default:
645                         set_remote_arch(RA_UNKNOWN);
646                 break;
647         }
648
649         /* possibly reload - change of architecture */
650         reload_services(sconn, conn_snum_used, true);
651
652         /* moved from the netbios session setup code since we don't have that 
653            when the client connects to port 445.  Of course there is a small
654            window where we are listening to messages   -- jerry */
655
656         serverid_register(messaging_server_id(sconn->msg_ctx),
657                           FLAG_MSG_GENERAL|FLAG_MSG_SMBD
658                           |FLAG_MSG_PRINT_GENERAL);
659
660         /* Check for protocols, most desirable first */
661         for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
662                 i = 0;
663                 if ((supported_protocols[protocol].protocol_level <= lp_srv_maxprotocol()) &&
664                                 (supported_protocols[protocol].protocol_level >= lp_srv_minprotocol()))
665                         while (i < num_cliprotos) {
666                                 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
667                                         choice = i;
668                                 i++;
669                         }
670                 if(choice != -1)
671                         break;
672         }
673
674         if(choice != -1) {
675                 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
676                 reload_services(sconn, conn_snum_used, true);
677                 supported_protocols[protocol].proto_reply_fn(req, choice);
678                 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
679         } else {
680                 DEBUG(0,("No protocol supported !\n"));
681                 reply_outbuf(req, 1, 0);
682                 SSVAL(req->outbuf, smb_vwv0, choice);
683         }
684
685         DEBUG( 5, ( "negprot index=%d\n", choice ) );
686
687         if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
688             && (get_Protocol() < PROTOCOL_NT1)) {
689                 exit_server_cleanly("SMB signing is required and "
690                         "client negotiated a downlevel protocol");
691         }
692
693         TALLOC_FREE(cliprotos);
694
695         if (lp_async_smb_echo_handler() && (get_Protocol() < PROTOCOL_SMB2_02) &&
696             !fork_echo_handler(sconn)) {
697                 exit_server("Failed to fork echo handler");
698         }
699
700         END_PROFILE(SMBnegprot);
701         return;
702 }