s3-auth rename auth_ntlmssp_state -> auth_generic_state
[Samba.git] / source3 / smbd / negprot.c
blobf7d277be3a8b8e861bb911199d9442de0544f1db
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 "ntlmssp_wrap.h"
28 #include "messages.h"
29 #include "smbprofile.h"
30 #include "auth/gensec/gensec.h"
31 #include "../libcli/smb/smb_signing.h"
33 extern fstring remote_proto;
35 static void get_challenge(struct smbd_server_connection *sconn, uint8 buff[8])
37 NTSTATUS nt_status;
39 /* We might be called more than once, multiple negprots are
40 * permitted */
41 if (sconn->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(sconn->smb1.negprot.auth_context);
47 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
48 nt_status = make_auth_context_subsystem(
49 sconn, &sconn->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 sconn->smb1.negprot.auth_context->get_ntlm_challenge(
57 sconn->smb1.negprot.auth_context, buff);
60 /****************************************************************************
61 Reply for the core protocol.
62 ****************************************************************************/
64 static void reply_corep(struct smb_request *req, uint16 choice)
66 reply_outbuf(req, 1, 0);
67 SSVAL(req->outbuf, smb_vwv0, choice);
69 set_Protocol(PROTOCOL_CORE);
72 /****************************************************************************
73 Reply for the coreplus protocol.
74 ****************************************************************************/
76 static void reply_coreplus(struct smb_request *req, uint16 choice)
78 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
80 reply_outbuf(req, 13, 0);
82 SSVAL(req->outbuf,smb_vwv0,choice);
83 SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
84 readbraw and writebraw (possibly) */
85 /* Reply, SMBlockread, SMBwritelock supported. */
86 SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
87 SSVAL(req->outbuf,smb_vwv1,0x1); /* user level security, don't
88 * encrypt */
89 set_Protocol(PROTOCOL_COREPLUS);
92 /****************************************************************************
93 Reply for the lanman 1.0 protocol.
94 ****************************************************************************/
96 static void reply_lanman1(struct smb_request *req, uint16 choice)
98 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
99 int secword=0;
100 time_t t = time(NULL);
101 struct smbd_server_connection *sconn = req->sconn;
103 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
105 if (lp_security()>=SEC_USER) {
106 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
108 if (sconn->smb1.negprot.encrypted_passwords) {
109 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
112 reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
114 SSVAL(req->outbuf,smb_vwv0,choice);
115 SSVAL(req->outbuf,smb_vwv1,secword);
116 /* Create a token value and add it to the outgoing packet. */
117 if (sconn->smb1.negprot.encrypted_passwords) {
118 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
119 SSVAL(req->outbuf,smb_vwv11, 8);
122 set_Protocol(PROTOCOL_LANMAN1);
124 /* Reply, SMBlockread, SMBwritelock supported. */
125 SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
126 SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
127 SSVAL(req->outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
128 SSVAL(req->outbuf,smb_vwv4,1);
129 SSVAL(req->outbuf,smb_vwv5,raw); /* tell redirector we support
130 readbraw writebraw (possibly) */
131 SIVAL(req->outbuf,smb_vwv6,sys_getpid());
132 SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
134 srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
136 return;
139 /****************************************************************************
140 Reply for the lanman 2.0 protocol.
141 ****************************************************************************/
143 static void reply_lanman2(struct smb_request *req, uint16 choice)
145 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
146 int secword=0;
147 time_t t = time(NULL);
148 struct smbd_server_connection *sconn = req->sconn;
150 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
152 if (lp_security()>=SEC_USER) {
153 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
155 if (sconn->smb1.negprot.encrypted_passwords) {
156 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
159 reply_outbuf(req, 13, sconn->smb1.negprot.encrypted_passwords?8:0);
161 SSVAL(req->outbuf,smb_vwv0,choice);
162 SSVAL(req->outbuf,smb_vwv1,secword);
163 SIVAL(req->outbuf,smb_vwv6,sys_getpid());
165 /* Create a token value and add it to the outgoing packet. */
166 if (sconn->smb1.negprot.encrypted_passwords) {
167 get_challenge(sconn, (uint8 *)smb_buf(req->outbuf));
168 SSVAL(req->outbuf,smb_vwv11, 8);
171 set_Protocol(PROTOCOL_LANMAN2);
173 /* Reply, SMBlockread, SMBwritelock supported. */
174 SCVAL(req->outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
175 SSVAL(req->outbuf,smb_vwv2,sconn->smb1.negprot.max_recv);
176 SSVAL(req->outbuf,smb_vwv3,lp_maxmux());
177 SSVAL(req->outbuf,smb_vwv4,1);
178 SSVAL(req->outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
179 SSVAL(req->outbuf,smb_vwv10, set_server_zone_offset(t)/60);
180 srv_put_dos_date((char *)req->outbuf,smb_vwv8,t);
183 /****************************************************************************
184 Generate the spnego negprot reply blob. Return the number of bytes used.
185 ****************************************************************************/
187 DATA_BLOB negprot_spnego(TALLOC_CTX *ctx, struct smbd_server_connection *sconn)
189 DATA_BLOB blob = data_blob_null;
190 DATA_BLOB blob_out = data_blob_null;
191 nstring dos_name;
192 fstring unix_name;
193 NTSTATUS status;
194 #ifdef DEVELOPER
195 size_t slen;
196 #endif
197 const char *OIDs_krb5[] = {OID_KERBEROS5,
198 OID_KERBEROS5_OLD,
199 OID_NTLMSSP,
200 NULL};
201 const char *OIDs_ntlm[] = {OID_NTLMSSP, NULL};
202 struct auth_generic_state *auth_ntlmssp_state;
204 sconn->use_gensec_hook = false;
206 /* See if we can get an SPNEGO blob out of the gensec hook (if auth_samba4 is loaded) */
207 status = auth_ntlmssp_prepare(sconn->remote_address,
208 &auth_ntlmssp_state);
209 if (NT_STATUS_IS_OK(status)) {
210 status = auth_generic_start(auth_ntlmssp_state, GENSEC_OID_SPNEGO);
211 if (NT_STATUS_IS_OK(status)) {
212 status = gensec_update(auth_ntlmssp_state->gensec_security, ctx,
213 NULL, data_blob_null, &blob);
214 /* If we get the list of OIDs, the 'OK' answer
215 * is NT_STATUS_MORE_PROCESSING_REQUIRED */
216 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
217 sconn->use_gensec_hook = true;
220 TALLOC_FREE(auth_ntlmssp_state);
223 sconn->smb1.negprot.spnego = true;
225 /* strangely enough, NT does not sent the single OID NTLMSSP when
226 not a ADS member, it sends no OIDs at all
228 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
229 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
231 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
232 back to doing what W2K3 does here. This is needed to make PocketPC 2003
233 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
234 for details. JRA.
238 if (sconn->use_gensec_hook) {
239 /* blob initialised above */
240 } else if (lp_security() != SEC_ADS && !USE_KERBEROS_KEYTAB) {
241 #if 0
242 /* Code for PocketPC client */
243 blob = data_blob(guid, 16);
244 #else
245 /* Code for standalone WXP client */
246 blob = spnego_gen_negTokenInit(ctx, OIDs_ntlm, NULL, "NONE");
247 #endif
248 } else if (!lp_send_spnego_principal()) {
249 /* By default, Windows 2008 and later sends not_defined_in_RFC4178@please_ignore */
250 blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, ADS_IGNORE_PRINCIPAL);
251 } else {
252 fstring myname;
253 char *host_princ_s = NULL;
254 name_to_fqdn(myname, lp_netbios_name());
255 strlower_m(myname);
256 if (asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm())
257 == -1) {
258 return data_blob_null;
260 blob = spnego_gen_negTokenInit(ctx, OIDs_krb5, NULL, host_princ_s);
261 SAFE_FREE(host_princ_s);
264 if (blob.length == 0 || blob.data == NULL) {
265 return data_blob_null;
268 blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
269 if (blob_out.data == NULL) {
270 data_blob_free(&blob);
271 return data_blob_null;
274 memset(blob_out.data, '\0', 16);
276 checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
277 strlower_m(unix_name);
278 push_ascii_nstring(dos_name, unix_name);
279 strlcpy((char *)blob_out.data, dos_name, 17);
281 #ifdef DEVELOPER
282 /* Fix valgrind 'uninitialized bytes' issue. */
283 slen = strlen(dos_name);
284 if (slen < 16) {
285 memset(blob_out.data+slen, '\0', 16 - slen);
287 #endif
289 memcpy(&blob_out.data[16], blob.data, blob.length);
291 data_blob_free(&blob);
293 return blob_out;
296 /****************************************************************************
297 Reply for the nt protocol.
298 ****************************************************************************/
300 static void reply_nt1(struct smb_request *req, uint16 choice)
302 /* dual names + lock_and_read + nt SMBs + remote API calls */
303 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
304 CAP_LEVEL_II_OPLOCKS;
306 int secword=0;
307 bool negotiate_spnego = False;
308 struct timespec ts;
309 ssize_t ret;
310 struct smbd_server_connection *sconn = req->sconn;
311 bool signing_enabled = false;
312 bool signing_required = false;
314 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
316 /* Check the flags field to see if this is Vista.
317 WinXP sets it and Vista does not. But we have to
318 distinguish from NT which doesn't set it either. */
320 if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
321 ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
323 if (get_remote_arch() != RA_SAMBA) {
324 set_remote_arch( RA_VISTA );
328 reply_outbuf(req,17,0);
330 /* do spnego in user level security if the client
331 supports it and we can do encrypted passwords */
333 if (sconn->smb1.negprot.encrypted_passwords &&
334 (lp_security() != SEC_SHARE) &&
335 lp_use_spnego() &&
336 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
337 negotiate_spnego = True;
338 capabilities |= CAP_EXTENDED_SECURITY;
339 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
340 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
341 (already partially constructed. */
342 SSVAL(req->outbuf, smb_flg2,
343 req->flags2 | FLAGS2_EXTENDED_SECURITY);
346 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
348 if (lp_unix_extensions()) {
349 capabilities |= CAP_UNIX;
352 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
353 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
355 if (SMB_OFF_T_BITS == 64)
356 capabilities |= CAP_LARGE_FILES;
358 if (lp_readraw() && lp_writeraw())
359 capabilities |= CAP_RAW_MODE;
361 if (lp_nt_status_support())
362 capabilities |= CAP_STATUS32;
364 if (lp_host_msdfs())
365 capabilities |= CAP_DFS;
367 if (lp_security() >= SEC_USER) {
368 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
370 if (sconn->smb1.negprot.encrypted_passwords) {
371 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
374 signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state);
375 signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
377 if (signing_enabled) {
378 if (lp_security() >= SEC_USER) {
379 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
380 /* No raw mode with smb signing. */
381 capabilities &= ~CAP_RAW_MODE;
382 if (signing_required) {
383 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
385 } else {
386 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
387 if (signing_required) {
388 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
393 SSVAL(req->outbuf,smb_vwv0,choice);
394 SCVAL(req->outbuf,smb_vwv1,secword);
396 set_Protocol(PROTOCOL_NT1);
398 SSVAL(req->outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
399 SSVAL(req->outbuf,smb_vwv2+1,1); /* num vcs */
400 SIVAL(req->outbuf,smb_vwv3+1,
401 sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
402 SIVAL(req->outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
403 SIVAL(req->outbuf,smb_vwv7+1,sys_getpid()); /* session key */
404 SIVAL(req->outbuf,smb_vwv9+1,capabilities); /* capabilities */
405 clock_gettime(CLOCK_REALTIME,&ts);
406 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
407 SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
409 if (!negotiate_spnego) {
410 /* Create a token value and add it to the outgoing packet. */
411 if (sconn->smb1.negprot.encrypted_passwords) {
412 uint8 chal[8];
413 /* note that we do not send a challenge at all if
414 we are using plaintext */
415 get_challenge(sconn, chal);
416 ret = message_push_blob(
417 &req->outbuf, data_blob_const(chal, sizeof(chal)));
418 if (ret == -1) {
419 DEBUG(0, ("Could not push challenge\n"));
420 reply_nterror(req, NT_STATUS_NO_MEMORY);
421 return;
423 SCVAL(req->outbuf, smb_vwv16+1, ret);
425 ret = message_push_string(&req->outbuf, lp_workgroup(),
426 STR_UNICODE|STR_TERMINATE
427 |STR_NOALIGN);
428 if (ret == -1) {
429 DEBUG(0, ("Could not push workgroup string\n"));
430 reply_nterror(req, NT_STATUS_NO_MEMORY);
431 return;
433 ret = message_push_string(&req->outbuf, lp_netbios_name(),
434 STR_UNICODE|STR_TERMINATE
435 |STR_NOALIGN);
436 if (ret == -1) {
437 DEBUG(0, ("Could not push netbios name string\n"));
438 reply_nterror(req, NT_STATUS_NO_MEMORY);
439 return;
441 DEBUG(3,("not using SPNEGO\n"));
442 } else {
443 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
445 if (spnego_blob.data == NULL) {
446 reply_nterror(req, NT_STATUS_NO_MEMORY);
447 return;
450 ret = message_push_blob(&req->outbuf, spnego_blob);
451 if (ret == -1) {
452 DEBUG(0, ("Could not push spnego blob\n"));
453 reply_nterror(req, NT_STATUS_NO_MEMORY);
454 return;
456 data_blob_free(&spnego_blob);
458 SCVAL(req->outbuf,smb_vwv16+1, 0);
459 DEBUG(3,("using SPNEGO\n"));
462 return;
465 /* these are the protocol lists used for auto architecture detection:
467 WinNT 3.51:
468 protocol [PC NETWORK PROGRAM 1.0]
469 protocol [XENIX CORE]
470 protocol [MICROSOFT NETWORKS 1.03]
471 protocol [LANMAN1.0]
472 protocol [Windows for Workgroups 3.1a]
473 protocol [LM1.2X002]
474 protocol [LANMAN2.1]
475 protocol [NT LM 0.12]
477 Win95:
478 protocol [PC NETWORK PROGRAM 1.0]
479 protocol [XENIX CORE]
480 protocol [MICROSOFT NETWORKS 1.03]
481 protocol [LANMAN1.0]
482 protocol [Windows for Workgroups 3.1a]
483 protocol [LM1.2X002]
484 protocol [LANMAN2.1]
485 protocol [NT LM 0.12]
487 Win2K:
488 protocol [PC NETWORK PROGRAM 1.0]
489 protocol [LANMAN1.0]
490 protocol [Windows for Workgroups 3.1a]
491 protocol [LM1.2X002]
492 protocol [LANMAN2.1]
493 protocol [NT LM 0.12]
495 Vista:
496 protocol [PC NETWORK PROGRAM 1.0]
497 protocol [LANMAN1.0]
498 protocol [Windows for Workgroups 3.1a]
499 protocol [LM1.2X002]
500 protocol [LANMAN2.1]
501 protocol [NT LM 0.12]
502 protocol [SMB 2.001]
504 OS/2:
505 protocol [PC NETWORK PROGRAM 1.0]
506 protocol [XENIX CORE]
507 protocol [LANMAN1.0]
508 protocol [LM1.2X002]
509 protocol [LANMAN2.1]
513 * Modified to recognize the architecture of the remote machine better.
515 * This appears to be the matrix of which protocol is used by which
516 * MS product.
517 Protocol WfWg Win95 WinNT Win2K OS/2 Vista
518 PC NETWORK PROGRAM 1.0 1 1 1 1 1 1
519 XENIX CORE 2 2
520 MICROSOFT NETWORKS 3.0 2 2
521 DOS LM1.2X002 3 3
522 MICROSOFT NETWORKS 1.03 3
523 DOS LANMAN2.1 4 4
524 LANMAN1.0 4 2 3 2
525 Windows for Workgroups 3.1a 5 5 5 3 3
526 LM1.2X002 6 4 4 4
527 LANMAN2.1 7 5 5 5
528 NT LM 0.12 6 8 6 6
529 SMB 2.001 7
531 * tim@fsg.com 09/29/95
532 * Win2K added by matty 17/7/99
535 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
536 #define ARCH_WIN95 0x2
537 #define ARCH_WINNT 0x4
538 #define ARCH_WIN2K 0xC /* Win2K is like NT */
539 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
540 #define ARCH_SAMBA 0x20
541 #define ARCH_CIFSFS 0x40
542 #define ARCH_VISTA 0x8C /* Vista is like XP/2K */
544 #define ARCH_ALL 0x7F
546 /* List of supported protocols, most desired first */
547 static const struct {
548 const char *proto_name;
549 const char *short_name;
550 void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
551 int protocol_level;
552 } supported_protocols[] = {
553 {"SMB 2.???", "SMB2_FF", reply_smb20ff, PROTOCOL_SMB2_10},
554 {"SMB 2.002", "SMB2_02", reply_smb2002, PROTOCOL_SMB2_02},
555 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
556 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
557 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
558 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
559 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
560 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
561 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
562 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
563 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
564 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
565 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
566 {NULL,NULL,NULL,0},
569 /****************************************************************************
570 Reply to a negprot.
571 conn POINTER CAN BE NULL HERE !
572 ****************************************************************************/
574 void reply_negprot(struct smb_request *req)
576 int choice= -1;
577 int protocol;
578 const char *p;
579 int arch = ARCH_ALL;
580 int num_cliprotos;
581 char **cliprotos;
582 int i;
583 size_t converted_size;
584 struct smbd_server_connection *sconn = req->sconn;
586 START_PROFILE(SMBnegprot);
588 if (sconn->smb1.negprot.done) {
589 END_PROFILE(SMBnegprot);
590 exit_server_cleanly("multiple negprot's are not permitted");
592 sconn->smb1.negprot.done = true;
594 if (req->buflen == 0) {
595 DEBUG(0, ("negprot got no protocols\n"));
596 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
597 END_PROFILE(SMBnegprot);
598 return;
601 if (req->buf[req->buflen-1] != '\0') {
602 DEBUG(0, ("negprot protocols not 0-terminated\n"));
603 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
604 END_PROFILE(SMBnegprot);
605 return;
608 p = (const char *)req->buf + 1;
610 num_cliprotos = 0;
611 cliprotos = NULL;
613 while (smbreq_bufrem(req, p) > 0) {
615 char **tmp;
617 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
618 num_cliprotos+1);
619 if (tmp == NULL) {
620 DEBUG(0, ("talloc failed\n"));
621 TALLOC_FREE(cliprotos);
622 reply_nterror(req, NT_STATUS_NO_MEMORY);
623 END_PROFILE(SMBnegprot);
624 return;
627 cliprotos = tmp;
629 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
630 &converted_size)) {
631 DEBUG(0, ("pull_ascii_talloc failed\n"));
632 TALLOC_FREE(cliprotos);
633 reply_nterror(req, NT_STATUS_NO_MEMORY);
634 END_PROFILE(SMBnegprot);
635 return;
638 DEBUG(3, ("Requested protocol [%s]\n",
639 cliprotos[num_cliprotos]));
641 num_cliprotos += 1;
642 p += strlen(p) + 2;
645 for (i=0; i<num_cliprotos; i++) {
646 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
647 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
648 | ARCH_WIN2K );
649 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
650 arch &= ( ARCH_WFWG | ARCH_WIN95 );
651 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
652 arch &= ( ARCH_WFWG | ARCH_WIN95 );
653 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
654 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
655 | ARCH_CIFSFS);
656 else if (strcsequal(cliprotos[i], "SMB 2.001"))
657 arch = ARCH_VISTA;
658 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
659 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
660 else if (strcsequal(cliprotos[i], "LM1.2X002"))
661 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
662 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
663 arch &= ARCH_WINNT;
664 else if (strcsequal(cliprotos[i], "XENIX CORE"))
665 arch &= ( ARCH_WINNT | ARCH_OS2 );
666 else if (strcsequal(cliprotos[i], "Samba")) {
667 arch = ARCH_SAMBA;
668 break;
669 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
670 arch = ARCH_CIFSFS;
671 break;
675 /* CIFSFS can send one arch only, NT LM 0.12. */
676 if (i == 1 && (arch & ARCH_CIFSFS)) {
677 arch = ARCH_CIFSFS;
680 switch ( arch ) {
681 case ARCH_CIFSFS:
682 set_remote_arch(RA_CIFSFS);
683 break;
684 case ARCH_SAMBA:
685 set_remote_arch(RA_SAMBA);
686 break;
687 case ARCH_WFWG:
688 set_remote_arch(RA_WFWG);
689 break;
690 case ARCH_WIN95:
691 set_remote_arch(RA_WIN95);
692 break;
693 case ARCH_WINNT:
694 if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
695 set_remote_arch(RA_WIN2K);
696 else
697 set_remote_arch(RA_WINNT);
698 break;
699 case ARCH_WIN2K:
700 /* Vista may have been set in the negprot so don't
701 override it here */
702 if ( get_remote_arch() != RA_VISTA )
703 set_remote_arch(RA_WIN2K);
704 break;
705 case ARCH_VISTA:
706 set_remote_arch(RA_VISTA);
707 break;
708 case ARCH_OS2:
709 set_remote_arch(RA_OS2);
710 break;
711 default:
712 set_remote_arch(RA_UNKNOWN);
713 break;
716 /* possibly reload - change of architecture */
717 reload_services(sconn, conn_snum_used, true);
719 /* moved from the netbios session setup code since we don't have that
720 when the client connects to port 445. Of course there is a small
721 window where we are listening to messages -- jerry */
723 serverid_register(messaging_server_id(sconn->msg_ctx),
724 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
725 |FLAG_MSG_PRINT_GENERAL);
727 /* Check for protocols, most desirable first */
728 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
729 i = 0;
730 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
731 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
732 while (i < num_cliprotos) {
733 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
734 choice = i;
735 i++;
737 if(choice != -1)
738 break;
741 if(choice != -1) {
742 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
743 reload_services(sconn, conn_snum_used, true);
744 supported_protocols[protocol].proto_reply_fn(req, choice);
745 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
746 } else {
747 DEBUG(0,("No protocol supported !\n"));
748 reply_outbuf(req, 1, 0);
749 SSVAL(req->outbuf, smb_vwv0, choice);
752 DEBUG( 5, ( "negprot index=%d\n", choice ) );
754 if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
755 && (get_Protocol() < PROTOCOL_NT1)) {
756 exit_server_cleanly("SMB signing is required and "
757 "client negotiated a downlevel protocol");
760 TALLOC_FREE(cliprotos);
762 if (lp_async_smb_echo_handler() && (get_Protocol() < PROTOCOL_SMB2_02) &&
763 !fork_echo_handler(sconn)) {
764 exit_server("Failed to fork echo handler");
767 END_PROFILE(SMBnegprot);
768 return;