r1383: sync from 3.0 tree
[Samba.git] / source / smbd / negprot.c
blob5ff53f63007113dd579e76842a58216d9193d937
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 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])
31 NTSTATUS nt_status;
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;
60 return outsize;
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;
79 return outsize;
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);
89 int secword=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);
131 int secword=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)
171 DATA_BLOB blob;
172 nstring dos_name;
173 fstring unix_name;
174 uint8 guid[17];
175 const char *OIDs_krb5[] = {OID_KERBEROS5,
176 OID_KERBEROS5_OLD,
177 OID_NTLMSSP,
178 NULL};
179 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
180 char *principal;
181 int len;
183 global_spnego_negotiated = True;
185 ZERO_STRUCT(guid);
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);
192 #ifdef DEVELOPER
193 /* valgrind fixer... */
195 size_t sl = strlen(guid);
196 if (sizeof(guid)-sl)
197 memset(&guid[sl], '\0', sizeof(guid)-sl);
199 #endif
201 #if 0
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) {
209 memcpy(p, guid, 16);
210 return 16;
212 #endif
213 if (lp_security() != SEC_ADS) {
214 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
215 } else {
216 asprintf(&principal, "%s$@%s", guid, lp_realm());
217 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
218 free(principal);
220 memcpy(p, blob.data, blob.length);
221 len = blob.length;
222 data_blob_free(&blob);
223 return len;
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;
236 int secword=0;
237 time_t t = time(NULL);
238 char *p, *q;
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) &&
248 lp_use_spnego() &&
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|CAP_UNICODE;
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 if (lp_nt_status_support())
270 capabilities |= CAP_STATUS32;
272 if (lp_host_msdfs())
273 capabilities |= CAP_DFS;
275 if (lp_security() >= SEC_USER)
276 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
277 if (global_encrypted_passwords_negotiated)
278 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
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.");
296 set_message(outbuf,17,0,True);
298 SCVAL(outbuf,smb_vwv1,secword);
300 Protocol = PROTOCOL_NT1;
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);
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;
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);
327 SSVALS(outbuf,smb_vwv16+1,len);
328 p += len;
329 DEBUG(3,("using SPNEGO\n"));
332 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
333 set_message_end(outbuf, p);
335 return (smb_len(outbuf)+4);
338 /* these are the protocol lists used for auto architecture detection:
340 WinNT 3.51:
341 protocol [PC NETWORK PROGRAM 1.0]
342 protocol [XENIX CORE]
343 protocol [MICROSOFT NETWORKS 1.03]
344 protocol [LANMAN1.0]
345 protocol [Windows for Workgroups 3.1a]
346 protocol [LM1.2X002]
347 protocol [LANMAN2.1]
348 protocol [NT LM 0.12]
350 Win95:
351 protocol [PC NETWORK PROGRAM 1.0]
352 protocol [XENIX CORE]
353 protocol [MICROSOFT NETWORKS 1.03]
354 protocol [LANMAN1.0]
355 protocol [Windows for Workgroups 3.1a]
356 protocol [LM1.2X002]
357 protocol [LANMAN2.1]
358 protocol [NT LM 0.12]
360 Win2K:
361 protocol [PC NETWORK PROGRAM 1.0]
362 protocol [LANMAN1.0]
363 protocol [Windows for Workgroups 3.1a]
364 protocol [LM1.2X002]
365 protocol [LANMAN2.1]
366 protocol [NT LM 0.12]
368 OS/2:
369 protocol [PC NETWORK PROGRAM 1.0]
370 protocol [XENIX CORE]
371 protocol [LANMAN1.0]
372 protocol [LM1.2X002]
373 protocol [LANMAN2.1]
377 * Modified to recognize the architecture of the remote machine better.
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
394 * tim@fsg.com 09/29/95
395 * Win2K added by matty 17/7/99
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 #define ARCH_CIFSFS 0x40
406 #define ARCH_ALL 0x7F
408 /* List of supported protocols, most desired first */
409 static const struct {
410 const char *proto_name;
411 const char *short_name;
412 int (*proto_reply_fn)(char *, char *);
413 int protocol_level;
414 } supported_protocols[] = {
415 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
416 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
417 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
418 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
419 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
420 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
421 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
422 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
423 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
424 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
425 {NULL,NULL,NULL,0},
428 /****************************************************************************
429 Reply to a negprot.
430 ****************************************************************************/
432 int reply_negprot(connection_struct *conn,
433 char *inbuf,char *outbuf, int dum_size,
434 int dum_buffsize)
436 int outsize = set_message(outbuf,1,0,True);
437 int Index=0;
438 int choice= -1;
439 int protocol;
440 char *p;
441 int bcc = SVAL(smb_buf(inbuf),-2);
442 int arch = ARCH_ALL;
444 static BOOL done_negprot = False;
446 START_PROFILE(SMBnegprot);
448 if (done_negprot) {
449 END_PROFILE(SMBnegprot);
450 exit_server("multiple negprot's are not permitted");
452 done_negprot = True;
454 p = smb_buf(inbuf)+1;
455 while (p < (smb_buf(inbuf) + bcc)) {
456 Index++;
457 DEBUG(3,("Requested protocol [%s]\n",p));
458 if (strcsequal(p,"Windows for Workgroups 3.1a"))
459 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
460 else if (strcsequal(p,"DOS LM1.2X002"))
461 arch &= ( ARCH_WFWG | ARCH_WIN95 );
462 else if (strcsequal(p,"DOS LANMAN2.1"))
463 arch &= ( ARCH_WFWG | ARCH_WIN95 );
464 else if (strcsequal(p,"NT LM 0.12"))
465 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
466 else if (strcsequal(p,"LANMAN2.1"))
467 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
468 else if (strcsequal(p,"LM1.2X002"))
469 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
470 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
471 arch &= ARCH_WINNT;
472 else if (strcsequal(p,"XENIX CORE"))
473 arch &= ( ARCH_WINNT | ARCH_OS2 );
474 else if (strcsequal(p,"Samba")) {
475 arch = ARCH_SAMBA;
476 break;
477 } else if (strcsequal(p,"POSIX 2")) {
478 arch = ARCH_CIFSFS;
479 break;
482 p += strlen(p) + 2;
485 /* CIFSFS can send one arch only, NT LM 0.12. */
486 if (Index == 1 && (arch & ARCH_CIFSFS)) {
487 arch = ARCH_CIFSFS;
490 switch ( arch ) {
491 case ARCH_CIFSFS:
492 set_remote_arch(RA_CIFSFS);
493 break;
494 case ARCH_SAMBA:
495 set_remote_arch(RA_SAMBA);
496 break;
497 case ARCH_WFWG:
498 set_remote_arch(RA_WFWG);
499 break;
500 case ARCH_WIN95:
501 set_remote_arch(RA_WIN95);
502 break;
503 case ARCH_WINNT:
504 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
505 set_remote_arch(RA_WIN2K);
506 else
507 set_remote_arch(RA_WINNT);
508 break;
509 case ARCH_WIN2K:
510 set_remote_arch(RA_WIN2K);
511 break;
512 case ARCH_OS2:
513 set_remote_arch(RA_OS2);
514 break;
515 default:
516 set_remote_arch(RA_UNKNOWN);
517 break;
520 /* possibly reload - change of architecture */
521 reload_services(True);
523 /* Check for protocols, most desirable first */
524 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
525 p = smb_buf(inbuf)+1;
526 Index = 0;
527 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
528 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
529 while (p < (smb_buf(inbuf) + bcc)) {
530 if (strequal(p,supported_protocols[protocol].proto_name))
531 choice = Index;
532 Index++;
533 p += strlen(p) + 2;
535 if(choice != -1)
536 break;
539 SSVAL(outbuf,smb_vwv0,choice);
540 if(choice != -1) {
541 extern fstring remote_proto;
542 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
543 reload_services(True);
544 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
545 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
546 } else {
547 DEBUG(0,("No protocol supported !\n"));
549 SSVAL(outbuf,smb_vwv0,choice);
551 DEBUG( 5, ( "negprot index=%d\n", choice ) );
553 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
554 exit_server("SMB signing is required and client negotiated a downlevel protocol");
557 END_PROFILE(SMBnegprot);
558 return(outsize);