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