2 Unix SMB/CIFS implementation.
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.
23 extern fstring remote_proto;
24 extern enum protocol_types Protocol;
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])
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;
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;
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);
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);
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)
176 const char *OIDs_krb5[] = {OID_KERBEROS5,
180 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
184 global_spnego_negotiated = True;
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((char *)guid, dos_name, sizeof(guid)-1);
194 /* valgrind fixer... */
196 size_t sl = strlen(guid);
198 memset(&guid[sl], '\0', sizeof(guid)-sl);
203 /* strangely enough, NT does not sent the single OID NTLMSSP when
204 not a ADS member, it sends no OIDs at all
206 we can't do this until we teach our sesssion setup parser to know
207 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
209 if (lp_security() != SEC_ADS) {
214 if (lp_security() != SEC_ADS) {
215 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
217 asprintf(&principal, "%s$@%s", guid, lp_realm());
218 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
221 memcpy(p, blob.data, blob.length);
223 data_blob_free(&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;
238 time_t t = time(NULL);
240 BOOL negotiate_spnego = False;
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) &&
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;
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();
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,TimeDiff(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 */
323 SSVALS(outbuf,smb_vwv16+1,8);
326 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
327 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
328 DEBUG(3,("not using SPNEGO\n"));
330 int len = negprot_spnego(p);
332 SSVALS(outbuf,smb_vwv16+1,len);
334 DEBUG(3,("using SPNEGO\n"));
337 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
338 set_message_end(outbuf, p);
340 return (smb_len(outbuf)+4);
343 /* these are the protocol lists used for auto architecture detection:
346 protocol [PC NETWORK PROGRAM 1.0]
347 protocol [XENIX CORE]
348 protocol [MICROSOFT NETWORKS 1.03]
350 protocol [Windows for Workgroups 3.1a]
353 protocol [NT LM 0.12]
356 protocol [PC NETWORK PROGRAM 1.0]
357 protocol [XENIX CORE]
358 protocol [MICROSOFT NETWORKS 1.03]
360 protocol [Windows for Workgroups 3.1a]
363 protocol [NT LM 0.12]
366 protocol [PC NETWORK PROGRAM 1.0]
368 protocol [Windows for Workgroups 3.1a]
371 protocol [NT LM 0.12]
374 protocol [PC NETWORK PROGRAM 1.0]
375 protocol [XENIX CORE]
382 * Modified to recognize the architecture of the remote machine better.
384 * This appears to be the matrix of which protocol is used by which
386 Protocol WfWg Win95 WinNT Win2K OS/2
387 PC NETWORK PROGRAM 1.0 1 1 1 1 1
389 MICROSOFT NETWORKS 3.0 2 2
391 MICROSOFT NETWORKS 1.03 3
394 Windows for Workgroups 3.1a 5 5 5 3
399 * tim@fsg.com 09/29/95
400 * Win2K added by matty 17/7/99
403 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
404 #define ARCH_WIN95 0x2
405 #define ARCH_WINNT 0x4
406 #define ARCH_WIN2K 0xC /* Win2K is like NT */
407 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
408 #define ARCH_SAMBA 0x20
409 #define ARCH_CIFSFS 0x40
411 #define ARCH_ALL 0x7F
413 /* List of supported protocols, most desired first */
414 static const struct {
415 const char *proto_name;
416 const char *short_name;
417 int (*proto_reply_fn)(char *, char *);
419 } supported_protocols[] = {
420 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
421 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
422 {"POSIX 2", "NT1", reply_nt1, PROTOCOL_NT1},
423 {"LANMAN2.1", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
424 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
425 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
426 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
427 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
428 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
429 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
430 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
434 /****************************************************************************
436 ****************************************************************************/
438 int reply_negprot(connection_struct *conn,
439 char *inbuf,char *outbuf, int dum_size,
442 int outsize = set_message(outbuf,1,0,True);
447 int bcc = SVAL(smb_buf(inbuf),-2);
450 static BOOL done_negprot = False;
452 START_PROFILE(SMBnegprot);
455 END_PROFILE(SMBnegprot);
456 exit_server("multiple negprot's are not permitted");
460 p = smb_buf(inbuf)+1;
461 while (p < (smb_buf(inbuf) + bcc)) {
463 DEBUG(3,("Requested protocol [%s]\n",p));
464 if (strcsequal(p,"Windows for Workgroups 3.1a"))
465 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
466 else if (strcsequal(p,"DOS LM1.2X002"))
467 arch &= ( ARCH_WFWG | ARCH_WIN95 );
468 else if (strcsequal(p,"DOS LANMAN2.1"))
469 arch &= ( ARCH_WFWG | ARCH_WIN95 );
470 else if (strcsequal(p,"NT LM 0.12"))
471 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K | ARCH_CIFSFS);
472 else if (strcsequal(p,"LANMAN2.1"))
473 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
474 else if (strcsequal(p,"LM1.2X002"))
475 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
476 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
478 else if (strcsequal(p,"XENIX CORE"))
479 arch &= ( ARCH_WINNT | ARCH_OS2 );
480 else if (strcsequal(p,"Samba")) {
483 } else if (strcsequal(p,"POSIX 2")) {
491 /* CIFSFS can send one arch only, NT LM 0.12. */
492 if (Index == 1 && (arch & ARCH_CIFSFS)) {
498 set_remote_arch(RA_CIFSFS);
501 set_remote_arch(RA_SAMBA);
504 set_remote_arch(RA_WFWG);
507 set_remote_arch(RA_WIN95);
510 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
511 set_remote_arch(RA_WIN2K);
513 set_remote_arch(RA_WINNT);
516 set_remote_arch(RA_WIN2K);
519 set_remote_arch(RA_OS2);
522 set_remote_arch(RA_UNKNOWN);
526 /* possibly reload - change of architecture */
527 reload_services(True);
529 /* moved from the netbios session setup code since we don't have that
530 when the client connects to port 445. Of course there is a small
531 window where we are listening to messages -- jerry */
533 claim_connection(NULL,"",0,True,FLAG_MSG_GENERAL|FLAG_MSG_SMBD|FLAG_MSG_PRINT_GENERAL);
535 /* Check for protocols, most desirable first */
536 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
537 p = smb_buf(inbuf)+1;
539 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
540 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
541 while (p < (smb_buf(inbuf) + bcc)) {
542 if (strequal(p,supported_protocols[protocol].proto_name))
551 SSVAL(outbuf,smb_vwv0,choice);
553 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
554 reload_services(True);
555 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
556 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
558 DEBUG(0,("No protocol supported !\n"));
560 SSVAL(outbuf,smb_vwv0,choice);
562 DEBUG( 5, ( "negprot index=%d\n", choice ) );
564 if ((lp_server_signing() == Required) && (Protocol < PROTOCOL_NT1)) {
565 exit_server("SMB signing is required and client negotiated a downlevel protocol");
568 END_PROFILE(SMBnegprot);