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.
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])
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;
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;
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);
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);
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)
173 const char *OIDs_krb5[] = {OID_KERBEROS5,
177 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
181 global_spnego_negotiated = True;
184 safe_strcpy((char *)guid, global_myname(), sizeof(guid)-1);
187 /* valgrind fixer... */
189 size_t sl = strlen(guid);
191 memset(&guid[sl], '\0', sizeof(guid)-sl);
195 strlower_m((char *)guid);
198 /* strangely enough, NT does not sent the single OID NTLMSSP when
199 not a ADS member, it sends no OIDs at all
201 we can't do this until we teach our sesssion setup parser to know
202 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
204 if (lp_security() != SEC_ADS) {
209 if (lp_security() != SEC_ADS) {
210 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
212 asprintf(&principal, "%s$@%s", guid, lp_realm());
213 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
216 memcpy(p, blob.data, blob.length);
218 data_blob_free(&blob);
222 /****************************************************************************
223 Reply for the nt protocol.
224 ****************************************************************************/
226 static int reply_nt1(char *inbuf, char *outbuf)
228 /* dual names + lock_and_read + nt SMBs + remote API calls */
229 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
230 CAP_LEVEL_II_OPLOCKS;
233 time_t t = time(NULL);
235 BOOL negotiate_spnego = False;
237 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
239 /* do spnego in user level security if the client
240 supports it and we can do encrypted passwords */
242 if (global_encrypted_passwords_negotiated &&
243 (lp_security() != SEC_SHARE) &&
245 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
246 negotiate_spnego = True;
247 capabilities |= CAP_EXTENDED_SECURITY;
250 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
252 if (lp_unix_extensions()) {
253 capabilities |= CAP_UNIX;
256 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
257 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
259 if (SMB_OFF_T_BITS == 64)
260 capabilities |= CAP_LARGE_FILES;
262 if (lp_readraw() && lp_writeraw())
263 capabilities |= CAP_RAW_MODE;
265 /* allow for disabling unicode */
267 capabilities |= CAP_UNICODE;
269 if (lp_nt_status_support())
270 capabilities |= CAP_STATUS32;
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 set_message(outbuf,17,0,True);
282 SCVAL(outbuf,smb_vwv1,secword);
284 Protocol = PROTOCOL_NT1;
286 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
287 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
288 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
289 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
290 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
291 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
292 put_long_date(outbuf+smb_vwv11+1,t);
293 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
295 p = q = smb_buf(outbuf);
296 if (!negotiate_spnego) {
297 /* Create a token value and add it to the outgoing packet. */
298 if (global_encrypted_passwords_negotiated) {
299 /* note that we do not send a challenge at all if
300 we are using plaintext */
302 SSVALS(outbuf,smb_vwv16+1,8);
305 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
306 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
307 DEBUG(3,("not using SPNEGO\n"));
309 int len = negprot_spnego(p);
311 SSVALS(outbuf,smb_vwv16+1,len);
313 DEBUG(3,("using SPNEGO\n"));
316 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
317 set_message_end(outbuf, p);
319 return (smb_len(outbuf)+4);
322 /* these are the protocol lists used for auto architecture detection:
325 protocol [PC NETWORK PROGRAM 1.0]
326 protocol [XENIX CORE]
327 protocol [MICROSOFT NETWORKS 1.03]
329 protocol [Windows for Workgroups 3.1a]
332 protocol [NT LM 0.12]
335 protocol [PC NETWORK PROGRAM 1.0]
336 protocol [XENIX CORE]
337 protocol [MICROSOFT NETWORKS 1.03]
339 protocol [Windows for Workgroups 3.1a]
342 protocol [NT LM 0.12]
345 protocol [PC NETWORK PROGRAM 1.0]
347 protocol [Windows for Workgroups 3.1a]
350 protocol [NT LM 0.12]
353 protocol [PC NETWORK PROGRAM 1.0]
354 protocol [XENIX CORE]
361 * Modified to recognize the architecture of the remote machine better.
363 * This appears to be the matrix of which protocol is used by which
365 Protocol WfWg Win95 WinNT Win2K OS/2
366 PC NETWORK PROGRAM 1.0 1 1 1 1 1
368 MICROSOFT NETWORKS 3.0 2 2
370 MICROSOFT NETWORKS 1.03 3
373 Windows for Workgroups 3.1a 5 5 5 3
378 * tim@fsg.com 09/29/95
379 * Win2K added by matty 17/7/99
382 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
383 #define ARCH_WIN95 0x2
384 #define ARCH_WINNT 0x4
385 #define ARCH_WIN2K 0xC /* Win2K is like NT */
386 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
387 #define ARCH_SAMBA 0x20
389 #define ARCH_ALL 0x3F
391 /* List of supported protocols, most desired first */
392 static const struct {
393 const char *proto_name;
394 const char *short_name;
395 int (*proto_reply_fn)(char *, char *);
397 } supported_protocols[] = {
398 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
399 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
400 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
401 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
402 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
403 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
404 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
405 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
406 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
410 /****************************************************************************
412 ****************************************************************************/
414 int reply_negprot(connection_struct *conn,
415 char *inbuf,char *outbuf, int dum_size,
418 int outsize = set_message(outbuf,1,0,True);
423 int bcc = SVAL(smb_buf(inbuf),-2);
426 static BOOL done_negprot = False;
428 START_PROFILE(SMBnegprot);
431 END_PROFILE(SMBnegprot);
432 exit_server("multiple negprot's are not permitted");
436 p = smb_buf(inbuf)+1;
437 while (p < (smb_buf(inbuf) + bcc)) {
439 DEBUG(3,("Requested protocol [%s]\n",p));
440 if (strcsequal(p,"Windows for Workgroups 3.1a"))
441 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
442 else if (strcsequal(p,"DOS LM1.2X002"))
443 arch &= ( ARCH_WFWG | ARCH_WIN95 );
444 else if (strcsequal(p,"DOS LANMAN2.1"))
445 arch &= ( ARCH_WFWG | ARCH_WIN95 );
446 else if (strcsequal(p,"NT LM 0.12"))
447 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
448 else if (strcsequal(p,"LANMAN2.1"))
449 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
450 else if (strcsequal(p,"LM1.2X002"))
451 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
452 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
454 else if (strcsequal(p,"XENIX CORE"))
455 arch &= ( ARCH_WINNT | ARCH_OS2 );
456 else if (strcsequal(p,"Samba")) {
466 set_remote_arch(RA_SAMBA);
469 set_remote_arch(RA_WFWG);
472 set_remote_arch(RA_WIN95);
475 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
476 set_remote_arch(RA_WIN2K);
478 set_remote_arch(RA_WINNT);
481 set_remote_arch(RA_WIN2K);
484 set_remote_arch(RA_OS2);
487 set_remote_arch(RA_UNKNOWN);
491 /* possibly reload - change of architecture */
492 reload_services(True);
494 /* Check for protocols, most desirable first */
495 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
496 p = smb_buf(inbuf)+1;
498 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
499 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
500 while (p < (smb_buf(inbuf) + bcc)) {
501 if (strequal(p,supported_protocols[protocol].proto_name))
510 SSVAL(outbuf,smb_vwv0,choice);
512 extern fstring remote_proto;
513 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
514 reload_services(True);
515 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
516 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
518 DEBUG(0,("No protocol supported !\n"));
520 SSVAL(outbuf,smb_vwv0,choice);
522 DEBUG( 5, ( "negprot index=%d\n", choice ) );
524 END_PROFILE(SMBnegprot);