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.
25 BOOL global_encrypted_passwords_negotiated = False;
26 BOOL global_spnego_negotiated = False;
27 struct auth_context *negprot_global_auth_context = NULL;
29 static void get_challenge(char buff[8])
32 const uint8 *cryptkey;
34 /* We might be called more than once, muliple negprots are premitted */
35 if (negprot_global_auth_context) {
36 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
37 (negprot_global_auth_context->free)(&negprot_global_auth_context);
40 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
41 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
42 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
43 smb_panic("cannot make_negprot_global_auth_context!\n");
45 DEBUG(10, ("get challenge: getting challenge\n"));
46 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
47 memcpy(buff, cryptkey, 8);
50 /****************************************************************************
51 Reply for the core protocol.
52 ****************************************************************************/
54 static int reply_corep(char *inbuf, char *outbuf)
56 int outsize = set_message(outbuf,1,0,True);
58 Protocol = PROTOCOL_CORE;
63 /****************************************************************************
64 Reply for the coreplus protocol.
65 ****************************************************************************/
67 static int reply_coreplus(char *inbuf, char *outbuf)
69 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
70 int outsize = set_message(outbuf,13,0,True);
71 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
72 readbraw and writebraw (possibly) */
73 /* Reply, SMBlockread, SMBwritelock supported. */
74 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
75 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
77 Protocol = PROTOCOL_COREPLUS;
82 /****************************************************************************
83 Reply for the lanman 1.0 protocol.
84 ****************************************************************************/
86 static int reply_lanman1(char *inbuf, char *outbuf)
88 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
90 time_t t = time(NULL);
92 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
94 if (lp_security()>=SEC_USER)
95 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
96 if (global_encrypted_passwords_negotiated)
97 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
99 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
100 SSVAL(outbuf,smb_vwv1,secword);
101 /* Create a token value and add it to the outgoing packet. */
102 if (global_encrypted_passwords_negotiated) {
103 get_challenge(smb_buf(outbuf));
104 SSVAL(outbuf,smb_vwv11, 8);
107 Protocol = PROTOCOL_LANMAN1;
109 /* Reply, SMBlockread, SMBwritelock supported. */
110 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
111 SSVAL(outbuf,smb_vwv2,max_recv);
112 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
113 SSVAL(outbuf,smb_vwv4,1);
114 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
115 readbraw writebraw (possibly) */
116 SIVAL(outbuf,smb_vwv6,sys_getpid());
117 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
119 put_dos_date(outbuf,smb_vwv8,t);
121 return (smb_len(outbuf)+4);
124 /****************************************************************************
125 Reply for the lanman 2.0 protocol.
126 ****************************************************************************/
128 static int reply_lanman2(char *inbuf, char *outbuf)
130 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
132 time_t t = time(NULL);
134 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
136 if (lp_security()>=SEC_USER)
137 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
138 if (global_encrypted_passwords_negotiated)
139 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
141 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
142 SSVAL(outbuf,smb_vwv1,secword);
143 SIVAL(outbuf,smb_vwv6,sys_getpid());
145 /* Create a token value and add it to the outgoing packet. */
146 if (global_encrypted_passwords_negotiated) {
147 get_challenge(smb_buf(outbuf));
148 SSVAL(outbuf,smb_vwv11, 8);
151 Protocol = PROTOCOL_LANMAN2;
153 /* Reply, SMBlockread, SMBwritelock supported. */
154 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
155 SSVAL(outbuf,smb_vwv2,max_recv);
156 SSVAL(outbuf,smb_vwv3,lp_maxmux());
157 SSVAL(outbuf,smb_vwv4,1);
158 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
159 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
160 put_dos_date(outbuf,smb_vwv8,t);
162 return (smb_len(outbuf)+4);
165 /****************************************************************************
166 Generate the spnego negprot reply blob. Return the number of bytes used.
167 ****************************************************************************/
169 static int negprot_spnego(char *p)
175 const char *OIDs_krb5[] = {OID_KERBEROS5,
179 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
183 global_spnego_negotiated = True;
187 safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
188 strlower_m(unix_name);
189 push_ascii_nstring(dos_name, unix_name);
190 safe_strcpy((char *)guid, dos_name, sizeof(guid)-1);
193 /* valgrind fixer... */
195 size_t sl = strlen(guid);
197 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 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 if (lp_security() != SEC_ADS) {
213 if (lp_security() != SEC_ADS) {
214 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
216 asprintf(&principal, "%s$@%s", guid, lp_realm());
217 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
220 memcpy(p, blob.data, blob.length);
222 data_blob_free(&blob);
226 /****************************************************************************
227 Reply for the nt protocol.
228 ****************************************************************************/
230 static int reply_nt1(char *inbuf, char *outbuf)
232 /* dual names + lock_and_read + nt SMBs + remote API calls */
233 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
234 CAP_LEVEL_II_OPLOCKS;
237 time_t t = time(NULL);
239 BOOL negotiate_spnego = False;
241 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
243 /* do spnego in user level security if the client
244 supports it and we can do encrypted passwords */
246 if (global_encrypted_passwords_negotiated &&
247 (lp_security() != SEC_SHARE) &&
249 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
250 negotiate_spnego = True;
251 capabilities |= CAP_EXTENDED_SECURITY;
254 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
256 if (lp_unix_extensions()) {
257 capabilities |= CAP_UNIX;
260 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
261 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
263 if (SMB_OFF_T_BITS == 64)
264 capabilities |= CAP_LARGE_FILES;
266 if (lp_readraw() && lp_writeraw())
267 capabilities |= CAP_RAW_MODE;
269 /* allow for disabling unicode */
271 capabilities |= CAP_UNICODE;
273 if (lp_nt_status_support())
274 capabilities |= CAP_STATUS32;
277 capabilities |= CAP_DFS;
279 if (lp_security() >= SEC_USER)
280 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
281 if (global_encrypted_passwords_negotiated)
282 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
284 if (lp_server_signing()) {
285 if (lp_security() >= SEC_USER) {
286 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
287 /* No raw mode with smb signing. */
288 capabilities &= ~CAP_RAW_MODE;
289 if (lp_server_signing() == Required)
290 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
291 srv_set_signing_negotiated();
293 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
294 if (lp_server_signing() == Required) {
295 exit_server("reply_nt1: smb signing required and share level security selected.");
300 set_message(outbuf,17,0,True);
302 SCVAL(outbuf,smb_vwv1,secword);
304 Protocol = PROTOCOL_NT1;
306 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
307 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
308 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
309 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
310 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
311 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
312 put_long_date(outbuf+smb_vwv11+1,t);
313 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
315 p = q = smb_buf(outbuf);
316 if (!negotiate_spnego) {
317 /* Create a token value and add it to the outgoing packet. */
318 if (global_encrypted_passwords_negotiated) {
319 /* note that we do not send a challenge at all if
320 we are using plaintext */
322 SSVALS(outbuf,smb_vwv16+1,8);
325 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
326 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
327 DEBUG(3,("not using SPNEGO\n"));
329 int len = negprot_spnego(p);
331 SSVALS(outbuf,smb_vwv16+1,len);
333 DEBUG(3,("using SPNEGO\n"));
336 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
337 set_message_end(outbuf, p);
339 return (smb_len(outbuf)+4);
342 /* these are the protocol lists used for auto architecture detection:
345 protocol [PC NETWORK PROGRAM 1.0]
346 protocol [XENIX CORE]
347 protocol [MICROSOFT NETWORKS 1.03]
349 protocol [Windows for Workgroups 3.1a]
352 protocol [NT LM 0.12]
355 protocol [PC NETWORK PROGRAM 1.0]
356 protocol [XENIX CORE]
357 protocol [MICROSOFT NETWORKS 1.03]
359 protocol [Windows for Workgroups 3.1a]
362 protocol [NT LM 0.12]
365 protocol [PC NETWORK PROGRAM 1.0]
367 protocol [Windows for Workgroups 3.1a]
370 protocol [NT LM 0.12]
373 protocol [PC NETWORK PROGRAM 1.0]
374 protocol [XENIX CORE]
381 * Modified to recognize the architecture of the remote machine better.
383 * This appears to be the matrix of which protocol is used by which
385 Protocol WfWg Win95 WinNT Win2K OS/2
386 PC NETWORK PROGRAM 1.0 1 1 1 1 1
388 MICROSOFT NETWORKS 3.0 2 2
390 MICROSOFT NETWORKS 1.03 3
393 Windows for Workgroups 3.1a 5 5 5 3
398 * tim@fsg.com 09/29/95
399 * Win2K added by matty 17/7/99
402 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
403 #define ARCH_WIN95 0x2
404 #define ARCH_WINNT 0x4
405 #define ARCH_WIN2K 0xC /* Win2K is like NT */
406 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
407 #define ARCH_SAMBA 0x20
409 #define ARCH_ALL 0x3F
411 /* List of supported protocols, most desired first */
412 static const struct {
413 const char *proto_name;
414 const char *short_name;
415 int (*proto_reply_fn)(char *, char *);
417 } supported_protocols[] = {
418 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
419 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
420 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
421 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
422 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
423 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
424 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
425 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
426 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
430 /****************************************************************************
432 ****************************************************************************/
434 int reply_negprot(connection_struct *conn,
435 char *inbuf,char *outbuf, int dum_size,
438 int outsize = set_message(outbuf,1,0,True);
443 int bcc = SVAL(smb_buf(inbuf),-2);
446 static BOOL done_negprot = False;
448 START_PROFILE(SMBnegprot);
451 END_PROFILE(SMBnegprot);
452 exit_server("multiple negprot's are not permitted");
456 p = smb_buf(inbuf)+1;
457 while (p < (smb_buf(inbuf) + bcc)) {
459 DEBUG(3,("Requested protocol [%s]\n",p));
460 if (strcsequal(p,"Windows for Workgroups 3.1a"))
461 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
462 else if (strcsequal(p,"DOS LM1.2X002"))
463 arch &= ( ARCH_WFWG | ARCH_WIN95 );
464 else if (strcsequal(p,"DOS LANMAN2.1"))
465 arch &= ( ARCH_WFWG | ARCH_WIN95 );
466 else if (strcsequal(p,"NT LM 0.12"))
467 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
468 else if (strcsequal(p,"LANMAN2.1"))
469 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
470 else if (strcsequal(p,"LM1.2X002"))
471 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
472 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
474 else if (strcsequal(p,"XENIX CORE"))
475 arch &= ( ARCH_WINNT | ARCH_OS2 );
476 else if (strcsequal(p,"Samba")) {
486 set_remote_arch(RA_SAMBA);
489 set_remote_arch(RA_WFWG);
492 set_remote_arch(RA_WIN95);
495 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
496 set_remote_arch(RA_WIN2K);
498 set_remote_arch(RA_WINNT);
501 set_remote_arch(RA_WIN2K);
504 set_remote_arch(RA_OS2);
507 set_remote_arch(RA_UNKNOWN);
511 /* possibly reload - change of architecture */
512 reload_services(True);
514 /* Check for protocols, most desirable first */
515 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
516 p = smb_buf(inbuf)+1;
518 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
519 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
520 while (p < (smb_buf(inbuf) + bcc)) {
521 if (strequal(p,supported_protocols[protocol].proto_name))
530 SSVAL(outbuf,smb_vwv0,choice);
532 extern fstring remote_proto;
533 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
534 reload_services(True);
535 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
536 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
538 DEBUG(0,("No protocol supported !\n"));
540 SSVAL(outbuf,smb_vwv0,choice);
542 DEBUG( 5, ( "negprot index=%d\n", choice ) );
544 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
545 exit_server("SMB signing is required and client negotiated a downlevel protocol");
548 END_PROFILE(SMBnegprot);