1/*
2   Unix SMB/CIFS implementation.
3   negprot reply code
4   Copyright (C) Andrew Tridgell 1992-1998
5
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.
10
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.
15
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.
19*/
20
21#include "includes.h"
22
23extern int Protocol;
24extern int max_recv;
25BOOL global_encrypted_passwords_negotiated = False;
26BOOL global_spnego_negotiated = False;
27struct auth_context *negprot_global_auth_context = NULL;
28
29static void get_challenge(char buff[8])
30{
31	NTSTATUS nt_status;
32	const uint8 *cryptkey;
33
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);
38	}
39
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");
44	}
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);
48}
49
50/****************************************************************************
51 Reply for the core protocol.
52****************************************************************************/
53
54static int reply_corep(char *inbuf, char *outbuf)
55{
56	int outsize = set_message(outbuf,1,0,True);
57
58	Protocol = PROTOCOL_CORE;
59
60	return outsize;
61}
62
63/****************************************************************************
64 Reply for the coreplus protocol.
65****************************************************************************/
66
67static int reply_coreplus(char *inbuf, char *outbuf)
68{
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 */
76
77	Protocol = PROTOCOL_COREPLUS;
78
79	return outsize;
80}
81
82/****************************************************************************
83 Reply for the lanman 1.0 protocol.
84****************************************************************************/
85
86static int reply_lanman1(char *inbuf, char *outbuf)
87{
88	int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
89	int secword=0;
90	time_t t = time(NULL);
91
92	global_encrypted_passwords_negotiated = lp_encrypted_passwords();
93
94	if (lp_security()>=SEC_USER)
95		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
96	if (global_encrypted_passwords_negotiated)
97		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
98
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);
105	}
106
107	Protocol = PROTOCOL_LANMAN1;
108
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);
118
119	put_dos_date(outbuf,smb_vwv8,t);
120
121	return (smb_len(outbuf)+4);
122}
123
124/****************************************************************************
125 Reply for the lanman 2.0 protocol.
126****************************************************************************/
127
128static int reply_lanman2(char *inbuf, char *outbuf)
129{
130	int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
131	int secword=0;
132	time_t t = time(NULL);
133
134	global_encrypted_passwords_negotiated = lp_encrypted_passwords();
135
136	if (lp_security()>=SEC_USER)
137		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
138	if (global_encrypted_passwords_negotiated)
139		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
140
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());
144
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);
149	}
150
151	Protocol = PROTOCOL_LANMAN2;
152
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);
161
162	return (smb_len(outbuf)+4);
163}
164
165/****************************************************************************
166 Generate the spnego negprot reply blob. Return the number of bytes used.
167****************************************************************************/
168
169static int negprot_spnego(char *p)
170{
171	DATA_BLOB blob;
172	uint8 guid[17];
173	const char *OIDs_krb5[] = {OID_KERBEROS5,
174				   OID_KERBEROS5_OLD,
175				   OID_NTLMSSP,
176				   NULL};
177	const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
178	char *principal;
179	int len;
180
181	global_spnego_negotiated = True;
182
183	ZERO_STRUCT(guid);
184	safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1);
185
186#ifdef DEVELOPER
187	/* valgrind fixer... */
188	{
189		size_t sl = strlen(guid);
190		if (sizeof(guid)-sl)
191			memset(&guid[sl], '\0', sizeof(guid)-sl);
192	}
193#endif
194
195	strlower_m((char *)guid);
196
197#if 0
198	/* strangely enough, NT does not sent the single OID NTLMSSP when
199	   not a ADS member, it sends no OIDs at all
200
201	   we can't do this until we teach our sesssion setup parser to know
202	   about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
203	*/
204	if (lp_security() != SEC_ADS) {
205		memcpy(p, guid, 16);
206		return 16;
207	}
208#endif
209	if (lp_security() != SEC_ADS) {
210		blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
211	} else {
212		asprintf(&principal, "%s$@%s", guid, lp_realm());
213		blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
214		free(principal);
215	}
216	memcpy(p, blob.data, blob.length);
217	len = blob.length;
218	data_blob_free(&blob);
219	return len;
220}
221
222/****************************************************************************
223 Reply for the nt protocol.
224****************************************************************************/
225
226static int reply_nt1(char *inbuf, char *outbuf)
227{
228	/* dual names + lock_and_read + nt SMBs + remote API calls */
229	int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
230		CAP_LEVEL_II_OPLOCKS;
231
232	int secword=0;
233	time_t t = time(NULL);
234	char *p, *q;
235	BOOL negotiate_spnego = False;
236
237	global_encrypted_passwords_negotiated = lp_encrypted_passwords();
238
239	/* do spnego in user level security if the client
240	   supports it and we can do encrypted passwords */
241
242	if (global_encrypted_passwords_negotiated &&
243	    (lp_security() != SEC_SHARE) &&
244	    lp_use_spnego() &&
245	    (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
246		negotiate_spnego = True;
247		capabilities |= CAP_EXTENDED_SECURITY;
248	}
249
250	capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
251
252	if (lp_unix_extensions()) {
253		capabilities |= CAP_UNIX;
254	}
255
256	if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
257		capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
258
259	if (SMB_OFF_T_BITS == 64)
260		capabilities |= CAP_LARGE_FILES;
261
262	if (lp_readraw() && lp_writeraw())
263		capabilities |= CAP_RAW_MODE;
264
265	/* allow for disabling unicode */
266	if (lp_unicode())
267		capabilities |= CAP_UNICODE;
268
269	if (lp_nt_status_support())
270		capabilities |= CAP_STATUS32;
271
272	if (lp_host_msdfs())
273		capabilities |= CAP_DFS;
274
275	if (lp_security() >= SEC_USER)
276		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
277	if (global_encrypted_passwords_negotiated)
278		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
279
280	if (lp_server_signing()) {
281	       	if (lp_security() >= SEC_USER) {
282			secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
283			/* No raw mode with smb signing. */
284			capabilities &= ~CAP_RAW_MODE;
285			if (lp_server_signing() == Required)
286				secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
287			srv_set_signing_negotiated();
288		} else {
289			DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
290			if (lp_server_signing() == Required) {
291				exit_server("reply_nt1: smb signing required and share level security selected.");
292			}
293		}
294	}
295
296	set_message(outbuf,17,0,True);
297
298	SCVAL(outbuf,smb_vwv1,secword);
299
300	Protocol = PROTOCOL_NT1;
301
302	SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
303	SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
304	SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
305	SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
306	SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
307	SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
308	put_long_date(outbuf+smb_vwv11+1,t);
309	SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
310
311	p = q = smb_buf(outbuf);
312	if (!negotiate_spnego) {
313		/* Create a token value and add it to the outgoing packet. */
314		if (global_encrypted_passwords_negotiated) {
315			/* note that we do not send a challenge at all if
316			   we are using plaintext */
317			get_challenge(p);
318			SSVALS(outbuf,smb_vwv16+1,8);
319			p += 8;
320		}
321		p += srvstr_push(outbuf, p, lp_workgroup(), -1,
322				 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
323		DEBUG(3,("not using SPNEGO\n"));
324	} else {
325		int len = negprot_spnego(p);
326
327		SSVALS(outbuf,smb_vwv16+1,len);
328		p += len;
329		DEBUG(3,("using SPNEGO\n"));
330	}
331
332	SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
333	set_message_end(outbuf, p);
334
335	return (smb_len(outbuf)+4);
336}
337
338/* these are the protocol lists used for auto architecture detection:
339
340WinNT 3.51:
341protocol [PC NETWORK PROGRAM 1.0]
342protocol [XENIX CORE]
343protocol [MICROSOFT NETWORKS 1.03]
344protocol [LANMAN1.0]
345protocol [Windows for Workgroups 3.1a]
346protocol [LM1.2X002]
347protocol [LANMAN2.1]
348protocol [NT LM 0.12]
349
350Win95:
351protocol [PC NETWORK PROGRAM 1.0]
352protocol [XENIX CORE]
353protocol [MICROSOFT NETWORKS 1.03]
354protocol [LANMAN1.0]
355protocol [Windows for Workgroups 3.1a]
356protocol [LM1.2X002]
357protocol [LANMAN2.1]
358protocol [NT LM 0.12]
359
360Win2K:
361protocol [PC NETWORK PROGRAM 1.0]
362protocol [LANMAN1.0]
363protocol [Windows for Workgroups 3.1a]
364protocol [LM1.2X002]
365protocol [LANMAN2.1]
366protocol [NT LM 0.12]
367
368OS/2:
369protocol [PC NETWORK PROGRAM 1.0]
370protocol [XENIX CORE]
371protocol [LANMAN1.0]
372protocol [LM1.2X002]
373protocol [LANMAN2.1]
374*/
375
376/*
377  * Modified to recognize the architecture of the remote machine better.
378  *
379  * This appears to be the matrix of which protocol is used by which
380  * MS product.
381       Protocol                       WfWg    Win95   WinNT  Win2K  OS/2
382       PC NETWORK PROGRAM 1.0          1       1       1      1      1
383       XENIX CORE                                      2             2
384       MICROSOFT NETWORKS 3.0          2       2
385       DOS LM1.2X002                   3       3
386       MICROSOFT NETWORKS 1.03                         3
387       DOS LANMAN2.1                   4       4
388       LANMAN1.0                                       4      2      3
389       Windows for Workgroups 3.1a     5       5       5      3
390       LM1.2X002                                       6      4      4
391       LANMAN2.1                                       7      5      5
392       NT LM 0.12                              6       8      6
393  *
394  *  tim@fsg.com 09/29/95
395  *  Win2K added by matty 17/7/99
396  */
397
398#define ARCH_WFWG     0x3      /* This is a fudge because WfWg is like Win95 */
399#define ARCH_WIN95    0x2
400#define ARCH_WINNT    0x4
401#define ARCH_WIN2K    0xC      /* Win2K is like NT */
402#define ARCH_OS2      0x14     /* Again OS/2 is like NT */
403#define ARCH_SAMBA    0x20
404
405#define ARCH_ALL      0x3F
406
407/* List of supported protocols, most desired first */
408static const struct {
409	const char *proto_name;
410	const char *short_name;
411	int (*proto_reply_fn)(char *, char *);
412	int protocol_level;
413} supported_protocols[] = {
414	{"NT LANMAN 1.0",           "NT1",      reply_nt1,      PROTOCOL_NT1},
415	{"NT LM 0.12",              "NT1",      reply_nt1,      PROTOCOL_NT1},
416	{"LM1.2X002",               "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
417	{"Samba",                   "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
418	{"DOS LM1.2X002",           "LANMAN2",  reply_lanman2,  PROTOCOL_LANMAN2},
419	{"LANMAN1.0",               "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
420	{"MICROSOFT NETWORKS 3.0",  "LANMAN1",  reply_lanman1,  PROTOCOL_LANMAN1},
421	{"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
422	{"PC NETWORK PROGRAM 1.0",  "CORE",     reply_corep,    PROTOCOL_CORE},
423	{NULL,NULL,NULL,0},
424};
425
426/****************************************************************************
427 Reply to a negprot.
428****************************************************************************/
429
430int reply_negprot(connection_struct *conn,
431		  char *inbuf,char *outbuf, int dum_size,
432		  int dum_buffsize)
433{
434	int outsize = set_message(outbuf,1,0,True);
435	int Index=0;
436	int choice= -1;
437	int protocol;
438	char *p;
439	int bcc = SVAL(smb_buf(inbuf),-2);
440	int arch = ARCH_ALL;
441
442	static BOOL done_negprot = False;
443
444	START_PROFILE(SMBnegprot);
445
446	if (done_negprot) {
447		END_PROFILE(SMBnegprot);
448		exit_server("multiple negprot's are not permitted");
449	}
450	done_negprot = True;
451
452	p = smb_buf(inbuf)+1;
453	while (p < (smb_buf(inbuf) + bcc)) {
454		Index++;
455		DEBUG(3,("Requested protocol [%s]\n",p));
456		if (strcsequal(p,"Windows for Workgroups 3.1a"))
457			arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
458		else if (strcsequal(p,"DOS LM1.2X002"))
459			arch &= ( ARCH_WFWG | ARCH_WIN95 );
460		else if (strcsequal(p,"DOS LANMAN2.1"))
461			arch &= ( ARCH_WFWG | ARCH_WIN95 );
462		else if (strcsequal(p,"NT LM 0.12"))
463			arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
464		else if (strcsequal(p,"LANMAN2.1"))
465			arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
466		else if (strcsequal(p,"LM1.2X002"))
467			arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
468		else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
469			arch &= ARCH_WINNT;
470		else if (strcsequal(p,"XENIX CORE"))
471			arch &= ( ARCH_WINNT | ARCH_OS2 );
472		else if (strcsequal(p,"Samba")) {
473			arch = ARCH_SAMBA;
474			break;
475		}
476
477		p += strlen(p) + 2;
478	}
479
480	switch ( arch ) {
481		case ARCH_SAMBA:
482			set_remote_arch(RA_SAMBA);
483			break;
484		case ARCH_WFWG:
485			set_remote_arch(RA_WFWG);
486			break;
487		case ARCH_WIN95:
488			set_remote_arch(RA_WIN95);
489			break;
490		case ARCH_WINNT:
491			if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
492				set_remote_arch(RA_WIN2K);
493			else
494				set_remote_arch(RA_WINNT);
495			break;
496		case ARCH_WIN2K:
497			set_remote_arch(RA_WIN2K);
498			break;
499		case ARCH_OS2:
500			set_remote_arch(RA_OS2);
501			break;
502		default:
503			set_remote_arch(RA_UNKNOWN);
504		break;
505	}
506
507	/* possibly reload - change of architecture */
508	reload_services(True);
509
510	/* Check for protocols, most desirable first */
511	for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
512		p = smb_buf(inbuf)+1;
513		Index = 0;
514		if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
515				(supported_protocols[protocol].protocol_level >= lp_minprotocol()))
516			while (p < (smb_buf(inbuf) + bcc)) {
517				if (strequal(p,supported_protocols[protocol].proto_name))
518					choice = Index;
519				Index++;
520				p += strlen(p) + 2;
521			}
522		if(choice != -1)
523			break;
524	}
525
526	SSVAL(outbuf,smb_vwv0,choice);
527	if(choice != -1) {
528		extern fstring remote_proto;
529		fstrcpy(remote_proto,supported_protocols[protocol].short_name);
530		reload_services(True);
531		outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
532		DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
533	} else {
534		DEBUG(0,("No protocol supported !\n"));
535	}
536	SSVAL(outbuf,smb_vwv0,choice);
537
538	DEBUG( 5, ( "negprot index=%d\n", choice ) );
539
540	if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
541		exit_server("SMB signing is required and client negotiated a downlevel protocol");
542	}
543
544	END_PROFILE(SMBnegprot);
545	return(outsize);
546}
547