r10947: Fix bugs #3133 and #1828 - SPNEGO not working with PocketPC 2003.
[Samba.git] / source / smbd / negprot.c
blob1f4cb30003fffcdf30d43d6ce958b88c33c62254
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)
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 return 16;
216 } else {
217 fstring myname;
218 char *host_princ_s = NULL;
219 name_to_fqdn(myname, global_myname());
220 strlower_m(myname);
221 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
222 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
223 SAFE_FREE(host_princ_s);
225 memcpy(p, blob.data, blob.length);
226 len = blob.length;
227 data_blob_free(&blob);
228 return len;
231 /****************************************************************************
232 Reply for the nt protocol.
233 ****************************************************************************/
235 static int reply_nt1(char *inbuf, char *outbuf)
237 /* dual names + lock_and_read + nt SMBs + remote API calls */
238 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
239 CAP_LEVEL_II_OPLOCKS;
241 int secword=0;
242 time_t t = time(NULL);
243 char *p, *q;
244 BOOL negotiate_spnego = False;
246 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
248 /* do spnego in user level security if the client
249 supports it and we can do encrypted passwords */
251 if (global_encrypted_passwords_negotiated &&
252 (lp_security() != SEC_SHARE) &&
253 lp_use_spnego() &&
254 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
255 negotiate_spnego = True;
256 capabilities |= CAP_EXTENDED_SECURITY;
257 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
258 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
259 partially constructed. */
260 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
263 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
265 if (lp_unix_extensions()) {
266 capabilities |= CAP_UNIX;
269 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
270 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
272 if (SMB_OFF_T_BITS == 64)
273 capabilities |= CAP_LARGE_FILES;
275 if (lp_readraw() && lp_writeraw())
276 capabilities |= CAP_RAW_MODE;
278 if (lp_nt_status_support())
279 capabilities |= CAP_STATUS32;
281 if (lp_host_msdfs())
282 capabilities |= CAP_DFS;
284 if (lp_security() >= SEC_USER)
285 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
286 if (global_encrypted_passwords_negotiated)
287 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
289 if (lp_server_signing()) {
290 if (lp_security() >= SEC_USER) {
291 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
292 /* No raw mode with smb signing. */
293 capabilities &= ~CAP_RAW_MODE;
294 if (lp_server_signing() == Required)
295 secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
296 srv_set_signing_negotiated();
297 } else {
298 DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
299 if (lp_server_signing() == Required) {
300 exit_server("reply_nt1: smb signing required and share level security selected.");
305 set_message(outbuf,17,0,True);
307 SCVAL(outbuf,smb_vwv1,secword);
309 Protocol = PROTOCOL_NT1;
311 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
312 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
313 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
314 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
315 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
316 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
317 put_long_date(outbuf+smb_vwv11+1,t);
318 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
320 p = q = smb_buf(outbuf);
321 if (!negotiate_spnego) {
322 /* Create a token value and add it to the outgoing packet. */
323 if (global_encrypted_passwords_negotiated) {
324 /* note that we do not send a challenge at all if
325 we are using plaintext */
326 get_challenge(p);
327 SSVALS(outbuf,smb_vwv16+1,8);
328 p += 8;
330 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
331 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
332 DEBUG(3,("not using SPNEGO\n"));
333 } else {
334 int len = negprot_spnego(p);
336 SSVALS(outbuf,smb_vwv16+1,len);
337 p += len;
338 DEBUG(3,("using SPNEGO\n"));
341 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
342 set_message_end(outbuf, p);
344 return (smb_len(outbuf)+4);
347 /* these are the protocol lists used for auto architecture detection:
349 WinNT 3.51:
350 protocol [PC NETWORK PROGRAM 1.0]
351 protocol [XENIX CORE]
352 protocol [MICROSOFT NETWORKS 1.03]
353 protocol [LANMAN1.0]
354 protocol [Windows for Workgroups 3.1a]
355 protocol [LM1.2X002]
356 protocol [LANMAN2.1]
357 protocol [NT LM 0.12]
359 Win95:
360 protocol [PC NETWORK PROGRAM 1.0]
361 protocol [XENIX CORE]
362 protocol [MICROSOFT NETWORKS 1.03]
363 protocol [LANMAN1.0]
364 protocol [Windows for Workgroups 3.1a]
365 protocol [LM1.2X002]
366 protocol [LANMAN2.1]
367 protocol [NT LM 0.12]
369 Win2K:
370 protocol [PC NETWORK PROGRAM 1.0]
371 protocol [LANMAN1.0]
372 protocol [Windows for Workgroups 3.1a]
373 protocol [LM1.2X002]
374 protocol [LANMAN2.1]
375 protocol [NT LM 0.12]
377 OS/2:
378 protocol [PC NETWORK PROGRAM 1.0]
379 protocol [XENIX CORE]
380 protocol [LANMAN1.0]
381 protocol [LM1.2X002]
382 protocol [LANMAN2.1]
386 * Modified to recognize the architecture of the remote machine better.
388 * This appears to be the matrix of which protocol is used by which
389 * MS product.
390 Protocol WfWg Win95 WinNT Win2K OS/2
391 PC NETWORK PROGRAM 1.0 1 1 1 1 1
392 XENIX CORE 2 2
393 MICROSOFT NETWORKS 3.0 2 2
394 DOS LM1.2X002 3 3
395 MICROSOFT NETWORKS 1.03 3
396 DOS LANMAN2.1 4 4
397 LANMAN1.0 4 2 3
398 Windows for Workgroups 3.1a 5 5 5 3
399 LM1.2X002 6 4 4
400 LANMAN2.1 7 5 5
401 NT LM 0.12 6 8 6
403 * tim@fsg.com 09/29/95
404 * Win2K added by matty 17/7/99
407 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
408 #define ARCH_WIN95 0x2
409 #define ARCH_WINNT 0x4
410 #define ARCH_WIN2K 0xC /* Win2K is like NT */
411 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
412 #define ARCH_SAMBA 0x20
413 #define ARCH_CIFSFS 0x40
415 #define ARCH_ALL 0x7F
417 /* List of supported protocols, most desired first */
418 static const struct {
419 const char *proto_name;
420 const char *short_name;
421 int (*proto_reply_fn)(char *, char *);
422 int protocol_level;
423 } supported_protocols[] = {
424 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
425 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
426 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
427 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
428 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
429 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
430 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
431 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
432 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
433 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
434 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
435 {NULL,NULL,NULL,0},
438 /****************************************************************************
439 Reply to a negprot.
440 ****************************************************************************/
442 int reply_negprot(connection_struct *conn,
443 char *inbuf,char *outbuf, int dum_size,
444 int dum_buffsize)
446 int outsize = set_message(outbuf,1,0,True);
447 int Index=0;
448 int choice= -1;
449 int protocol;
450 char *p;
451 int bcc = SVAL(smb_buf(inbuf),-2);
452 int arch = ARCH_ALL;
454 static BOOL done_negprot = False;
456 START_PROFILE(SMBnegprot);
458 if (done_negprot) {
459 END_PROFILE(SMBnegprot);
460 exit_server("multiple negprot's are not permitted");
462 done_negprot = True;
464 p = smb_buf(inbuf)+1;
465 while (p < (smb_buf(inbuf) + bcc)) {
466 Index++;
467 DEBUG(3,("Requested protocol [%s]\n",p));
468 if (strcsequal(p,"Windows for Workgroups 3.1a"))
469 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
470 else if (strcsequal(p,"DOS LM1.2X002"))
471 arch &= ( ARCH_WFWG | ARCH_WIN95 );
472 else if (strcsequal(p,"DOS LANMAN2.1"))
473 arch &= ( ARCH_WFWG | ARCH_WIN95 );
474 else if (strcsequal(p,"NT LM 0.12"))
475 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
476 else if (strcsequal(p,"LANMAN2.1"))
477 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
478 else if (strcsequal(p,"LM1.2X002"))
479 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
480 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
481 arch &= ARCH_WINNT;
482 else if (strcsequal(p,"XENIX CORE"))
483 arch &= ( ARCH_WINNT | ARCH_OS2 );
484 else if (strcsequal(p,"Samba")) {
485 arch = ARCH_SAMBA;
486 break;
487 } else if (strcsequal(p,"POSIX 2")) {
488 arch = ARCH_CIFSFS;
489 break;
492 p += strlen(p) + 2;
495 /* CIFSFS can send one arch only, NT LM 0.12. */
496 if (Index == 1 && (arch & ARCH_CIFSFS)) {
497 arch = ARCH_CIFSFS;
500 switch ( arch ) {
501 case ARCH_CIFSFS:
502 set_remote_arch(RA_CIFSFS);
503 break;
504 case ARCH_SAMBA:
505 set_remote_arch(RA_SAMBA);
506 break;
507 case ARCH_WFWG:
508 set_remote_arch(RA_WFWG);
509 break;
510 case ARCH_WIN95:
511 set_remote_arch(RA_WIN95);
512 break;
513 case ARCH_WINNT:
514 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
515 set_remote_arch(RA_WIN2K);
516 else
517 set_remote_arch(RA_WINNT);
518 break;
519 case ARCH_WIN2K:
520 set_remote_arch(RA_WIN2K);
521 break;
522 case ARCH_OS2:
523 set_remote_arch(RA_OS2);
524 break;
525 default:
526 set_remote_arch(RA_UNKNOWN);
527 break;
530 /* possibly reload - change of architecture */
531 reload_services(True);
533 /* moved from the netbios session setup code since we don't have that
534 when the client connects to port 445. Of course there is a small
535 window where we are listening to messages -- jerry */
537 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
539 /* Check for protocols, most desirable first */
540 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
541 p = smb_buf(inbuf)+1;
542 Index = 0;
543 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
544 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
545 while (p < (smb_buf(inbuf) + bcc)) {
546 if (strequal(p,supported_protocols[protocol].proto_name))
547 choice = Index;
548 Index++;
549 p += strlen(p) + 2;
551 if(choice != -1)
552 break;
555 SSVAL(outbuf,smb_vwv0,choice);
556 if(choice != -1) {
557 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
558 reload_services(True);
559 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
560 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
561 } else {
562 DEBUG(0,("No protocol supported !\n"));
564 SSVAL(outbuf,smb_vwv0,choice);
566 DEBUG( 5, ( "negprot index=%d\n", choice ) );
568 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
569 exit_server("SMB signing is required and client negotiated a downlevel protocol");
572 END_PROFILE(SMBnegprot);
573 return(outsize);