Talloc doc: Fix a cut&paste error
[Samba/gebeck_regimport.git] / source3 / smbd / negprot.c
blob9ddafee657a221ba0c3b5242787b2b6ee964ef5d
1 /*
2 Unix SMB/CIFS implementation.
3 negprot reply code
4 Copyright (C) Andrew Tridgell 1992-1998
5 Copyright (C) Volker Lendecke 2007
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.
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.
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/>.
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"
32 extern fstring remote_proto;
34 static void get_challenge(struct smbd_server_connection *sconn, uint8 buff[8])
36 NTSTATUS nt_status;
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);
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!");
54 DEBUG(10, ("get challenge: getting challenge\n"));
55 sconn->smb1.negprot.auth_context->get_ntlm_challenge(
56 sconn->smb1.negprot.auth_context, buff);
59 /****************************************************************************
60 Reply for the core protocol.
61 ****************************************************************************/
63 static void reply_corep(struct smb_request *req, uint16 choice)
65 reply_outbuf(req, 1, 0);
66 SSVAL(req->outbuf, smb_vwv0, choice);
68 set_Protocol(PROTOCOL_CORE);
71 /****************************************************************************
72 Reply for the coreplus protocol.
73 ****************************************************************************/
75 static void reply_coreplus(struct smb_request *req, uint16 choice)
77 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
79 reply_outbuf(req, 13, 0);
81 SSVAL(req->outbuf,smb_vwv0,choice);
82 SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
83 readbraw and writebraw (possibly) */
84 /* Reply, SMBlockread, SMBwritelock supported. */
85 SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
86 SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
87 * encrypt */
88 set_Protocol(PROTOCOL_COREPLUS);
91 /****************************************************************************
92 Reply for the lanman 1.0 protocol.
93 ****************************************************************************/
95 static void reply_lanman1(struct smb_request *req, uint16 choice)
97 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
98 int secword=0;
99 time_t t = time(NULL);
100 struct smbd_server_connection *sconn = req->sconn;
102 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
104 if (lp_security()>=SEC_USER) {
105 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
107 if (sconn->smb1.negprot.encrypted_passwords) {
108 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
111 reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
113 SSVAL(req->outbuf,smb_vwv0,choice);
114 SSVAL(req->outbuf,smb_vwv1,secword);
115 /* Create a token value and add it to the outgoing packet. */
116 if (sconn->smb1.negprot.encrypted_passwords) {
117 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
118 SSVAL(req->outbuf,smb_vwv11, 8);
121 set_Protocol(PROTOCOL_LANMAN1);
123 /* Reply, SMBlockread, SMBwritelock supported. */
124 SCVAL(req->outbuf,smb_flg, FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
125 SSVAL(req->outbuf,smb_vwv2, sconn->smb1.negprot.max_recv);
126 SSVAL(req->outbuf,smb_vwv3, lp_maxmux()); /* maxmux */
127 SSVAL(req->outbuf,smb_vwv4, 1);
128 SSVAL(req->outbuf,smb_vwv5, raw); /* tell redirector we support
129 readbraw writebraw (possibly) */
130 SIVAL(req->outbuf,smb_vwv6, getpid());
131 SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
133 srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
135 return;
138 /****************************************************************************
139 Reply for the lanman 2.0 protocol.
140 ****************************************************************************/
142 static void reply_lanman2(struct smb_request *req, uint16 choice)
144 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
145 int secword=0;
146 time_t t = time(NULL);
147 struct smbd_server_connection *sconn = req->sconn;
149 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
151 if (lp_security()>=SEC_USER) {
152 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
154 if (sconn->smb1.negprot.encrypted_passwords) {
155 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
158 reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
160 SSVAL(req->outbuf,smb_vwv0, choice);
161 SSVAL(req->outbuf,smb_vwv1, secword);
162 SIVAL(req->outbuf,smb_vwv6, getpid());
164 /* Create a token value and add it to the outgoing packet. */
165 if (sconn->smb1.negprot.encrypted_passwords) {
166 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
167 SSVAL(req->outbuf,smb_vwv11, 8);
170 set_Protocol(PROTOCOL_LANMAN2);
172 /* Reply, SMBlockread, SMBwritelock supported. */
173 SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
174 SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
175 SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
176 SSVAL(req->outbuf,smb_vwv4,1);
177 SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
178 SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
179 srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
182 /****************************************************************************
183 Generate the spnego negprot reply blob. Return the number of bytes used.
184 ****************************************************************************/
186 DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
188 DATA_BLOB blob = data_blob_null;
189 DATA_BLOB blob_out = data_blob_null;
190 nstring dos_name;
191 fstring unix_name;
192 NTSTATUS status;
193 #ifdef DEVELOPER
194 size_t slen;
195 #endif
196 struct gensec_security *gensec_security;
198 /* See if we can get an SPNEGO blob */
199 status = auth_generic_prepare(talloc_tos(),
200 sconn->remote_address,
201 &gensec_security);
202 if (NT_STATUS_IS_OK(status)) {
203 status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
204 if (NT_STATUS_IS_OK(status)) {
205 status = gensec_update(gensec_security, ctx,
206 NULL, data_blob_null, &blob);
207 /* If we get the list of OIDs, the 'OK' answer
208 * is NT_STATUS_MORE_PROCESSING_REQUIRED */
209 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
210 DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n"));
211 blob = data_blob_null;
214 TALLOC_FREE(gensec_security);
217 sconn->smb1.negprot.spnego = true;
219 /* strangely enough, NT does not sent the single OID NTLMSSP when
220 not a ADS member, it sends no OIDs at all
222 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
223 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
225 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
226 back to doing what W2K3 does here. This is needed to make PocketPC 2003
227 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
228 for details. JRA.
232 if (blob.length == 0 || blob.data == NULL) {
233 return data_blob_null;
236 blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
237 if (blob_out.data == NULL) {
238 data_blob_free(&blob);
239 return data_blob_null;
242 memset(blob_out.data, '\0', 16);
244 checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
245 strlower_m(unix_name);
246 push_ascii_nstring(dos_name, unix_name);
247 strlcpy((char *)blob_out.data, dos_name, 17);
249 #ifdef DEVELOPER
250 /* Fix valgrind 'uninitialized bytes' issue. */
251 slen = strlen(dos_name);
252 if (slen < 16) {
253 memset(blob_out.data+slen, '\0', 16 - slen);
255 #endif
257 memcpy(&blob_out.data[16], blob.data, blob.length);
259 data_blob_free(&blob);
261 return blob_out;
264 /****************************************************************************
265 Reply for the nt protocol.
266 ****************************************************************************/
268 static void reply_nt1(struct smb_request *req, uint16 choice)
270 /* dual names + lock_and_read + nt SMBs + remote API calls */
271 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
272 CAP_LEVEL_II_OPLOCKS;
274 int secword=0;
275 bool negotiate_spnego = False;
276 struct timespec ts;
277 ssize_t ret;
278 struct smbd_server_connection *sconn = req->sconn;
279 bool signing_enabled = false;
280 bool signing_required = false;
282 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
284 /* Check the flags field to see if this is Vista.
285 WinXP sets it and Vista does not. But we have to
286 distinguish from NT which doesn't set it either. */
288 if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
289 ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
291 if (get_remote_arch() != RA_SAMBA) {
292 set_remote_arch( RA_VISTA );
296 reply_outbuf(req,17,0);
298 /* do spnego in user level security if the client
299 supports it and we can do encrypted passwords */
301 if (sconn->smb1.negprot.encrypted_passwords &&
302 lp_use_spnego() &&
303 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
304 negotiate_spnego = True;
305 capabilities |= CAP_EXTENDED_SECURITY;
306 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
307 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
308 (already partially constructed. */
309 SSVAL(req->outbuf, smb_flg2,
310 req->flags2 | FLAGS2_EXTENDED_SECURITY);
313 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
315 if (lp_unix_extensions()) {
316 capabilities |= CAP_UNIX;
319 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
320 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
322 if (SMB_OFF_T_BITS == 64)
323 capabilities |= CAP_LARGE_FILES;
325 if (lp_readraw() && lp_writeraw())
326 capabilities |= CAP_RAW_MODE;
328 if (lp_nt_status_support())
329 capabilities |= CAP_STATUS32;
331 if (lp_host_msdfs())
332 capabilities |= CAP_DFS;
334 if (lp_security() >= SEC_USER) {
335 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
337 if (sconn->smb1.negprot.encrypted_passwords) {
338 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
341 signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state);
342 signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
344 if (signing_enabled) {
345 if (lp_security() >= SEC_USER) {
346 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
347 /* No raw mode with smb signing. */
348 capabilities &= ~CAP_RAW_MODE;
349 if (signing_required) {
350 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
352 } else {
353 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
354 if (signing_required) {
355 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
360 SSVAL(req->outbuf,smb_vwv0,choice);
361 SCVAL(req->outbuf,smb_vwv1,secword);
363 set_Protocol(PROTOCOL_NT1);
365 SSVAL(req->outbuf,smb_vwv1+1, lp_maxmux()); /* maxmpx */
366 SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
367 SIVAL(req->outbuf,smb_vwv3+1,
368 sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
369 SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */
370 SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */
371 SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */
372 clock_gettime(CLOCK_REALTIME,&ts);
373 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
374 SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
376 if (!negotiate_spnego) {
377 /* Create a token value and add it to the outgoing packet. */
378 if (sconn->smb1.negprot.encrypted_passwords) {
379 uint8 chal[8];
380 /* note that we do not send a challenge at all if
381 we are using plaintext */
382 get_challenge(sconn, chal);
383 ret = message_push_blob(
384 &req->outbuf, data_blob_const(chal, sizeof(chal)));
385 if (ret == -1) {
386 DEBUG(0, ("Could not push challenge\n"));
387 reply_nterror(req, NT_STATUS_NO_MEMORY);
388 return;
390 SCVAL(req->outbuf, smb_vwv16+1, ret);
392 ret = message_push_string(&req->outbuf, lp_workgroup(),
393 STR_UNICODE|STR_TERMINATE
394 |STR_NOALIGN);
395 if (ret == -1) {
396 DEBUG(0, ("Could not push workgroup string\n"));
397 reply_nterror(req, NT_STATUS_NO_MEMORY);
398 return;
400 ret = message_push_string(&req->outbuf, lp_netbios_name(),
401 STR_UNICODE|STR_TERMINATE
402 |STR_NOALIGN);
403 if (ret == -1) {
404 DEBUG(0, ("Could not push netbios name string\n"));
405 reply_nterror(req, NT_STATUS_NO_MEMORY);
406 return;
408 DEBUG(3,("not using SPNEGO\n"));
409 } else {
410 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
412 if (spnego_blob.data == NULL) {
413 reply_nterror(req, NT_STATUS_NO_MEMORY);
414 return;
417 ret = message_push_blob(&req->outbuf, spnego_blob);
418 if (ret == -1) {
419 DEBUG(0, ("Could not push spnego blob\n"));
420 reply_nterror(req, NT_STATUS_NO_MEMORY);
421 return;
423 data_blob_free(&spnego_blob);
425 SCVAL(req->outbuf,smb_vwv16+1, 0);
426 DEBUG(3,("using SPNEGO\n"));
429 return;
432 /* these are the protocol lists used for auto architecture detection:
434 WinNT 3.51:
435 protocol [PC NETWORK PROGRAM 1.0]
436 protocol [XENIX CORE]
437 protocol [MICROSOFT NETWORKS 1.03]
438 protocol [LANMAN1.0]
439 protocol [Windows for Workgroups 3.1a]
440 protocol [LM1.2X002]
441 protocol [LANMAN2.1]
442 protocol [NT LM 0.12]
444 Win95:
445 protocol [PC NETWORK PROGRAM 1.0]
446 protocol [XENIX CORE]
447 protocol [MICROSOFT NETWORKS 1.03]
448 protocol [LANMAN1.0]
449 protocol [Windows for Workgroups 3.1a]
450 protocol [LM1.2X002]
451 protocol [LANMAN2.1]
452 protocol [NT LM 0.12]
454 Win2K:
455 protocol [PC NETWORK PROGRAM 1.0]
456 protocol [LANMAN1.0]
457 protocol [Windows for Workgroups 3.1a]
458 protocol [LM1.2X002]
459 protocol [LANMAN2.1]
460 protocol [NT LM 0.12]
462 Vista:
463 protocol [PC NETWORK PROGRAM 1.0]
464 protocol [LANMAN1.0]
465 protocol [Windows for Workgroups 3.1a]
466 protocol [LM1.2X002]
467 protocol [LANMAN2.1]
468 protocol [NT LM 0.12]
469 protocol [SMB 2.001]
471 OS/2:
472 protocol [PC NETWORK PROGRAM 1.0]
473 protocol [XENIX CORE]
474 protocol [LANMAN1.0]
475 protocol [LM1.2X002]
476 protocol [LANMAN2.1]
480 * Modified to recognize the architecture of the remote machine better.
482 * This appears to be the matrix of which protocol is used by which
483 * MS product.
484 Protocol WfWg Win95 WinNT Win2K OS/2 Vista
485 PC NETWORK PROGRAM 1.0 1 1 1 1 1 1
486 XENIX CORE 2 2
487 MICROSOFT NETWORKS 3.0 2 2
488 DOS LM1.2X002 3 3
489 MICROSOFT NETWORKS 1.03 3
490 DOS LANMAN2.1 4 4
491 LANMAN1.0 4 2 3 2
492 Windows for Workgroups 3.1a 5 5 5 3 3
493 LM1.2X002 6 4 4 4
494 LANMAN2.1 7 5 5 5
495 NT LM 0.12 6 8 6 6
496 SMB 2.001 7
498 * tim@fsg.com 09/29/95
499 * Win2K added by matty 17/7/99
502 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
503 #define ARCH_WIN95 0x2
504 #define ARCH_WINNT 0x4
505 #define ARCH_WIN2K 0xC /* Win2K is like NT */
506 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
507 #define ARCH_SAMBA 0x20
508 #define ARCH_CIFSFS 0x40
509 #define ARCH_VISTA 0x8C /* Vista is like XP/2K */
511 #define ARCH_ALL 0x7F
513 /* List of supported protocols, most desired first */
514 static const struct {
515 const char *proto_name;
516 const char *short_name;
517 void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
518 int protocol_level;
519 } supported_protocols[] = {
520 {"SMB 2.???", "SMB2_FF", reply_smb20ff, PROTOCOL_SMB2_10},
521 {"SMB 2.002", "SMB2_02", reply_smb2002, PROTOCOL_SMB2_02},
522 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
523 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
524 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
525 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
526 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
527 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
528 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
529 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
530 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
531 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
532 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
533 {NULL,NULL,NULL,0},
536 /****************************************************************************
537 Reply to a negprot.
538 conn POINTER CAN BE NULL HERE !
539 ****************************************************************************/
541 void reply_negprot(struct smb_request *req)
543 int choice= -1;
544 int protocol;
545 const char *p;
546 int arch = ARCH_ALL;
547 int num_cliprotos;
548 char **cliprotos;
549 int i;
550 size_t converted_size;
551 struct smbd_server_connection *sconn = req->sconn;
553 START_PROFILE(SMBnegprot);
555 if (sconn->smb1.negprot.done) {
556 END_PROFILE(SMBnegprot);
557 exit_server_cleanly("multiple negprot's are not permitted");
559 sconn->smb1.negprot.done = true;
561 if (req->buflen == 0) {
562 DEBUG(0, ("negprot got no protocols\n"));
563 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
564 END_PROFILE(SMBnegprot);
565 return;
568 if (req->buf[req->buflen-1] != '\0') {
569 DEBUG(0, ("negprot protocols not 0-terminated\n"));
570 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
571 END_PROFILE(SMBnegprot);
572 return;
575 p = (const char *)req->buf + 1;
577 num_cliprotos = 0;
578 cliprotos = NULL;
580 while (smbreq_bufrem(req, p) > 0) {
582 char **tmp;
584 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
585 num_cliprotos+1);
586 if (tmp == NULL) {
587 DEBUG(0, ("talloc failed\n"));
588 TALLOC_FREE(cliprotos);
589 reply_nterror(req, NT_STATUS_NO_MEMORY);
590 END_PROFILE(SMBnegprot);
591 return;
594 cliprotos = tmp;
596 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
597 &converted_size)) {
598 DEBUG(0, ("pull_ascii_talloc failed\n"));
599 TALLOC_FREE(cliprotos);
600 reply_nterror(req, NT_STATUS_NO_MEMORY);
601 END_PROFILE(SMBnegprot);
602 return;
605 DEBUG(3, ("Requested protocol [%s]\n",
606 cliprotos[num_cliprotos]));
608 num_cliprotos += 1;
609 p += strlen(p) + 2;
612 for (i=0; i<num_cliprotos; i++) {
613 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
614 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
615 | ARCH_WIN2K );
616 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
617 arch &= ( ARCH_WFWG | ARCH_WIN95 );
618 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
619 arch &= ( ARCH_WFWG | ARCH_WIN95 );
620 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
621 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
622 | ARCH_CIFSFS);
623 else if (strcsequal(cliprotos[i], "SMB 2.001"))
624 arch = ARCH_VISTA;
625 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
626 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
627 else if (strcsequal(cliprotos[i], "LM1.2X002"))
628 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
629 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
630 arch &= ARCH_WINNT;
631 else if (strcsequal(cliprotos[i], "XENIX CORE"))
632 arch &= ( ARCH_WINNT | ARCH_OS2 );
633 else if (strcsequal(cliprotos[i], "Samba")) {
634 arch = ARCH_SAMBA;
635 break;
636 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
637 arch = ARCH_CIFSFS;
638 break;
642 /* CIFSFS can send one arch only, NT LM 0.12. */
643 if (i == 1 && (arch & ARCH_CIFSFS)) {
644 arch = ARCH_CIFSFS;
647 switch ( arch ) {
648 case ARCH_CIFSFS:
649 set_remote_arch(RA_CIFSFS);
650 break;
651 case ARCH_SAMBA:
652 set_remote_arch(RA_SAMBA);
653 break;
654 case ARCH_WFWG:
655 set_remote_arch(RA_WFWG);
656 break;
657 case ARCH_WIN95:
658 set_remote_arch(RA_WIN95);
659 break;
660 case ARCH_WINNT:
661 if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
662 set_remote_arch(RA_WIN2K);
663 else
664 set_remote_arch(RA_WINNT);
665 break;
666 case ARCH_WIN2K:
667 /* Vista may have been set in the negprot so don't
668 override it here */
669 if ( get_remote_arch() != RA_VISTA )
670 set_remote_arch(RA_WIN2K);
671 break;
672 case ARCH_VISTA:
673 set_remote_arch(RA_VISTA);
674 break;
675 case ARCH_OS2:
676 set_remote_arch(RA_OS2);
677 break;
678 default:
679 set_remote_arch(RA_UNKNOWN);
680 break;
683 /* possibly reload - change of architecture */
684 reload_services(sconn, conn_snum_used, true);
686 /* moved from the netbios session setup code since we don't have that
687 when the client connects to port 445. Of course there is a small
688 window where we are listening to messages -- jerry */
690 serverid_register(messaging_server_id(sconn->msg_ctx),
691 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
692 |FLAG_MSG_PRINT_GENERAL);
694 /* Check for protocols, most desirable first */
695 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
696 i = 0;
697 if ((supported_protocols[protocol].protocol_level <= lp_srv_maxprotocol()) &&
698 (supported_protocols[protocol].protocol_level >= lp_srv_minprotocol()))
699 while (i < num_cliprotos) {
700 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
701 choice = i;
702 i++;
704 if(choice != -1)
705 break;
708 if(choice != -1) {
709 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
710 reload_services(sconn, conn_snum_used, true);
711 supported_protocols[protocol].proto_reply_fn(req, choice);
712 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
713 } else {
714 DEBUG(0,("No protocol supported !\n"));
715 reply_outbuf(req, 1, 0);
716 SSVAL(req->outbuf, smb_vwv0, choice);
719 DEBUG( 5, ( "negprot index=%d\n", choice ) );
721 if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
722 && (get_Protocol() < PROTOCOL_NT1)) {
723 exit_server_cleanly("SMB signing is required and "
724 "client negotiated a downlevel protocol");
727 TALLOC_FREE(cliprotos);
729 if (lp_async_smb_echo_handler() && (get_Protocol() < PROTOCOL_SMB2_02) &&
730 !fork_echo_handler(sconn)) {
731 exit_server("Failed to fork echo handler");
734 END_PROFILE(SMBnegprot);
735 return;