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);
188 size_t sl = strlen(guid);
190 memset(&guid[sl], '\0', sizeof(guid)-sl);
194 strlower((char *)guid);
197 /* strangely enough, NT does not sent the single OID NTLMSSP when
198 not a ADS member, it sends no OIDs at all
200 we can't do this until we teach our sesssion setup parser to know
201 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
203 if (lp_security() != SEC_ADS) {
208 if (lp_security() != SEC_ADS) {
209 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
211 asprintf(&principal, "%s$@%s", guid, lp_realm());
212 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
215 memcpy(p, blob.data, blob.length);
217 data_blob_free(&blob);
221 /****************************************************************************
222 Reply for the nt protocol.
223 ****************************************************************************/
225 static int reply_nt1(char *inbuf, char *outbuf)
227 /* dual names + lock_and_read + nt SMBs + remote API calls */
228 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
229 CAP_LEVEL_II_OPLOCKS;
232 time_t t = time(NULL);
234 BOOL negotiate_spnego = False;
236 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
238 /* do spnego in user level security if the client
239 supports it and we can do encrypted passwords */
241 if (global_encrypted_passwords_negotiated &&
242 (lp_security() != SEC_SHARE) &&
244 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
245 negotiate_spnego = True;
246 capabilities |= CAP_EXTENDED_SECURITY;
249 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
251 if (lp_unix_extensions()) {
252 capabilities |= CAP_UNIX;
255 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
256 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
258 if (SMB_OFF_T_BITS == 64)
259 capabilities |= CAP_LARGE_FILES;
261 if (lp_readraw() && lp_writeraw())
262 capabilities |= CAP_RAW_MODE;
264 /* allow for disabling unicode */
266 capabilities |= CAP_UNICODE;
268 if (lp_nt_status_support())
269 capabilities |= CAP_STATUS32;
272 capabilities |= CAP_DFS;
274 if (lp_security() >= SEC_USER)
275 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
276 if (global_encrypted_passwords_negotiated)
277 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
279 set_message(outbuf,17,0,True);
281 SCVAL(outbuf,smb_vwv1,secword);
283 Protocol = PROTOCOL_NT1;
285 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
286 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
287 SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
288 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
289 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
290 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
291 put_long_date(outbuf+smb_vwv11+1,t);
292 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
294 p = q = smb_buf(outbuf);
295 if (!negotiate_spnego) {
296 /* Create a token value and add it to the outgoing packet. */
297 if (global_encrypted_passwords_negotiated) {
298 /* note that we do not send a challenge at all if
299 we are using plaintext */
301 SSVALS(outbuf,smb_vwv16+1,8);
304 p += srvstr_push(outbuf, p, lp_workgroup(), -1,
305 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
306 DEBUG(3,("not using SPNEGO\n"));
308 int len = negprot_spnego(p);
310 SSVALS(outbuf,smb_vwv16+1,len);
312 DEBUG(3,("using SPNEGO\n"));
315 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
316 set_message_end(outbuf, p);
318 return (smb_len(outbuf)+4);
321 /* these are the protocol lists used for auto architecture detection:
324 protocol [PC NETWORK PROGRAM 1.0]
325 protocol [XENIX CORE]
326 protocol [MICROSOFT NETWORKS 1.03]
328 protocol [Windows for Workgroups 3.1a]
331 protocol [NT LM 0.12]
334 protocol [PC NETWORK PROGRAM 1.0]
335 protocol [XENIX CORE]
336 protocol [MICROSOFT NETWORKS 1.03]
338 protocol [Windows for Workgroups 3.1a]
341 protocol [NT LM 0.12]
344 protocol [PC NETWORK PROGRAM 1.0]
346 protocol [Windows for Workgroups 3.1a]
349 protocol [NT LM 0.12]
352 protocol [PC NETWORK PROGRAM 1.0]
353 protocol [XENIX CORE]
360 * Modified to recognize the architecture of the remote machine better.
362 * This appears to be the matrix of which protocol is used by which
364 Protocol WfWg Win95 WinNT Win2K OS/2
365 PC NETWORK PROGRAM 1.0 1 1 1 1 1
367 MICROSOFT NETWORKS 3.0 2 2
369 MICROSOFT NETWORKS 1.03 3
372 Windows for Workgroups 3.1a 5 5 5 3
377 * tim@fsg.com 09/29/95
378 * Win2K added by matty 17/7/99
381 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
382 #define ARCH_WIN95 0x2
383 #define ARCH_WINNT 0x4
384 #define ARCH_WIN2K 0xC /* Win2K is like NT */
385 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
386 #define ARCH_SAMBA 0x20
388 #define ARCH_ALL 0x3F
390 /* List of supported protocols, most desired first */
391 static const struct {
392 const char *proto_name;
393 const char *short_name;
394 int (*proto_reply_fn)(char *, char *);
396 } supported_protocols[] = {
397 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
398 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
399 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
400 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
401 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
402 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
403 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
404 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
405 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
409 /****************************************************************************
411 ****************************************************************************/
413 int reply_negprot(connection_struct *conn,
414 char *inbuf,char *outbuf, int dum_size,
417 int outsize = set_message(outbuf,1,0,True);
422 int bcc = SVAL(smb_buf(inbuf),-2);
425 static BOOL done_negprot = False;
427 START_PROFILE(SMBnegprot);
430 END_PROFILE(SMBnegprot);
431 exit_server("multiple negprot's are not permitted");
435 p = smb_buf(inbuf)+1;
436 while (p < (smb_buf(inbuf) + bcc)) {
438 DEBUG(3,("Requested protocol [%s]\n",p));
439 if (strcsequal(p,"Windows for Workgroups 3.1a"))
440 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
441 else if (strcsequal(p,"DOS LM1.2X002"))
442 arch &= ( ARCH_WFWG | ARCH_WIN95 );
443 else if (strcsequal(p,"DOS LANMAN2.1"))
444 arch &= ( ARCH_WFWG | ARCH_WIN95 );
445 else if (strcsequal(p,"NT LM 0.12"))
446 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
447 else if (strcsequal(p,"LANMAN2.1"))
448 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
449 else if (strcsequal(p,"LM1.2X002"))
450 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
451 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
453 else if (strcsequal(p,"XENIX CORE"))
454 arch &= ( ARCH_WINNT | ARCH_OS2 );
455 else if (strcsequal(p,"Samba")) {
465 set_remote_arch(RA_SAMBA);
468 set_remote_arch(RA_WFWG);
471 set_remote_arch(RA_WIN95);
474 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
475 set_remote_arch(RA_WIN2K);
477 set_remote_arch(RA_WINNT);
480 set_remote_arch(RA_WIN2K);
483 set_remote_arch(RA_OS2);
486 set_remote_arch(RA_UNKNOWN);
490 /* possibly reload - change of architecture */
491 reload_services(True);
493 /* Check for protocols, most desirable first */
494 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
495 p = smb_buf(inbuf)+1;
497 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
498 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
499 while (p < (smb_buf(inbuf) + bcc)) {
500 if (strequal(p,supported_protocols[protocol].proto_name))
509 SSVAL(outbuf,smb_vwv0,choice);
511 extern fstring remote_proto;
512 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
513 reload_services(True);
514 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
515 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
517 DEBUG(0,("No protocol supported !\n"));
519 SSVAL(outbuf,smb_vwv0,choice);
521 DEBUG( 5, ( "negprot index=%d\n", choice ) );
523 END_PROFILE(SMBnegprot);