r19692: Another fix.
[Samba.git] / source / smbd / negprot.c
blobbbd101305090517bdccfe333345af1eb33314c38
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 fstring remote_proto;
24 extern enum protocol_types Protocol;
25 extern int max_recv;
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, multiple negprots are
37 * permitted */
38 if (negprot_global_auth_context) {
39 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
40 (negprot_global_auth_context->free)(&negprot_global_auth_context);
43 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
44 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
45 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
46 smb_panic("cannot make_negprot_global_auth_context!\n");
48 DEBUG(10, ("get challenge: getting challenge\n"));
49 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
50 memcpy(buff, cryptkey, 8);
53 /****************************************************************************
54 Reply for the core protocol.
55 ****************************************************************************/
57 static int reply_corep(char *inbuf, char *outbuf)
59 int outsize = set_message(outbuf,1,0,True);
61 Protocol = PROTOCOL_CORE;
63 return outsize;
66 /****************************************************************************
67 Reply for the coreplus protocol.
68 ****************************************************************************/
70 static int reply_coreplus(char *inbuf, char *outbuf)
72 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
73 int outsize = set_message(outbuf,13,0,True);
74 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
75 readbraw and writebraw (possibly) */
76 /* Reply, SMBlockread, SMBwritelock supported. */
77 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
78 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
80 Protocol = PROTOCOL_COREPLUS;
82 return outsize;
85 /****************************************************************************
86 Reply for the lanman 1.0 protocol.
87 ****************************************************************************/
89 static int reply_lanman1(char *inbuf, char *outbuf)
91 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
92 int secword=0;
93 time_t t = time(NULL);
95 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
97 if (lp_security()>=SEC_USER)
98 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
99 if (global_encrypted_passwords_negotiated)
100 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
102 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
103 SSVAL(outbuf,smb_vwv1,secword);
104 /* Create a token value and add it to the outgoing packet. */
105 if (global_encrypted_passwords_negotiated) {
106 get_challenge(smb_buf(outbuf));
107 SSVAL(outbuf,smb_vwv11, 8);
110 Protocol = PROTOCOL_LANMAN1;
112 /* Reply, SMBlockread, SMBwritelock supported. */
113 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
114 SSVAL(outbuf,smb_vwv2,max_recv);
115 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
116 SSVAL(outbuf,smb_vwv4,1);
117 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
118 readbraw writebraw (possibly) */
119 SIVAL(outbuf,smb_vwv6,sys_getpid());
120 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
122 srv_put_dos_date(outbuf,smb_vwv8,t);
124 return (smb_len(outbuf)+4);
127 /****************************************************************************
128 Reply for the lanman 2.0 protocol.
129 ****************************************************************************/
131 static int reply_lanman2(char *inbuf, char *outbuf)
133 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
134 int secword=0;
135 time_t t = time(NULL);
137 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
139 if (lp_security()>=SEC_USER)
140 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
141 if (global_encrypted_passwords_negotiated)
142 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
144 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
145 SSVAL(outbuf,smb_vwv1,secword);
146 SIVAL(outbuf,smb_vwv6,sys_getpid());
148 /* Create a token value and add it to the outgoing packet. */
149 if (global_encrypted_passwords_negotiated) {
150 get_challenge(smb_buf(outbuf));
151 SSVAL(outbuf,smb_vwv11, 8);
154 Protocol = PROTOCOL_LANMAN2;
156 /* Reply, SMBlockread, SMBwritelock supported. */
157 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
158 SSVAL(outbuf,smb_vwv2,max_recv);
159 SSVAL(outbuf,smb_vwv3,lp_maxmux());
160 SSVAL(outbuf,smb_vwv4,1);
161 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
162 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
163 srv_put_dos_date(outbuf,smb_vwv8,t);
165 return (smb_len(outbuf)+4);
168 /****************************************************************************
169 Generate the spnego negprot reply blob. Return the number of bytes used.
170 ****************************************************************************/
172 static DATA_BLOB negprot_spnego(void)
174 DATA_BLOB blob;
175 nstring dos_name;
176 fstring unix_name;
177 char guid[17];
178 const char *OIDs_krb5[] = {OID_KERBEROS5,
179 OID_KERBEROS5_OLD,
180 OID_NTLMSSP,
181 NULL};
182 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
184 global_spnego_negotiated = True;
186 ZERO_STRUCT(guid);
188 safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
189 strlower_m(unix_name);
190 push_ascii_nstring(dos_name, unix_name);
191 safe_strcpy(guid, dos_name, sizeof(guid)-1);
193 /* strangely enough, NT does not sent the single OID NTLMSSP when
194 not a ADS member, it sends no OIDs at all
196 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
197 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
199 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
200 back to doing what W2K3 does here. This is needed to make PocketPC 2003
201 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
202 for details. JRA.
206 if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
207 #if 0
208 /* Code for PocketPC client */
209 blob = data_blob(guid, 16);
210 #else
211 /* Code for standalone WXP client */
212 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
213 #endif
214 } else {
215 fstring myname;
216 char *host_princ_s = NULL;
217 name_to_fqdn(myname, global_myname());
218 strlower_m(myname);
219 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
220 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
221 SAFE_FREE(host_princ_s);
224 return blob;
227 /****************************************************************************
228 Reply for the nt protocol.
229 ****************************************************************************/
231 static int reply_nt1(char *inbuf, char *outbuf)
233 /* dual names + lock_and_read + nt SMBs + remote API calls */
234 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
235 CAP_LEVEL_II_OPLOCKS;
237 int secword=0;
238 char *p, *q;
239 BOOL negotiate_spnego = False;
240 time_t t = time(NULL);
242 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
244 /* do spnego in user level security if the client
245 supports it and we can do encrypted passwords */
247 if (global_encrypted_passwords_negotiated &&
248 (lp_security() != SEC_SHARE) &&
249 lp_use_spnego() &&
250 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
251 negotiate_spnego = True;
252 capabilities |= CAP_EXTENDED_SECURITY;
253 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
254 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
255 partially constructed. */
256 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
259 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
261 if (lp_unix_extensions()) {
262 capabilities |= CAP_UNIX;
265 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
266 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
268 if (SMB_OFF_T_BITS == 64)
269 capabilities |= CAP_LARGE_FILES;
271 if (lp_readraw() && lp_writeraw())
272 capabilities |= CAP_RAW_MODE;
274 if (lp_nt_status_support())
275 capabilities |= CAP_STATUS32;
277 if (lp_host_msdfs())
278 capabilities |= CAP_DFS;
280 if (lp_security() >= SEC_USER)
281 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
282 if (global_encrypted_passwords_negotiated)
283 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
285 if (lp_server_signing()) {
286 if (lp_security() >= SEC_USER) {
287 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
288 /* No raw mode with smb signing. */
289 capabilities &= ~CAP_RAW_MODE;
290 if (lp_server_signing() == Required)
291 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
292 srv_set_signing_negotiated();
293 } else {
294 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
295 if (lp_server_signing() == Required) {
296 exit_server("reply_nt1: smb signing required and share level security selected.");
301 set_message(outbuf,17,0,True);
303 SCVAL(outbuf,smb_vwv1,secword);
305 Protocol = PROTOCOL_NT1;
307 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
308 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
309 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
310 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
311 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
312 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
313 put_long_date(outbuf+smb_vwv11+1,t);
314 SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
316 p = q = smb_buf(outbuf);
317 if (!negotiate_spnego) {
318 /* Create a token value and add it to the outgoing packet. */
319 if (global_encrypted_passwords_negotiated) {
320 /* note that we do not send a challenge at all if
321 we are using plaintext */
322 get_challenge(p);
323 SCVAL(outbuf,smb_vwv16+1,8);
324 p += 8;
326 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
327 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
328 DEBUG(3,("not using SPNEGO\n"));
329 } else {
330 DATA_BLOB spnego_blob = negprot_spnego();
332 if (spnego_blob.data == NULL) {
333 return ERROR_NT(NT_STATUS_NO_MEMORY);
336 memcpy(p, spnego_blob.data, spnego_blob.length);
337 p += spnego_blob.length;
338 data_blob_free(&spnego_blob);
340 SCVAL(outbuf,smb_vwv16+1, 0);
341 DEBUG(3,("using SPNEGO\n"));
344 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
345 set_message_end(outbuf, p);
347 return (smb_len(outbuf)+4);
350 /* these are the protocol lists used for auto architecture detection:
352 WinNT 3.51:
353 protocol [PC NETWORK PROGRAM 1.0]
354 protocol [XENIX CORE]
355 protocol [MICROSOFT NETWORKS 1.03]
356 protocol [LANMAN1.0]
357 protocol [Windows for Workgroups 3.1a]
358 protocol [LM1.2X002]
359 protocol [LANMAN2.1]
360 protocol [NT LM 0.12]
362 Win95:
363 protocol [PC NETWORK PROGRAM 1.0]
364 protocol [XENIX CORE]
365 protocol [MICROSOFT NETWORKS 1.03]
366 protocol [LANMAN1.0]
367 protocol [Windows for Workgroups 3.1a]
368 protocol [LM1.2X002]
369 protocol [LANMAN2.1]
370 protocol [NT LM 0.12]
372 Win2K:
373 protocol [PC NETWORK PROGRAM 1.0]
374 protocol [LANMAN1.0]
375 protocol [Windows for Workgroups 3.1a]
376 protocol [LM1.2X002]
377 protocol [LANMAN2.1]
378 protocol [NT LM 0.12]
380 OS/2:
381 protocol [PC NETWORK PROGRAM 1.0]
382 protocol [XENIX CORE]
383 protocol [LANMAN1.0]
384 protocol [LM1.2X002]
385 protocol [LANMAN2.1]
389 * Modified to recognize the architecture of the remote machine better.
391 * This appears to be the matrix of which protocol is used by which
392 * MS product.
393 Protocol WfWg Win95 WinNT Win2K OS/2
394 PC NETWORK PROGRAM 1.0 1 1 1 1 1
395 XENIX CORE 2 2
396 MICROSOFT NETWORKS 3.0 2 2
397 DOS LM1.2X002 3 3
398 MICROSOFT NETWORKS 1.03 3
399 DOS LANMAN2.1 4 4
400 LANMAN1.0 4 2 3
401 Windows for Workgroups 3.1a 5 5 5 3
402 LM1.2X002 6 4 4
403 LANMAN2.1 7 5 5
404 NT LM 0.12 6 8 6
406 * tim@fsg.com 09/29/95
407 * Win2K added by matty 17/7/99
410 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
411 #define ARCH_WIN95 0x2
412 #define ARCH_WINNT 0x4
413 #define ARCH_WIN2K 0xC /* Win2K is like NT */
414 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
415 #define ARCH_SAMBA 0x20
416 #define ARCH_CIFSFS 0x40
418 #define ARCH_ALL 0x7F
420 /* List of supported protocols, most desired first */
421 static const struct {
422 const char *proto_name;
423 const char *short_name;
424 int (*proto_reply_fn)(char *, char *);
425 int protocol_level;
426 } supported_protocols[] = {
427 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
428 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
429 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
430 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
431 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
432 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
433 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
434 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
435 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
436 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
437 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
438 {NULL,NULL,NULL,0},
441 /****************************************************************************
442 Reply to a negprot.
443 conn POINTER CAN BE NULL HERE !
444 ****************************************************************************/
446 int reply_negprot(connection_struct *conn,
447 char *inbuf,char *outbuf, int dum_size,
448 int dum_buffsize)
450 int outsize = set_message(outbuf,1,0,True);
451 int Index=0;
452 int choice= -1;
453 int protocol;
454 char *p;
455 int bcc = SVAL(smb_buf(inbuf),-2);
456 int arch = ARCH_ALL;
458 static BOOL done_negprot = False;
460 START_PROFILE(SMBnegprot);
462 if (done_negprot) {
463 END_PROFILE(SMBnegprot);
464 exit_server("multiple negprot's are not permitted");
466 done_negprot = True;
468 p = smb_buf(inbuf)+1;
469 while (p < (smb_buf(inbuf) + bcc)) {
470 Index++;
471 DEBUG(3,("Requested protocol [%s]\n",p));
472 if (strcsequal(p,"Windows for Workgroups 3.1a"))
473 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
474 else if (strcsequal(p,"DOS LM1.2X002"))
475 arch &= ( ARCH_WFWG | ARCH_WIN95 );
476 else if (strcsequal(p,"DOS LANMAN2.1"))
477 arch &= ( ARCH_WFWG | ARCH_WIN95 );
478 else if (strcsequal(p,"NT LM 0.12"))
479 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
480 else if (strcsequal(p,"LANMAN2.1"))
481 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
482 else if (strcsequal(p,"LM1.2X002"))
483 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
484 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
485 arch &= ARCH_WINNT;
486 else if (strcsequal(p,"XENIX CORE"))
487 arch &= ( ARCH_WINNT | ARCH_OS2 );
488 else if (strcsequal(p,"Samba")) {
489 arch = ARCH_SAMBA;
490 break;
491 } else if (strcsequal(p,"POSIX 2")) {
492 arch = ARCH_CIFSFS;
493 break;
496 p += strlen(p) + 2;
499 /* CIFSFS can send one arch only, NT LM 0.12. */
500 if (Index == 1 && (arch & ARCH_CIFSFS)) {
501 arch = ARCH_CIFSFS;
504 switch ( arch ) {
505 case ARCH_CIFSFS:
506 set_remote_arch(RA_CIFSFS);
507 break;
508 case ARCH_SAMBA:
509 set_remote_arch(RA_SAMBA);
510 break;
511 case ARCH_WFWG:
512 set_remote_arch(RA_WFWG);
513 break;
514 case ARCH_WIN95:
515 set_remote_arch(RA_WIN95);
516 break;
517 case ARCH_WINNT:
518 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
519 set_remote_arch(RA_WIN2K);
520 else
521 set_remote_arch(RA_WINNT);
522 break;
523 case ARCH_WIN2K:
524 set_remote_arch(RA_WIN2K);
525 break;
526 case ARCH_OS2:
527 set_remote_arch(RA_OS2);
528 break;
529 default:
530 set_remote_arch(RA_UNKNOWN);
531 break;
534 /* possibly reload - change of architecture */
535 reload_services(True);
537 /* moved from the netbios session setup code since we don't have that
538 when the client connects to port 445. Of course there is a small
539 window where we are listening to messages -- jerry */
541 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
543 /* Check for protocols, most desirable first */
544 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
545 p = smb_buf(inbuf)+1;
546 Index = 0;
547 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
548 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
549 while (p < (smb_buf(inbuf) + bcc)) {
550 if (strequal(p,supported_protocols[protocol].proto_name))
551 choice = Index;
552 Index++;
553 p += strlen(p) + 2;
555 if(choice != -1)
556 break;
559 SSVAL(outbuf,smb_vwv0,choice);
560 if(choice != -1) {
561 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
562 reload_services(True);
563 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
564 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
565 } else {
566 DEBUG(0,("No protocol supported !\n"));
568 SSVAL(outbuf,smb_vwv0,choice);
570 DEBUG( 5, ( "negprot index=%d\n", choice ) );
572 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
573 exit_server("SMB signing is required and client negotiated a downlevel protocol");
576 END_PROFILE(SMBnegprot);
577 return(outsize);