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 conn POINTER CAN BE NULL HERE !
460 ****************************************************************************/
462 int reply_negprot(connection_struct *conn,
463 char *inbuf,char *outbuf, int dum_size,
466 int outsize = set_message(outbuf,1,0,True);
471 int bcc = SVAL(smb_buf(inbuf),-2);
474 static BOOL done_negprot = False;
476 START_PROFILE(SMBnegprot);
479 END_PROFILE(SMBnegprot);
480 exit_server("multiple negprot's are not permitted");
484 p = smb_buf(inbuf)+1;
485 while (p < (smb_buf(inbuf) + bcc)) {
487 DEBUG(3,("Requested protocol [%s]\n",p));
488 if (strcsequal(p,"Windows for Workgroups 3.1a"))
489 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
490 else if (strcsequal(p,"DOS LM1.2X002"))
491 arch &= ( ARCH_WFWG | ARCH_WIN95 );
492 else if (strcsequal(p,"DOS LANMAN2.1"))
493 arch &= ( ARCH_WFWG | ARCH_WIN95 );
494 else if (strcsequal(p,"NT LM 0.12"))
495 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
496 else if (strcsequal(p,"LANMAN2.1"))
497 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
498 else if (strcsequal(p,"LM1.2X002"))
499 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
500 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
502 else if (strcsequal(p,"XENIX CORE"))
503 arch &= ( ARCH_WINNT | ARCH_OS2 );
504 else if (strcsequal(p,"Samba")) {
507 } else if (strcsequal(p,"POSIX 2")) {
515 /* CIFSFS can send one arch only, NT LM 0.12. */
516 if (Index == 1 && (arch & ARCH_CIFSFS)) {
522 set_remote_arch(RA_CIFSFS);
525 set_remote_arch(RA_SAMBA);
528 set_remote_arch(RA_WFWG);
531 set_remote_arch(RA_WIN95);
534 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
535 set_remote_arch(RA_WIN2K);
537 set_remote_arch(RA_WINNT);
540 set_remote_arch(RA_WIN2K);
543 set_remote_arch(RA_OS2);
546 set_remote_arch(RA_UNKNOWN);
550 /* possibly reload - change of architecture */
551 reload_services(True);
553 /* moved from the netbios session setup code since we don't have that
554 when the client connects to port 445. Of course there is a small
555 window where we are listening to messages -- jerry */
557 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
559 /* Check for protocols, most desirable first */
560 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
561 p = smb_buf(inbuf)+1;
563 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
564 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
565 while (p < (smb_buf(inbuf) + bcc)) {
566 if (strequal(p,supported_protocols[protocol].proto_name))
575 SSVAL(outbuf,smb_vwv0,choice);
577 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
578 reload_services(True);
579 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
580 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
582 DEBUG(0,("No protocol supported !\n"));
584 SSVAL(outbuf,smb_vwv0,choice);
586 DEBUG( 5, ( "negprot index=%d\n", choice ) );
588 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
589 exit_server("SMB signing is required and client negotiated a downlevel protocol");
592 END_PROFILE(SMBnegprot);