s3:libsmb: get rid of clisigning routines
[Samba/gebeck_regimport.git] / source3 / smbd / negprot.c
bloba55a7c336c52b25b0e871938d347c34ede096ec4
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 smbXsrv_connection_init_tables(req->sconn->conn, 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 */
89 smbXsrv_connection_init_tables(req->sconn->conn, 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 smbXsrv_connection_init_tables(req->sconn->conn, 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, 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, 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 smbXsrv_connection_init_tables(req->sconn->conn, 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 struct gensec_security *gensec_security;
199 /* See if we can get an SPNEGO blob */
200 status = auth_generic_prepare(talloc_tos(),
201 sconn->remote_address,
202 &gensec_security);
203 if (NT_STATUS_IS_OK(status)) {
204 status = gensec_start_mech_by_oid(gensec_security, GENSEC_OID_SPNEGO);
205 if (NT_STATUS_IS_OK(status)) {
206 status = gensec_update(gensec_security, ctx,
207 NULL, data_blob_null, &blob);
208 /* If we get the list of OIDs, the 'OK' answer
209 * is NT_STATUS_MORE_PROCESSING_REQUIRED */
210 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
211 DEBUG(0, ("Failed to start SPNEGO handler for negprot OID list!\n"));
212 blob = data_blob_null;
215 TALLOC_FREE(gensec_security);
218 sconn->smb1.negprot.spnego = true;
220 /* strangely enough, NT does not sent the single OID NTLMSSP when
221 not a ADS member, it sends no OIDs at all
223 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
224 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
226 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
227 back to doing what W2K3 does here. This is needed to make PocketPC 2003
228 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
229 for details. JRA.
233 if (blob.length == 0 || blob.data == NULL) {
234 return data_blob_null;
237 blob_out = data_blob_talloc(ctx, NULL, 16 + blob.length);
238 if (blob_out.data == NULL) {
239 data_blob_free(&blob);
240 return data_blob_null;
243 memset(blob_out.data, '\0', 16);
245 checked_strlcpy(unix_name, lp_netbios_name(), sizeof(unix_name));
246 strlower_m(unix_name);
247 push_ascii_nstring(dos_name, unix_name);
248 strlcpy((char *)blob_out.data, dos_name, 17);
250 #ifdef DEVELOPER
251 /* Fix valgrind 'uninitialized bytes' issue. */
252 slen = strlen(dos_name);
253 if (slen < 16) {
254 memset(blob_out.data+slen, '\0', 16 - slen);
256 #endif
258 memcpy(&blob_out.data[16], blob.data, blob.length);
260 data_blob_free(&blob);
262 return blob_out;
265 /****************************************************************************
266 Reply for the nt protocol.
267 ****************************************************************************/
269 static void reply_nt1(struct smb_request *req, uint16 choice)
271 /* dual names + lock_and_read + nt SMBs + remote API calls */
272 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
273 CAP_LEVEL_II_OPLOCKS;
275 int secword=0;
276 bool negotiate_spnego = False;
277 struct timespec ts;
278 ssize_t ret;
279 struct smbd_server_connection *sconn = req->sconn;
280 bool signing_enabled = false;
281 bool signing_required = false;
283 sconn->smb1.negprot.encrypted_passwords = lp_encrypted_passwords();
285 /* Check the flags field to see if this is Vista.
286 WinXP sets it and Vista does not. But we have to
287 distinguish from NT which doesn't set it either. */
289 if ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) &&
290 ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) )
292 if (get_remote_arch() != RA_SAMBA) {
293 set_remote_arch( RA_VISTA );
297 reply_outbuf(req,17,0);
299 /* do spnego in user level security if the client
300 supports it and we can do encrypted passwords */
302 if (sconn->smb1.negprot.encrypted_passwords &&
303 lp_use_spnego() &&
304 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
305 negotiate_spnego = True;
306 capabilities |= CAP_EXTENDED_SECURITY;
307 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
308 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply
309 (already partially constructed. */
310 SSVAL(req->outbuf, smb_flg2,
311 req->flags2 | FLAGS2_EXTENDED_SECURITY);
314 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
316 if (lp_unix_extensions()) {
317 capabilities |= CAP_UNIX;
320 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
321 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
323 if (SMB_OFF_T_BITS == 64)
324 capabilities |= CAP_LARGE_FILES;
326 if (lp_readraw() && lp_writeraw())
327 capabilities |= CAP_RAW_MODE;
329 if (lp_nt_status_support())
330 capabilities |= CAP_STATUS32;
332 if (lp_host_msdfs())
333 capabilities |= CAP_DFS;
335 if (lp_security() >= SEC_USER) {
336 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
338 if (sconn->smb1.negprot.encrypted_passwords) {
339 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
342 signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state);
343 signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state);
345 if (signing_enabled) {
346 if (lp_security() >= SEC_USER) {
347 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
348 /* No raw mode with smb signing. */
349 capabilities &= ~CAP_RAW_MODE;
350 if (signing_required) {
351 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
353 } else {
354 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
355 if (signing_required) {
356 exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
361 SSVAL(req->outbuf,smb_vwv0,choice);
362 SCVAL(req->outbuf,smb_vwv1,secword);
364 smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1);
366 SSVAL(req->outbuf,smb_vwv1+1, lp_maxmux()); /* maxmpx */
367 SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */
368 SIVAL(req->outbuf,smb_vwv3+1,
369 sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */
370 SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */
371 SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */
372 SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */
373 clock_gettime(CLOCK_REALTIME,&ts);
374 put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts);
375 SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60);
377 if (!negotiate_spnego) {
378 /* Create a token value and add it to the outgoing packet. */
379 if (sconn->smb1.negprot.encrypted_passwords) {
380 uint8 chal[8];
381 /* note that we do not send a challenge at all if
382 we are using plaintext */
383 get_challenge(sconn, chal);
384 ret = message_push_blob(
385 &req->outbuf, data_blob_const(chal, sizeof(chal)));
386 if (ret == -1) {
387 DEBUG(0, ("Could not push challenge\n"));
388 reply_nterror(req, NT_STATUS_NO_MEMORY);
389 return;
391 SCVAL(req->outbuf, smb_vwv16+1, ret);
393 ret = message_push_string(&req->outbuf, lp_workgroup(),
394 STR_UNICODE|STR_TERMINATE
395 |STR_NOALIGN);
396 if (ret == -1) {
397 DEBUG(0, ("Could not push workgroup string\n"));
398 reply_nterror(req, NT_STATUS_NO_MEMORY);
399 return;
401 ret = message_push_string(&req->outbuf, lp_netbios_name(),
402 STR_UNICODE|STR_TERMINATE
403 |STR_NOALIGN);
404 if (ret == -1) {
405 DEBUG(0, ("Could not push netbios name string\n"));
406 reply_nterror(req, NT_STATUS_NO_MEMORY);
407 return;
409 DEBUG(3,("not using SPNEGO\n"));
410 } else {
411 DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn);
413 if (spnego_blob.data == NULL) {
414 reply_nterror(req, NT_STATUS_NO_MEMORY);
415 return;
418 ret = message_push_blob(&req->outbuf, spnego_blob);
419 if (ret == -1) {
420 DEBUG(0, ("Could not push spnego blob\n"));
421 reply_nterror(req, NT_STATUS_NO_MEMORY);
422 return;
424 data_blob_free(&spnego_blob);
426 SCVAL(req->outbuf,smb_vwv16+1, 0);
427 DEBUG(3,("using SPNEGO\n"));
430 return;
433 /* these are the protocol lists used for auto architecture detection:
435 WinNT 3.51:
436 protocol [PC NETWORK PROGRAM 1.0]
437 protocol [XENIX CORE]
438 protocol [MICROSOFT NETWORKS 1.03]
439 protocol [LANMAN1.0]
440 protocol [Windows for Workgroups 3.1a]
441 protocol [LM1.2X002]
442 protocol [LANMAN2.1]
443 protocol [NT LM 0.12]
445 Win95:
446 protocol [PC NETWORK PROGRAM 1.0]
447 protocol [XENIX CORE]
448 protocol [MICROSOFT NETWORKS 1.03]
449 protocol [LANMAN1.0]
450 protocol [Windows for Workgroups 3.1a]
451 protocol [LM1.2X002]
452 protocol [LANMAN2.1]
453 protocol [NT LM 0.12]
455 Win2K:
456 protocol [PC NETWORK PROGRAM 1.0]
457 protocol [LANMAN1.0]
458 protocol [Windows for Workgroups 3.1a]
459 protocol [LM1.2X002]
460 protocol [LANMAN2.1]
461 protocol [NT LM 0.12]
463 Vista:
464 protocol [PC NETWORK PROGRAM 1.0]
465 protocol [LANMAN1.0]
466 protocol [Windows for Workgroups 3.1a]
467 protocol [LM1.2X002]
468 protocol [LANMAN2.1]
469 protocol [NT LM 0.12]
470 protocol [SMB 2.001]
472 OS/2:
473 protocol [PC NETWORK PROGRAM 1.0]
474 protocol [XENIX CORE]
475 protocol [LANMAN1.0]
476 protocol [LM1.2X002]
477 protocol [LANMAN2.1]
481 * Modified to recognize the architecture of the remote machine better.
483 * This appears to be the matrix of which protocol is used by which
484 * MS product.
485 Protocol WfWg Win95 WinNT Win2K OS/2 Vista
486 PC NETWORK PROGRAM 1.0 1 1 1 1 1 1
487 XENIX CORE 2 2
488 MICROSOFT NETWORKS 3.0 2 2
489 DOS LM1.2X002 3 3
490 MICROSOFT NETWORKS 1.03 3
491 DOS LANMAN2.1 4 4
492 LANMAN1.0 4 2 3 2
493 Windows for Workgroups 3.1a 5 5 5 3 3
494 LM1.2X002 6 4 4 4
495 LANMAN2.1 7 5 5 5
496 NT LM 0.12 6 8 6 6
497 SMB 2.001 7
499 * tim@fsg.com 09/29/95
500 * Win2K added by matty 17/7/99
503 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
504 #define ARCH_WIN95 0x2
505 #define ARCH_WINNT 0x4
506 #define ARCH_WIN2K 0xC /* Win2K is like NT */
507 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
508 #define ARCH_SAMBA 0x20
509 #define ARCH_CIFSFS 0x40
510 #define ARCH_VISTA 0x8C /* Vista is like XP/2K */
512 #define ARCH_ALL 0x7F
514 /* List of supported protocols, most desired first */
515 static const struct {
516 const char *proto_name;
517 const char *short_name;
518 void (*proto_reply_fn)(struct smb_request *req, uint16 choice);
519 int protocol_level;
520 } supported_protocols[] = {
521 {"SMB 2.???", "SMB2_FF", reply_smb20ff, PROTOCOL_SMB2_10},
522 {"SMB 2.002", "SMB2_02", reply_smb2002, PROTOCOL_SMB2_02},
523 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
524 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
525 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
526 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
527 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
528 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
529 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
530 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
531 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
532 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
533 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
534 {NULL,NULL,NULL,0},
537 /****************************************************************************
538 Reply to a negprot.
539 conn POINTER CAN BE NULL HERE !
540 ****************************************************************************/
542 void reply_negprot(struct smb_request *req)
544 int choice= -1;
545 int protocol;
546 const char *p;
547 int arch = ARCH_ALL;
548 int num_cliprotos;
549 char **cliprotos;
550 int i;
551 size_t converted_size;
552 struct smbd_server_connection *sconn = req->sconn;
554 START_PROFILE(SMBnegprot);
556 if (sconn->smb1.negprot.done) {
557 END_PROFILE(SMBnegprot);
558 exit_server_cleanly("multiple negprot's are not permitted");
560 sconn->smb1.negprot.done = true;
562 if (req->buflen == 0) {
563 DEBUG(0, ("negprot got no protocols\n"));
564 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
565 END_PROFILE(SMBnegprot);
566 return;
569 if (req->buf[req->buflen-1] != '\0') {
570 DEBUG(0, ("negprot protocols not 0-terminated\n"));
571 reply_nterror(req, NT_STATUS_INVALID_PARAMETER);
572 END_PROFILE(SMBnegprot);
573 return;
576 p = (const char *)req->buf + 1;
578 num_cliprotos = 0;
579 cliprotos = NULL;
581 while (smbreq_bufrem(req, p) > 0) {
583 char **tmp;
585 tmp = talloc_realloc(talloc_tos(), cliprotos, char *,
586 num_cliprotos+1);
587 if (tmp == NULL) {
588 DEBUG(0, ("talloc failed\n"));
589 TALLOC_FREE(cliprotos);
590 reply_nterror(req, NT_STATUS_NO_MEMORY);
591 END_PROFILE(SMBnegprot);
592 return;
595 cliprotos = tmp;
597 if (!pull_ascii_talloc(cliprotos, &cliprotos[num_cliprotos], p,
598 &converted_size)) {
599 DEBUG(0, ("pull_ascii_talloc failed\n"));
600 TALLOC_FREE(cliprotos);
601 reply_nterror(req, NT_STATUS_NO_MEMORY);
602 END_PROFILE(SMBnegprot);
603 return;
606 DEBUG(3, ("Requested protocol [%s]\n",
607 cliprotos[num_cliprotos]));
609 num_cliprotos += 1;
610 p += strlen(p) + 2;
613 for (i=0; i<num_cliprotos; i++) {
614 if (strcsequal(cliprotos[i], "Windows for Workgroups 3.1a"))
615 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT
616 | ARCH_WIN2K );
617 else if (strcsequal(cliprotos[i], "DOS LM1.2X002"))
618 arch &= ( ARCH_WFWG | ARCH_WIN95 );
619 else if (strcsequal(cliprotos[i], "DOS LANMAN2.1"))
620 arch &= ( ARCH_WFWG | ARCH_WIN95 );
621 else if (strcsequal(cliprotos[i], "NT LM 0.12"))
622 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K
623 | ARCH_CIFSFS);
624 else if (strcsequal(cliprotos[i], "SMB 2.001"))
625 arch = ARCH_VISTA;
626 else if (strcsequal(cliprotos[i], "LANMAN2.1"))
627 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
628 else if (strcsequal(cliprotos[i], "LM1.2X002"))
629 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
630 else if (strcsequal(cliprotos[i], "MICROSOFT NETWORKS 1.03"))
631 arch &= ARCH_WINNT;
632 else if (strcsequal(cliprotos[i], "XENIX CORE"))
633 arch &= ( ARCH_WINNT | ARCH_OS2 );
634 else if (strcsequal(cliprotos[i], "Samba")) {
635 arch = ARCH_SAMBA;
636 break;
637 } else if (strcsequal(cliprotos[i], "POSIX 2")) {
638 arch = ARCH_CIFSFS;
639 break;
643 /* CIFSFS can send one arch only, NT LM 0.12. */
644 if (i == 1 && (arch & ARCH_CIFSFS)) {
645 arch = ARCH_CIFSFS;
648 switch ( arch ) {
649 case ARCH_CIFSFS:
650 set_remote_arch(RA_CIFSFS);
651 break;
652 case ARCH_SAMBA:
653 set_remote_arch(RA_SAMBA);
654 break;
655 case ARCH_WFWG:
656 set_remote_arch(RA_WFWG);
657 break;
658 case ARCH_WIN95:
659 set_remote_arch(RA_WIN95);
660 break;
661 case ARCH_WINNT:
662 if(req->flags2 == FLAGS2_WIN2K_SIGNATURE)
663 set_remote_arch(RA_WIN2K);
664 else
665 set_remote_arch(RA_WINNT);
666 break;
667 case ARCH_WIN2K:
668 /* Vista may have been set in the negprot so don't
669 override it here */
670 if ( get_remote_arch() != RA_VISTA )
671 set_remote_arch(RA_WIN2K);
672 break;
673 case ARCH_VISTA:
674 set_remote_arch(RA_VISTA);
675 break;
676 case ARCH_OS2:
677 set_remote_arch(RA_OS2);
678 break;
679 default:
680 set_remote_arch(RA_UNKNOWN);
681 break;
684 /* possibly reload - change of architecture */
685 reload_services(sconn, conn_snum_used, true);
687 /* moved from the netbios session setup code since we don't have that
688 when the client connects to port 445. Of course there is a small
689 window where we are listening to messages -- jerry */
691 serverid_register(messaging_server_id(sconn->msg_ctx),
692 FLAG_MSG_GENERAL|FLAG_MSG_SMBD
693 |FLAG_MSG_PRINT_GENERAL);
695 /* Check for protocols, most desirable first */
696 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
697 i = 0;
698 if ((supported_protocols[protocol].protocol_level <= lp_srv_maxprotocol()) &&
699 (supported_protocols[protocol].protocol_level >= lp_srv_minprotocol()))
700 while (i < num_cliprotos) {
701 if (strequal(cliprotos[i],supported_protocols[protocol].proto_name))
702 choice = i;
703 i++;
705 if(choice != -1)
706 break;
709 if(choice != -1) {
710 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
711 reload_services(sconn, conn_snum_used, true);
712 supported_protocols[protocol].proto_reply_fn(req, choice);
713 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
714 } else {
715 DEBUG(0,("No protocol supported !\n"));
716 reply_outbuf(req, 1, 0);
717 SSVAL(req->outbuf, smb_vwv0, choice);
720 DEBUG( 5, ( "negprot index=%d\n", choice ) );
722 if ((lp_server_signing() == SMB_SIGNING_REQUIRED)
723 && (get_Protocol() < PROTOCOL_NT1)) {
724 exit_server_cleanly("SMB signing is required and "
725 "client negotiated a downlevel protocol");
728 TALLOC_FREE(cliprotos);
730 if (lp_async_smb_echo_handler() && (get_Protocol() < PROTOCOL_SMB2_02) &&
731 !fork_echo_handler(sconn)) {
732 exit_server("Failed to fork echo handler");
735 END_PROFILE(SMBnegprot);
736 return;