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