Removed version number from file header.
[Samba/ekacnet.git] / source / smbd / negprot.c
blob073edd70db4600c2a563a684696cae49dae797fe
1 /*
2 Unix SMB/CIFS implementation.
3 negprot reply code
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.
21 #include "includes.h"
23 extern int Protocol;
24 extern int max_recv;
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])
33 NTSTATUS nt_status;
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;
61 return outsize;
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;
80 return outsize;
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);
90 int secword=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);
129 int secword=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)
167 DATA_BLOB blob;
168 extern pstring global_myname;
169 uint8 guid[16];
170 const char *OIDs_krb5[] = {OID_NTLMSSP,
171 OID_KERBEROS5,
172 OID_KERBEROS5_OLD,
173 NULL};
174 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
175 char *principal;
176 int len;
178 global_spnego_negotiated = True;
180 memset(guid, 0, 16);
181 safe_strcpy((char *)guid, global_myname, 16);
182 strlower((char *)guid);
184 #if 0
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) {
192 memcpy(p, guid, 16);
193 return 16;
195 #endif
197 ADS_STRUCT *ads;
198 ads = ads_init(NULL, NULL, NULL, NULL);
200 /* win2000 uses host$@REALM, which we will probably use eventually,
201 but for now this works */
202 asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
203 blob = spnego_gen_negTokenInit(guid,
204 lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain,
205 principal);
206 free(principal);
207 ads_destroy(&ads);
209 memcpy(p, blob.data, blob.length);
210 len = blob.length;
211 data_blob_free(&blob);
212 return len;
217 /****************************************************************************
218 reply for the nt protocol
219 ****************************************************************************/
220 static int reply_nt1(char *inbuf, char *outbuf)
222 /* dual names + lock_and_read + nt SMBs + remote API calls */
223 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
224 CAP_LEVEL_II_OPLOCKS|CAP_STATUS32;
226 int secword=0;
227 time_t t = time(NULL);
228 char *p, *q;
229 BOOL negotiate_spnego = False;
231 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
233 /* do spnego in user level security if the client
234 supports it and we can do encrypted passwords */
236 if (global_encrypted_passwords_negotiated &&
237 (lp_security() != SEC_SHARE) &&
238 lp_use_spnego() &&
239 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
240 negotiate_spnego = True;
241 capabilities |= CAP_EXTENDED_SECURITY;
244 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX;
246 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
247 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
250 if (SMB_OFF_T_BITS == 64) {
251 capabilities |= CAP_LARGE_FILES;
254 if (lp_readraw() && lp_writeraw()) {
255 capabilities |= CAP_RAW_MODE;
258 /* allow for disabling unicode */
259 if (lp_unicode()) {
260 capabilities |= CAP_UNICODE;
263 if (lp_host_msdfs())
264 capabilities |= CAP_DFS;
266 if (lp_security() >= SEC_USER) secword |= 1;
267 if (global_encrypted_passwords_negotiated) secword |= 2;
269 set_message(outbuf,17,0,True);
271 SCVAL(outbuf,smb_vwv1,secword);
273 Protocol = PROTOCOL_NT1;
275 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
276 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
277 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
278 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
279 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
280 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
281 put_long_date(outbuf+smb_vwv11+1,t);
282 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
284 p = q = smb_buf(outbuf);
285 if (!negotiate_spnego) {
286 /* Create a token value and add it to the outgoing packet. */
287 if (global_encrypted_passwords_negotiated) {
288 get_challenge(p);
290 SSVALS(outbuf,smb_vwv16+1,8);
291 p += 8;
292 p += srvstr_push(outbuf, p, global_myworkgroup, -1,
293 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
294 DEBUG(3,("not using SPNEGO\n"));
295 } else {
296 int len = negprot_spnego(p);
298 SSVALS(outbuf,smb_vwv16+1,len);
299 p += len;
300 DEBUG(3,("using SPNEGO\n"));
303 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
304 set_message_end(outbuf, p);
306 return (smb_len(outbuf)+4);
309 /* these are the protocol lists used for auto architecture detection:
311 WinNT 3.51:
312 protocol [PC NETWORK PROGRAM 1.0]
313 protocol [XENIX CORE]
314 protocol [MICROSOFT NETWORKS 1.03]
315 protocol [LANMAN1.0]
316 protocol [Windows for Workgroups 3.1a]
317 protocol [LM1.2X002]
318 protocol [LANMAN2.1]
319 protocol [NT LM 0.12]
321 Win95:
322 protocol [PC NETWORK PROGRAM 1.0]
323 protocol [XENIX CORE]
324 protocol [MICROSOFT NETWORKS 1.03]
325 protocol [LANMAN1.0]
326 protocol [Windows for Workgroups 3.1a]
327 protocol [LM1.2X002]
328 protocol [LANMAN2.1]
329 protocol [NT LM 0.12]
331 Win2K:
332 protocol [PC NETWORK PROGRAM 1.0]
333 protocol [LANMAN1.0]
334 protocol [Windows for Workgroups 3.1a]
335 protocol [LM1.2X002]
336 protocol [LANMAN2.1]
337 protocol [NT LM 0.12]
339 OS/2:
340 protocol [PC NETWORK PROGRAM 1.0]
341 protocol [XENIX CORE]
342 protocol [LANMAN1.0]
343 protocol [LM1.2X002]
344 protocol [LANMAN2.1]
348 * Modified to recognize the architecture of the remote machine better.
350 * This appears to be the matrix of which protocol is used by which
351 * MS product.
352 Protocol WfWg Win95 WinNT Win2K OS/2
353 PC NETWORK PROGRAM 1.0 1 1 1 1 1
354 XENIX CORE 2 2
355 MICROSOFT NETWORKS 3.0 2 2
356 DOS LM1.2X002 3 3
357 MICROSOFT NETWORKS 1.03 3
358 DOS LANMAN2.1 4 4
359 LANMAN1.0 4 2 3
360 Windows for Workgroups 3.1a 5 5 5 3
361 LM1.2X002 6 4 4
362 LANMAN2.1 7 5 5
363 NT LM 0.12 6 8 6
365 * tim@fsg.com 09/29/95
366 * Win2K added by matty 17/7/99
369 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
370 #define ARCH_WIN95 0x2
371 #define ARCH_WINNT 0x4
372 #define ARCH_WIN2K 0xC /* Win2K is like NT */
373 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
374 #define ARCH_SAMBA 0x20
376 #define ARCH_ALL 0x3F
378 /* List of supported protocols, most desired first */
379 static struct {
380 char *proto_name;
381 char *short_name;
382 int (*proto_reply_fn)(char *, char *);
383 int protocol_level;
384 } supported_protocols[] = {
385 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
386 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
387 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
388 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
389 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
390 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
391 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
392 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
393 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
394 {NULL,NULL,NULL,0},
398 /****************************************************************************
399 reply to a negprot
400 ****************************************************************************/
401 int reply_negprot(connection_struct *conn,
402 char *inbuf,char *outbuf, int dum_size,
403 int dum_buffsize)
405 int outsize = set_message(outbuf,1,0,True);
406 int Index=0;
407 int choice= -1;
408 int protocol;
409 char *p;
410 int bcc = SVAL(smb_buf(inbuf),-2);
411 int arch = ARCH_ALL;
412 START_PROFILE(SMBnegprot);
414 p = smb_buf(inbuf)+1;
415 while (p < (smb_buf(inbuf) + bcc))
417 Index++;
418 DEBUG(3,("Requested protocol [%s]\n",p));
419 if (strcsequal(p,"Windows for Workgroups 3.1a"))
420 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
421 else if (strcsequal(p,"DOS LM1.2X002"))
422 arch &= ( ARCH_WFWG | ARCH_WIN95 );
423 else if (strcsequal(p,"DOS LANMAN2.1"))
424 arch &= ( ARCH_WFWG | ARCH_WIN95 );
425 else if (strcsequal(p,"NT LM 0.12"))
426 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
427 else if (strcsequal(p,"LANMAN2.1"))
428 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
429 else if (strcsequal(p,"LM1.2X002"))
430 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
431 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
432 arch &= ARCH_WINNT;
433 else if (strcsequal(p,"XENIX CORE"))
434 arch &= ( ARCH_WINNT | ARCH_OS2 );
435 else if (strcsequal(p,"Samba")) {
436 arch = ARCH_SAMBA;
437 break;
440 p += strlen(p) + 2;
443 switch ( arch ) {
444 case ARCH_SAMBA:
445 set_remote_arch(RA_SAMBA);
446 break;
447 case ARCH_WFWG:
448 set_remote_arch(RA_WFWG);
449 break;
450 case ARCH_WIN95:
451 set_remote_arch(RA_WIN95);
452 break;
453 case ARCH_WINNT:
454 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
455 set_remote_arch(RA_WIN2K);
456 else
457 set_remote_arch(RA_WINNT);
458 break;
459 case ARCH_WIN2K:
460 set_remote_arch(RA_WIN2K);
461 break;
462 case ARCH_OS2:
463 set_remote_arch(RA_OS2);
464 break;
465 default:
466 set_remote_arch(RA_UNKNOWN);
467 break;
470 /* possibly reload - change of architecture */
471 reload_services(True);
473 /* Check for protocols, most desirable first */
474 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
476 p = smb_buf(inbuf)+1;
477 Index = 0;
478 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
479 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
480 while (p < (smb_buf(inbuf) + bcc))
482 if (strequal(p,supported_protocols[protocol].proto_name))
483 choice = Index;
484 Index++;
485 p += strlen(p) + 2;
487 if(choice != -1)
488 break;
491 SSVAL(outbuf,smb_vwv0,choice);
492 if(choice != -1) {
493 extern fstring remote_proto;
494 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
495 reload_services(True);
496 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
497 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
499 else {
500 DEBUG(0,("No protocol supported !\n"));
502 SSVAL(outbuf,smb_vwv0,choice);
504 DEBUG( 5, ( "negprot index=%d\n", choice ) );
506 END_PROFILE(SMBnegprot);
507 return(outsize);