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