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 extern fstring global_myworkgroup;
26 extern fstring remote_machine;
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", get_nt_error_msg(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 ****************************************************************************/
55 static int reply_corep(char *inbuf, char *outbuf)
57 int outsize = set_message(outbuf,1,0,True);
59 Protocol = PROTOCOL_CORE;
65 /****************************************************************************
66 reply for the coreplus protocol
67 ****************************************************************************/
68 static int reply_coreplus(char *inbuf, char *outbuf)
70 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
71 int outsize = set_message(outbuf,13,0,True);
72 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
73 readbraw and writebraw (possibly) */
74 /* Reply, SMBlockread, SMBwritelock supported. */
75 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
76 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
78 Protocol = PROTOCOL_COREPLUS;
84 /****************************************************************************
85 reply for the lanman 1.0 protocol
86 ****************************************************************************/
87 static int reply_lanman1(char *inbuf, char *outbuf)
89 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
91 time_t t = time(NULL);
93 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
95 if (lp_security()>=SEC_USER) secword |= 1;
96 if (global_encrypted_passwords_negotiated) secword |= 2;
98 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
99 SSVAL(outbuf,smb_vwv1,secword);
100 /* Create a token value and add it to the outgoing packet. */
101 if (global_encrypted_passwords_negotiated) {
102 get_challenge(smb_buf(outbuf));
105 Protocol = PROTOCOL_LANMAN1;
107 /* Reply, SMBlockread, SMBwritelock supported. */
108 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
109 SSVAL(outbuf,smb_vwv2,max_recv);
110 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
111 SSVAL(outbuf,smb_vwv4,1);
112 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
113 readbraw writebraw (possibly) */
114 SIVAL(outbuf,smb_vwv6,sys_getpid());
115 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
117 put_dos_date(outbuf,smb_vwv8,t);
119 return (smb_len(outbuf)+4);
123 /****************************************************************************
124 reply for the lanman 2.0 protocol
125 ****************************************************************************/
126 static int reply_lanman2(char *inbuf, char *outbuf)
128 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
130 time_t t = time(NULL);
132 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
134 if (lp_security()>=SEC_USER) secword |= 1;
135 if (global_encrypted_passwords_negotiated) secword |= 2;
137 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
138 SSVAL(outbuf,smb_vwv1,secword);
139 SIVAL(outbuf,smb_vwv6,sys_getpid());
141 /* Create a token value and add it to the outgoing packet. */
142 if (global_encrypted_passwords_negotiated) {
143 get_challenge(smb_buf(outbuf));
146 Protocol = PROTOCOL_LANMAN2;
148 /* Reply, SMBlockread, SMBwritelock supported. */
149 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
150 SSVAL(outbuf,smb_vwv2,max_recv);
151 SSVAL(outbuf,smb_vwv3,lp_maxmux());
152 SSVAL(outbuf,smb_vwv4,1);
153 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
154 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
155 put_dos_date(outbuf,smb_vwv8,t);
157 return (smb_len(outbuf)+4);
163 generate the spnego negprot reply blob. Return the number of bytes used
165 static int negprot_spnego(char *p)
168 extern pstring global_myname;
170 const char *OIDs_krb5[] = {OID_NTLMSSP,
174 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
178 global_spnego_negotiated = True;
181 safe_strcpy((char *)guid, global_myname, 16);
182 strlower((char *)guid);
185 /* strangely enough, NT does not sent the single OID NTLMSSP when
186 not a ADS member, it sends no OIDs at all
188 we can't do this until we teach our sesssion setup parser to know
189 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
191 if (lp_security() != SEC_ADS) {
196 if (lp_security() != SEC_ADS) {
197 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
200 ads = ads_init(NULL, NULL, NULL, NULL);
201 /* win2000 uses host$@REALM, which we will probably use eventually,
202 but for now this works */
203 asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
204 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
208 memcpy(p, blob.data, blob.length);
210 data_blob_free(&blob);
216 /****************************************************************************
217 reply for the nt protocol
218 ****************************************************************************/
219 static int reply_nt1(char *inbuf, char *outbuf)
221 /* dual names + lock_and_read + nt SMBs + remote API calls */
222 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
223 CAP_LEVEL_II_OPLOCKS|CAP_STATUS32;
226 time_t t = time(NULL);
228 BOOL negotiate_spnego = False;
230 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
232 /* do spnego in user level security if the client
233 supports it and we can do encrypted passwords */
235 if (global_encrypted_passwords_negotiated &&
236 (lp_security() != SEC_SHARE) &&
238 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
239 negotiate_spnego = True;
240 capabilities |= CAP_EXTENDED_SECURITY;
243 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX;
245 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
246 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
249 if (SMB_OFF_T_BITS == 64) {
250 capabilities |= CAP_LARGE_FILES;
253 if (lp_readraw() && lp_writeraw()) {
254 capabilities |= CAP_RAW_MODE;
257 /* allow for disabling unicode */
259 capabilities |= CAP_UNICODE;
263 capabilities |= CAP_DFS;
265 if (lp_security() >= SEC_USER) secword |= 1;
266 if (global_encrypted_passwords_negotiated) secword |= 2;
268 set_message(outbuf,17,0,True);
270 SCVAL(outbuf,smb_vwv1,secword);
272 Protocol = PROTOCOL_NT1;
274 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
275 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
276 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
277 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
278 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
279 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
280 put_long_date(outbuf+smb_vwv11+1,t);
281 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
283 p = q = smb_buf(outbuf);
284 if (!negotiate_spnego) {
285 /* Create a token value and add it to the outgoing packet. */
286 if (global_encrypted_passwords_negotiated) {
289 SSVALS(outbuf,smb_vwv16+1,8);
291 p += srvstr_push(outbuf, p, global_myworkgroup, -1,
292 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
293 DEBUG(3,("not using SPNEGO\n"));
295 int len = negprot_spnego(p);
297 SSVALS(outbuf,smb_vwv16+1,len);
299 DEBUG(3,("using SPNEGO\n"));
302 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
303 set_message_end(outbuf, p);
305 return (smb_len(outbuf)+4);
308 /* these are the protocol lists used for auto architecture detection:
311 protocol [PC NETWORK PROGRAM 1.0]
312 protocol [XENIX CORE]
313 protocol [MICROSOFT NETWORKS 1.03]
315 protocol [Windows for Workgroups 3.1a]
318 protocol [NT LM 0.12]
321 protocol [PC NETWORK PROGRAM 1.0]
322 protocol [XENIX CORE]
323 protocol [MICROSOFT NETWORKS 1.03]
325 protocol [Windows for Workgroups 3.1a]
328 protocol [NT LM 0.12]
331 protocol [PC NETWORK PROGRAM 1.0]
333 protocol [Windows for Workgroups 3.1a]
336 protocol [NT LM 0.12]
339 protocol [PC NETWORK PROGRAM 1.0]
340 protocol [XENIX CORE]
347 * Modified to recognize the architecture of the remote machine better.
349 * This appears to be the matrix of which protocol is used by which
351 Protocol WfWg Win95 WinNT Win2K OS/2
352 PC NETWORK PROGRAM 1.0 1 1 1 1 1
354 MICROSOFT NETWORKS 3.0 2 2
356 MICROSOFT NETWORKS 1.03 3
359 Windows for Workgroups 3.1a 5 5 5 3
364 * tim@fsg.com 09/29/95
365 * Win2K added by matty 17/7/99
368 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
369 #define ARCH_WIN95 0x2
370 #define ARCH_WINNT 0x4
371 #define ARCH_WIN2K 0xC /* Win2K is like NT */
372 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
373 #define ARCH_SAMBA 0x20
375 #define ARCH_ALL 0x3F
377 /* List of supported protocols, most desired first */
381 int (*proto_reply_fn)(char *, char *);
383 } supported_protocols[] = {
384 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
385 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
386 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
387 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
388 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
389 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
390 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
391 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
392 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
397 /****************************************************************************
399 ****************************************************************************/
400 int reply_negprot(connection_struct *conn,
401 char *inbuf,char *outbuf, int dum_size,
404 int outsize = set_message(outbuf,1,0,True);
409 int bcc = SVAL(smb_buf(inbuf),-2);
411 START_PROFILE(SMBnegprot);
413 p = smb_buf(inbuf)+1;
414 while (p < (smb_buf(inbuf) + bcc))
417 DEBUG(3,("Requested protocol [%s]\n",p));
418 if (strcsequal(p,"Windows for Workgroups 3.1a"))
419 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
420 else if (strcsequal(p,"DOS LM1.2X002"))
421 arch &= ( ARCH_WFWG | ARCH_WIN95 );
422 else if (strcsequal(p,"DOS LANMAN2.1"))
423 arch &= ( ARCH_WFWG | ARCH_WIN95 );
424 else if (strcsequal(p,"NT LM 0.12"))
425 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
426 else if (strcsequal(p,"LANMAN2.1"))
427 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
428 else if (strcsequal(p,"LM1.2X002"))
429 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
430 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
432 else if (strcsequal(p,"XENIX CORE"))
433 arch &= ( ARCH_WINNT | ARCH_OS2 );
434 else if (strcsequal(p,"Samba")) {
444 set_remote_arch(RA_SAMBA);
447 set_remote_arch(RA_WFWG);
450 set_remote_arch(RA_WIN95);
453 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
454 set_remote_arch(RA_WIN2K);
456 set_remote_arch(RA_WINNT);
459 set_remote_arch(RA_WIN2K);
462 set_remote_arch(RA_OS2);
465 set_remote_arch(RA_UNKNOWN);
469 /* possibly reload - change of architecture */
470 reload_services(True);
472 /* Check for protocols, most desirable first */
473 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
475 p = smb_buf(inbuf)+1;
477 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
478 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
479 while (p < (smb_buf(inbuf) + bcc))
481 if (strequal(p,supported_protocols[protocol].proto_name))
490 SSVAL(outbuf,smb_vwv0,choice);
492 extern fstring remote_proto;
493 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
494 reload_services(True);
495 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
496 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
499 DEBUG(0,("No protocol supported !\n"));
501 SSVAL(outbuf,smb_vwv0,choice);
503 DEBUG( 5, ( "negprot index=%d\n", choice ) );
505 END_PROFILE(SMBnegprot);