r10974: Get closer to trying to fix #1825 (PcoketPC spnego bug). Ensure we
[Samba/bb.git] / source3 / smbd / negprot.c
blob91942bf028f208d873dfd8111b9f4b35ff63288f
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;
26 BOOL global_encrypted_passwords_negotiated = False;
27 BOOL global_spnego_negotiated = False;
28 struct auth_context *negprot_global_auth_context = NULL;
30 static void get_challenge(char buff[8])
32 NTSTATUS nt_status;
33 const uint8 *cryptkey;
35 /* We might be called more than once, muliple negprots are premitted */
36 if (negprot_global_auth_context) {
37 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
38 (negprot_global_auth_context->free)(&negprot_global_auth_context);
41 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
42 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
43 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
44 smb_panic("cannot make_negprot_global_auth_context!\n");
46 DEBUG(10, ("get challenge: getting challenge\n"));
47 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
48 memcpy(buff, cryptkey, 8);
51 /****************************************************************************
52 Reply for the core protocol.
53 ****************************************************************************/
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;
64 /****************************************************************************
65 Reply for the coreplus protocol.
66 ****************************************************************************/
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;
83 /****************************************************************************
84 Reply for the lanman 1.0 protocol.
85 ****************************************************************************/
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)
96 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
97 if (global_encrypted_passwords_negotiated)
98 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
100 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
101 SSVAL(outbuf,smb_vwv1,secword);
102 /* Create a token value and add it to the outgoing packet. */
103 if (global_encrypted_passwords_negotiated) {
104 get_challenge(smb_buf(outbuf));
105 SSVAL(outbuf,smb_vwv11, 8);
108 Protocol = PROTOCOL_LANMAN1;
110 /* Reply, SMBlockread, SMBwritelock supported. */
111 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
112 SSVAL(outbuf,smb_vwv2,max_recv);
113 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
114 SSVAL(outbuf,smb_vwv4,1);
115 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
116 readbraw writebraw (possibly) */
117 SIVAL(outbuf,smb_vwv6,sys_getpid());
118 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
120 put_dos_date(outbuf,smb_vwv8,t);
122 return (smb_len(outbuf)+4);
125 /****************************************************************************
126 Reply for the lanman 2.0 protocol.
127 ****************************************************************************/
129 static int reply_lanman2(char *inbuf, char *outbuf)
131 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
132 int secword=0;
133 time_t t = time(NULL);
135 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
137 if (lp_security()>=SEC_USER)
138 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
139 if (global_encrypted_passwords_negotiated)
140 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
142 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
143 SSVAL(outbuf,smb_vwv1,secword);
144 SIVAL(outbuf,smb_vwv6,sys_getpid());
146 /* Create a token value and add it to the outgoing packet. */
147 if (global_encrypted_passwords_negotiated) {
148 get_challenge(smb_buf(outbuf));
149 SSVAL(outbuf,smb_vwv11, 8);
152 Protocol = PROTOCOL_LANMAN2;
154 /* Reply, SMBlockread, SMBwritelock supported. */
155 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
156 SSVAL(outbuf,smb_vwv2,max_recv);
157 SSVAL(outbuf,smb_vwv3,lp_maxmux());
158 SSVAL(outbuf,smb_vwv4,1);
159 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
160 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
161 put_dos_date(outbuf,smb_vwv8,t);
163 return (smb_len(outbuf)+4);
166 /****************************************************************************
167 Generate the spnego negprot reply blob. Return the number of bytes used.
168 ****************************************************************************/
170 static int negprot_spnego(char *p, uint8 *pkeylen)
172 DATA_BLOB blob;
173 nstring dos_name;
174 fstring unix_name;
175 uint8 guid[17];
176 const char *OIDs_krb5[] = {OID_KERBEROS5,
177 OID_KERBEROS5_OLD,
178 OID_NTLMSSP,
179 NULL};
180 int len;
182 global_spnego_negotiated = True;
184 ZERO_STRUCT(guid);
186 safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
187 strlower_m(unix_name);
188 push_ascii_nstring(dos_name, unix_name);
189 safe_strcpy((char *)guid, dos_name, sizeof(guid)-1);
191 #ifdef DEVELOPER
192 /* valgrind fixer... */
194 size_t sl = strlen(guid);
195 if (sizeof(guid)-sl)
196 memset(&guid[sl], '\0', sizeof(guid)-sl);
198 #endif
200 /* strangely enough, NT does not sent the single OID NTLMSSP when
201 not a ADS member, it sends no OIDs at all
203 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
204 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
206 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
207 back to doing what W2K3 does here. This is needed to make PocketPC 2003
208 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
209 for details. JRA.
213 if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
214 memcpy(p, guid, 16);
215 *pkeylen = 0;
216 return 16;
217 } else {
218 fstring myname;
219 char *host_princ_s = NULL;
220 name_to_fqdn(myname, global_myname());
221 strlower_m(myname);
222 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
223 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
224 SAFE_FREE(host_princ_s);
226 memcpy(p, blob.data, blob.length);
227 len = blob.length;
228 if (len > 256) {
229 DEBUG(0,("negprot_spnego: blob length too long (%d)\n", len));
230 len = 255;
232 *pkeylen = len;
233 data_blob_free(&blob);
234 return len;
237 /****************************************************************************
238 Reply for the nt protocol.
239 ****************************************************************************/
241 static int reply_nt1(char *inbuf, char *outbuf)
243 /* dual names + lock_and_read + nt SMBs + remote API calls */
244 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
245 CAP_LEVEL_II_OPLOCKS;
247 int secword=0;
248 time_t t = time(NULL);
249 char *p, *q;
250 BOOL negotiate_spnego = False;
252 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
254 /* do spnego in user level security if the client
255 supports it and we can do encrypted passwords */
257 if (global_encrypted_passwords_negotiated &&
258 (lp_security() != SEC_SHARE) &&
259 lp_use_spnego() &&
260 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
261 negotiate_spnego = True;
262 capabilities |= CAP_EXTENDED_SECURITY;
263 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
264 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
265 partially constructed. */
266 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
269 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
271 if (lp_unix_extensions()) {
272 capabilities |= CAP_UNIX;
275 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
276 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
278 if (SMB_OFF_T_BITS == 64)
279 capabilities |= CAP_LARGE_FILES;
281 if (lp_readraw() && lp_writeraw())
282 capabilities |= CAP_RAW_MODE;
284 if (lp_nt_status_support())
285 capabilities |= CAP_STATUS32;
287 if (lp_host_msdfs())
288 capabilities |= CAP_DFS;
290 if (lp_security() >= SEC_USER)
291 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
292 if (global_encrypted_passwords_negotiated)
293 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
295 if (lp_server_signing()) {
296 if (lp_security() >= SEC_USER) {
297 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
298 /* No raw mode with smb signing. */
299 capabilities &= ~CAP_RAW_MODE;
300 if (lp_server_signing() == Required)
301 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
302 srv_set_signing_negotiated();
303 } else {
304 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
305 if (lp_server_signing() == Required) {
306 exit_server("reply_nt1: smb signing required and share level security selected.");
311 set_message(outbuf,17,0,True);
313 SCVAL(outbuf,smb_vwv1,secword);
315 Protocol = PROTOCOL_NT1;
317 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
318 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
319 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
320 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
321 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
322 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
323 put_long_date(outbuf+smb_vwv11+1,t);
324 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
326 p = q = smb_buf(outbuf);
327 if (!negotiate_spnego) {
328 /* Create a token value and add it to the outgoing packet. */
329 if (global_encrypted_passwords_negotiated) {
330 /* note that we do not send a challenge at all if
331 we are using plaintext */
332 get_challenge(p);
333 SCVAL(outbuf,smb_vwv16+1,8);
334 p += 8;
336 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
337 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
338 DEBUG(3,("not using SPNEGO\n"));
339 } else {
340 uint8 keylen;
341 int len = negprot_spnego(p, &keylen);
343 SCVAL(outbuf,smb_vwv16+1,keylen);
344 p += len;
345 DEBUG(3,("using SPNEGO\n"));
348 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
349 set_message_end(outbuf, p);
351 return (smb_len(outbuf)+4);
354 /* these are the protocol lists used for auto architecture detection:
356 WinNT 3.51:
357 protocol [PC NETWORK PROGRAM 1.0]
358 protocol [XENIX CORE]
359 protocol [MICROSOFT NETWORKS 1.03]
360 protocol [LANMAN1.0]
361 protocol [Windows for Workgroups 3.1a]
362 protocol [LM1.2X002]
363 protocol [LANMAN2.1]
364 protocol [NT LM 0.12]
366 Win95:
367 protocol [PC NETWORK PROGRAM 1.0]
368 protocol [XENIX CORE]
369 protocol [MICROSOFT NETWORKS 1.03]
370 protocol [LANMAN1.0]
371 protocol [Windows for Workgroups 3.1a]
372 protocol [LM1.2X002]
373 protocol [LANMAN2.1]
374 protocol [NT LM 0.12]
376 Win2K:
377 protocol [PC NETWORK PROGRAM 1.0]
378 protocol [LANMAN1.0]
379 protocol [Windows for Workgroups 3.1a]
380 protocol [LM1.2X002]
381 protocol [LANMAN2.1]
382 protocol [NT LM 0.12]
384 OS/2:
385 protocol [PC NETWORK PROGRAM 1.0]
386 protocol [XENIX CORE]
387 protocol [LANMAN1.0]
388 protocol [LM1.2X002]
389 protocol [LANMAN2.1]
393 * Modified to recognize the architecture of the remote machine better.
395 * This appears to be the matrix of which protocol is used by which
396 * MS product.
397 Protocol WfWg Win95 WinNT Win2K OS/2
398 PC NETWORK PROGRAM 1.0 1 1 1 1 1
399 XENIX CORE 2 2
400 MICROSOFT NETWORKS 3.0 2 2
401 DOS LM1.2X002 3 3
402 MICROSOFT NETWORKS 1.03 3
403 DOS LANMAN2.1 4 4
404 LANMAN1.0 4 2 3
405 Windows for Workgroups 3.1a 5 5 5 3
406 LM1.2X002 6 4 4
407 LANMAN2.1 7 5 5
408 NT LM 0.12 6 8 6
410 * tim@fsg.com 09/29/95
411 * Win2K added by matty 17/7/99
414 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
415 #define ARCH_WIN95 0x2
416 #define ARCH_WINNT 0x4
417 #define ARCH_WIN2K 0xC /* Win2K is like NT */
418 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
419 #define ARCH_SAMBA 0x20
420 #define ARCH_CIFSFS 0x40
422 #define ARCH_ALL 0x7F
424 /* List of supported protocols, most desired first */
425 static const struct {
426 const char *proto_name;
427 const char *short_name;
428 int (*proto_reply_fn)(char *, char *);
429 int protocol_level;
430 } supported_protocols[] = {
431 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
432 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
433 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
434 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
435 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
436 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
437 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
438 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
439 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
440 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
441 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
442 {NULL,NULL,NULL,0},
445 /****************************************************************************
446 Reply to a negprot.
447 ****************************************************************************/
449 int reply_negprot(connection_struct *conn,
450 char *inbuf,char *outbuf, int dum_size,
451 int dum_buffsize)
453 int outsize = set_message(outbuf,1,0,True);
454 int Index=0;
455 int choice= -1;
456 int protocol;
457 char *p;
458 int bcc = SVAL(smb_buf(inbuf),-2);
459 int arch = ARCH_ALL;
461 static BOOL done_negprot = False;
463 START_PROFILE(SMBnegprot);
465 if (done_negprot) {
466 END_PROFILE(SMBnegprot);
467 exit_server("multiple negprot's are not permitted");
469 done_negprot = True;
471 p = smb_buf(inbuf)+1;
472 while (p < (smb_buf(inbuf) + bcc)) {
473 Index++;
474 DEBUG(3,("Requested protocol [%s]\n",p));
475 if (strcsequal(p,"Windows for Workgroups 3.1a"))
476 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
477 else if (strcsequal(p,"DOS LM1.2X002"))
478 arch &= ( ARCH_WFWG | ARCH_WIN95 );
479 else if (strcsequal(p,"DOS LANMAN2.1"))
480 arch &= ( ARCH_WFWG | ARCH_WIN95 );
481 else if (strcsequal(p,"NT LM 0.12"))
482 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
483 else if (strcsequal(p,"LANMAN2.1"))
484 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
485 else if (strcsequal(p,"LM1.2X002"))
486 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
487 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
488 arch &= ARCH_WINNT;
489 else if (strcsequal(p,"XENIX CORE"))
490 arch &= ( ARCH_WINNT | ARCH_OS2 );
491 else if (strcsequal(p,"Samba")) {
492 arch = ARCH_SAMBA;
493 break;
494 } else if (strcsequal(p,"POSIX 2")) {
495 arch = ARCH_CIFSFS;
496 break;
499 p += strlen(p) + 2;
502 /* CIFSFS can send one arch only, NT LM 0.12. */
503 if (Index == 1 && (arch & ARCH_CIFSFS)) {
504 arch = ARCH_CIFSFS;
507 switch ( arch ) {
508 case ARCH_CIFSFS:
509 set_remote_arch(RA_CIFSFS);
510 break;
511 case ARCH_SAMBA:
512 set_remote_arch(RA_SAMBA);
513 break;
514 case ARCH_WFWG:
515 set_remote_arch(RA_WFWG);
516 break;
517 case ARCH_WIN95:
518 set_remote_arch(RA_WIN95);
519 break;
520 case ARCH_WINNT:
521 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
522 set_remote_arch(RA_WIN2K);
523 else
524 set_remote_arch(RA_WINNT);
525 break;
526 case ARCH_WIN2K:
527 set_remote_arch(RA_WIN2K);
528 break;
529 case ARCH_OS2:
530 set_remote_arch(RA_OS2);
531 break;
532 default:
533 set_remote_arch(RA_UNKNOWN);
534 break;
537 /* possibly reload - change of architecture */
538 reload_services(True);
540 /* moved from the netbios session setup code since we don't have that
541 when the client connects to port 445. Of course there is a small
542 window where we are listening to messages -- jerry */
544 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
546 /* Check for protocols, most desirable first */
547 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
548 p = smb_buf(inbuf)+1;
549 Index = 0;
550 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
551 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
552 while (p < (smb_buf(inbuf) + bcc)) {
553 if (strequal(p,supported_protocols[protocol].proto_name))
554 choice = Index;
555 Index++;
556 p += strlen(p) + 2;
558 if(choice != -1)
559 break;
562 SSVAL(outbuf,smb_vwv0,choice);
563 if(choice != -1) {
564 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
565 reload_services(True);
566 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
567 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
568 } else {
569 DEBUG(0,("No protocol supported !\n"));
571 SSVAL(outbuf,smb_vwv0,choice);
573 DEBUG( 5, ( "negprot index=%d\n", choice ) );
575 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
576 exit_server("SMB signing is required and client negotiated a downlevel protocol");
579 END_PROFILE(SMBnegprot);
580 return(outsize);