2 Unix SMB/CIFS implementation.
4 Copyright (C) Andrew Tridgell 1992-1998
6 This program is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with this program; if not, write to the Free Software
18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
23 extern fstring remote_proto;
24 extern enum protocol_types Protocol;
27 BOOL global_encrypted_passwords_negotiated = False;
28 BOOL global_spnego_negotiated = False;
29 struct auth_context *negprot_global_auth_context = NULL;
31 static void get_challenge(char buff[8])
34 const uint8 *cryptkey;
36 /* We might be called more than once, muliple negprots are premitted */
37 if (negprot_global_auth_context) {
38 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
39 (negprot_global_auth_context->free)(&negprot_global_auth_context);
42 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
43 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
44 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
45 smb_panic("cannot make_negprot_global_auth_context!\n");
47 DEBUG(10, ("get challenge: getting challenge\n"));
48 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
49 memcpy(buff, cryptkey, 8);
52 /****************************************************************************
53 Reply for the core protocol.
54 ****************************************************************************/
56 static int reply_corep(char *inbuf, char *outbuf)
58 int outsize = set_message(outbuf,1,0,True);
60 Protocol = PROTOCOL_CORE;
65 /****************************************************************************
66 Reply for the coreplus protocol.
67 ****************************************************************************/
69 static int reply_coreplus(char *inbuf, char *outbuf)
71 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
72 int outsize = set_message(outbuf,13,0,True);
73 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
74 readbraw and writebraw (possibly) */
75 /* Reply, SMBlockread, SMBwritelock supported. */
76 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
77 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
79 Protocol = PROTOCOL_COREPLUS;
84 /****************************************************************************
85 Reply for the lanman 1.0 protocol.
86 ****************************************************************************/
88 static int reply_lanman1(char *inbuf, char *outbuf)
90 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
92 time_t t = time(NULL);
94 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
96 if (lp_security()>=SEC_USER)
97 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
98 if (global_encrypted_passwords_negotiated)
99 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
101 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
102 SSVAL(outbuf,smb_vwv1,secword);
103 /* Create a token value and add it to the outgoing packet. */
104 if (global_encrypted_passwords_negotiated) {
105 get_challenge(smb_buf(outbuf));
106 SSVAL(outbuf,smb_vwv11, 8);
109 Protocol = PROTOCOL_LANMAN1;
111 /* Reply, SMBlockread, SMBwritelock supported. */
112 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
113 SSVAL(outbuf,smb_vwv2,max_recv);
114 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
115 SSVAL(outbuf,smb_vwv4,1);
116 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
117 readbraw writebraw (possibly) */
118 SIVAL(outbuf,smb_vwv6,sys_getpid());
119 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
121 srv_put_dos_date(outbuf,smb_vwv8,t);
123 return (smb_len(outbuf)+4);
126 /****************************************************************************
127 Reply for the lanman 2.0 protocol.
128 ****************************************************************************/
130 static int reply_lanman2(char *inbuf, char *outbuf)
132 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
134 time_t t = time(NULL);
136 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
138 if (lp_security()>=SEC_USER)
139 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
140 if (global_encrypted_passwords_negotiated)
141 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
143 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
144 SSVAL(outbuf,smb_vwv1,secword);
145 SIVAL(outbuf,smb_vwv6,sys_getpid());
147 /* Create a token value and add it to the outgoing packet. */
148 if (global_encrypted_passwords_negotiated) {
149 get_challenge(smb_buf(outbuf));
150 SSVAL(outbuf,smb_vwv11, 8);
153 Protocol = PROTOCOL_LANMAN2;
155 /* Reply, SMBlockread, SMBwritelock supported. */
156 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
157 SSVAL(outbuf,smb_vwv2,max_recv);
158 SSVAL(outbuf,smb_vwv3,lp_maxmux());
159 SSVAL(outbuf,smb_vwv4,1);
160 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
161 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
162 srv_put_dos_date(outbuf,smb_vwv8,t);
164 return (smb_len(outbuf)+4);
167 /****************************************************************************
168 Generate the spnego negprot reply blob. Return the number of bytes used.
169 ****************************************************************************/
171 static int negprot_spnego(char *p, uint8 *pkeylen)
177 const char *OIDs_krb5[] = {OID_KERBEROS5,
181 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
184 global_spnego_negotiated = True;
188 safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
189 strlower_m(unix_name);
190 push_ascii_nstring(dos_name, unix_name);
191 safe_strcpy(guid, dos_name, sizeof(guid)-1);
194 /* valgrind fixer... */
196 size_t sl = strlen(guid);
198 memset(&guid[sl], '\0', sizeof(guid)-sl);
202 /* strangely enough, NT does not sent the single OID NTLMSSP when
203 not a ADS member, it sends no OIDs at all
205 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
206 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
208 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
209 back to doing what W2K3 does here. This is needed to make PocketPC 2003
210 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
215 if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
217 /* Code for PocketPC client */
218 blob = data_blob(guid, 16);
220 /* Code for standalone WXP client */
221 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
225 char *host_princ_s = NULL;
226 name_to_fqdn(myname, global_myname());
228 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
229 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
230 SAFE_FREE(host_princ_s);
233 memcpy(p, blob.data, blob.length);
236 DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len));
239 data_blob_free(&blob);
241 if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
249 /****************************************************************************
250 Reply for the nt protocol.
251 ****************************************************************************/
253 static int reply_nt1(char *inbuf, char *outbuf)
255 /* dual names + lock_and_read + nt SMBs + remote API calls */
256 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
257 CAP_LEVEL_II_OPLOCKS;
261 BOOL negotiate_spnego = False;
262 time_t t = time(NULL);
264 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
266 /* do spnego in user level security if the client
267 supports it and we can do encrypted passwords */
269 if (global_encrypted_passwords_negotiated &&
270 (lp_security() != SEC_SHARE) &&
272 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
273 negotiate_spnego = True;
274 capabilities |= CAP_EXTENDED_SECURITY;
275 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
276 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
277 partially constructed. */
278 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
281 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
283 if (lp_unix_extensions()) {
284 capabilities |= CAP_UNIX;
287 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
288 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
290 if (SMB_OFF_T_BITS == 64)
291 capabilities |= CAP_LARGE_FILES;
293 if (lp_readraw() && lp_writeraw())
294 capabilities |= CAP_RAW_MODE;
296 if (lp_nt_status_support())
297 capabilities |= CAP_STATUS32;
300 capabilities |= CAP_DFS;
302 if (lp_security() >= SEC_USER)
303 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
304 if (global_encrypted_passwords_negotiated)
305 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
307 if (lp_server_signing()) {
308 if (lp_security() >= SEC_USER) {
309 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
310 /* No raw mode with smb signing. */
311 capabilities &= ~CAP_RAW_MODE;
312 if (lp_server_signing() == Required)
313 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
314 srv_set_signing_negotiated();
316 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
317 if (lp_server_signing() == Required) {
318 exit_server("reply_nt1: smb signing required and share level security selected.");
323 set_message(outbuf,17,0,True);
325 SCVAL(outbuf,smb_vwv1,secword);
327 Protocol = PROTOCOL_NT1;
329 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
330 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
331 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
332 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
333 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
334 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
335 put_long_date(outbuf+smb_vwv11+1,t);
336 SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
338 p = q = smb_buf(outbuf);
339 if (!negotiate_spnego) {
340 /* Create a token value and add it to the outgoing packet. */
341 if (global_encrypted_passwords_negotiated) {
342 /* note that we do not send a challenge at all if
343 we are using plaintext */
345 SCVAL(outbuf,smb_vwv16+1,8);
348 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
349 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
350 DEBUG(3,("not using SPNEGO\n"));
353 int len = negprot_spnego(p, &keylen);
355 SCVAL(outbuf,smb_vwv16+1,keylen);
357 DEBUG(3,("using SPNEGO\n"));
360 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
361 set_message_end(outbuf, p);
363 return (smb_len(outbuf)+4);
366 /* these are the protocol lists used for auto architecture detection:
369 protocol [PC NETWORK PROGRAM 1.0]
370 protocol [XENIX CORE]
371 protocol [MICROSOFT NETWORKS 1.03]
373 protocol [Windows for Workgroups 3.1a]
376 protocol [NT LM 0.12]
379 protocol [PC NETWORK PROGRAM 1.0]
380 protocol [XENIX CORE]
381 protocol [MICROSOFT NETWORKS 1.03]
383 protocol [Windows for Workgroups 3.1a]
386 protocol [NT LM 0.12]
389 protocol [PC NETWORK PROGRAM 1.0]
391 protocol [Windows for Workgroups 3.1a]
394 protocol [NT LM 0.12]
397 protocol [PC NETWORK PROGRAM 1.0]
398 protocol [XENIX CORE]
405 * Modified to recognize the architecture of the remote machine better.
407 * This appears to be the matrix of which protocol is used by which
409 Protocol WfWg Win95 WinNT Win2K OS/2
410 PC NETWORK PROGRAM 1.0 1 1 1 1 1
412 MICROSOFT NETWORKS 3.0 2 2
414 MICROSOFT NETWORKS 1.03 3
417 Windows for Workgroups 3.1a 5 5 5 3
422 * tim@fsg.com 09/29/95
423 * Win2K added by matty 17/7/99
426 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
427 #define ARCH_WIN95 0x2
428 #define ARCH_WINNT 0x4
429 #define ARCH_WIN2K 0xC /* Win2K is like NT */
430 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
431 #define ARCH_SAMBA 0x20
432 #define ARCH_CIFSFS 0x40
434 #define ARCH_ALL 0x7F
436 /* List of supported protocols, most desired first */
437 static const struct {
438 const char *proto_name;
439 const char *short_name;
440 int (*proto_reply_fn)(char *, char *);
442 } supported_protocols[] = {
443 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
444 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
445 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
446 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
447 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
448 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
449 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
450 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
451 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
452 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
453 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
457 /****************************************************************************
459 ****************************************************************************/
461 int reply_negprot(connection_struct *conn,
462 char *inbuf,char *outbuf, int dum_size,
465 int outsize = set_message(outbuf,1,0,True);
470 int bcc = SVAL(smb_buf(inbuf),-2);
473 static BOOL done_negprot = False;
475 START_PROFILE(SMBnegprot);
478 END_PROFILE(SMBnegprot);
479 exit_server("multiple negprot's are not permitted");
483 p = smb_buf(inbuf)+1;
484 while (p < (smb_buf(inbuf) + bcc)) {
486 DEBUG(3,("Requested protocol [%s]\n",p));
487 if (strcsequal(p,"Windows for Workgroups 3.1a"))
488 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
489 else if (strcsequal(p,"DOS LM1.2X002"))
490 arch &= ( ARCH_WFWG | ARCH_WIN95 );
491 else if (strcsequal(p,"DOS LANMAN2.1"))
492 arch &= ( ARCH_WFWG | ARCH_WIN95 );
493 else if (strcsequal(p,"NT LM 0.12"))
494 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
495 else if (strcsequal(p,"LANMAN2.1"))
496 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
497 else if (strcsequal(p,"LM1.2X002"))
498 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
499 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
501 else if (strcsequal(p,"XENIX CORE"))
502 arch &= ( ARCH_WINNT | ARCH_OS2 );
503 else if (strcsequal(p,"Samba")) {
506 } else if (strcsequal(p,"POSIX 2")) {
514 /* CIFSFS can send one arch only, NT LM 0.12. */
515 if (Index == 1 && (arch & ARCH_CIFSFS)) {
521 set_remote_arch(RA_CIFSFS);
524 set_remote_arch(RA_SAMBA);
527 set_remote_arch(RA_WFWG);
530 set_remote_arch(RA_WIN95);
533 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
534 set_remote_arch(RA_WIN2K);
536 set_remote_arch(RA_WINNT);
539 set_remote_arch(RA_WIN2K);
542 set_remote_arch(RA_OS2);
545 set_remote_arch(RA_UNKNOWN);
549 /* possibly reload - change of architecture */
550 reload_services(True);
552 /* moved from the netbios session setup code since we don't have that
553 when the client connects to port 445. Of course there is a small
554 window where we are listening to messages -- jerry */
556 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
558 /* Check for protocols, most desirable first */
559 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
560 p = smb_buf(inbuf)+1;
562 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
563 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
564 while (p < (smb_buf(inbuf) + bcc)) {
565 if (strequal(p,supported_protocols[protocol].proto_name))
574 SSVAL(outbuf,smb_vwv0,choice);
576 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
577 reload_services(True);
578 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
579 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
581 DEBUG(0,("No protocol supported !\n"));
583 SSVAL(outbuf,smb_vwv0,choice);
585 DEBUG( 5, ( "negprot index=%d\n", choice ) );
587 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
588 exit_server("SMB signing is required and client negotiated a downlevel protocol");
591 END_PROFILE(SMBnegprot);