2 Unix SMB/Netbios implementation.
5 Copyright (C) Andrew Tridgell 1992-1998
7 This program is free software; you can redistribute it and/or modify
8 it under the terms of the GNU General Public License as published by
9 the Free Software Foundation; either version 2 of the License, or
10 (at your option) any later version.
12 This program is distributed in the hope that it will be useful,
13 but WITHOUT ANY WARRANTY; without even the implied warranty of
14 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 GNU General Public License for more details.
17 You should have received a copy of the GNU General Public License
18 along with this program; if not, write to the Free Software
19 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
26 extern fstring global_myworkgroup;
27 extern fstring remote_machine;
28 BOOL global_encrypted_passwords_negotiated = False;
29 BOOL global_spnego_negotiated = False;
30 struct auth_context *negprot_global_auth_context = NULL;
32 static void get_challange(char buff[8])
35 const uint8 *cryptkey;
37 /* We might be called more than once, muliple negprots are premitted */
38 if (negprot_global_auth_context) {
39 DEBUG(3, ("get challange: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
40 negprot_global_auth_context->free(&negprot_global_auth_context);
43 DEBUG(10, ("get challange: creating negprot_global_auth_context\n"));
44 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
45 DEBUG(0, ("make_auth_context_subsystem returned %s", get_nt_error_msg(nt_status)));
46 smb_panic("cannot make_negprot_global_auth_context!\n");
48 DEBUG(10, ("get challange: getting challange\n"));
49 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
50 memcpy(buff, cryptkey, 8);
53 /****************************************************************************
54 reply for the core protocol
55 ****************************************************************************/
56 static int reply_corep(char *inbuf, char *outbuf)
58 int outsize = set_message(outbuf,1,0,True);
60 Protocol = PROTOCOL_CORE;
66 /****************************************************************************
67 reply for the coreplus protocol
68 ****************************************************************************/
69 static int reply_coreplus(char *inbuf, char *outbuf)
71 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
72 int outsize = set_message(outbuf,13,0,True);
73 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
74 readbraw and writebraw (possibly) */
75 /* Reply, SMBlockread, SMBwritelock supported. */
76 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
77 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
79 Protocol = PROTOCOL_COREPLUS;
85 /****************************************************************************
86 reply for the lanman 1.0 protocol
87 ****************************************************************************/
88 static int reply_lanman1(char *inbuf, char *outbuf)
90 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
92 time_t t = time(NULL);
94 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
96 if (lp_security()>=SEC_USER) secword |= 1;
97 if (global_encrypted_passwords_negotiated) secword |= 2;
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_challange(smb_buf(outbuf));
106 Protocol = PROTOCOL_LANMAN1;
108 /* Reply, SMBlockread, SMBwritelock supported. */
109 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
110 SSVAL(outbuf,smb_vwv2,max_recv);
111 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
112 SSVAL(outbuf,smb_vwv4,1);
113 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
114 readbraw writebraw (possibly) */
115 SIVAL(outbuf,smb_vwv6,sys_getpid());
116 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
118 put_dos_date(outbuf,smb_vwv8,t);
120 return (smb_len(outbuf)+4);
124 /****************************************************************************
125 reply for the lanman 2.0 protocol
126 ****************************************************************************/
127 static int reply_lanman2(char *inbuf, char *outbuf)
129 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
131 time_t t = time(NULL);
133 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
135 if (lp_security()>=SEC_USER) secword |= 1;
136 if (global_encrypted_passwords_negotiated) secword |= 2;
138 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
139 SSVAL(outbuf,smb_vwv1,secword);
140 SIVAL(outbuf,smb_vwv6,sys_getpid());
142 /* Create a token value and add it to the outgoing packet. */
143 if (global_encrypted_passwords_negotiated) {
144 get_challange(smb_buf(outbuf));
147 Protocol = PROTOCOL_LANMAN2;
149 /* Reply, SMBlockread, SMBwritelock supported. */
150 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
151 SSVAL(outbuf,smb_vwv2,max_recv);
152 SSVAL(outbuf,smb_vwv3,lp_maxmux());
153 SSVAL(outbuf,smb_vwv4,1);
154 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
155 SSVAL(outbuf,smb_vwv10, TimeDiff(t)/60);
156 put_dos_date(outbuf,smb_vwv8,t);
158 return (smb_len(outbuf)+4);
164 generate the spnego negprot reply blob. Return the number of bytes used
166 static int negprot_spnego(char *p)
169 extern pstring global_myname;
171 const char *OIDs_krb5[] = {OID_NTLMSSP,
175 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
179 global_spnego_negotiated = True;
182 safe_strcpy((char *)guid, global_myname, 16);
183 strlower((char *)guid);
186 /* strangely enough, NT does not sent the single OID NTLMSSP when
187 not a ADS member, it sends no OIDs at all
189 we can't do this until we teach our sesssion setup parser to know
190 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
192 if (lp_security() != SEC_ADS) {
199 ads = ads_init(NULL, NULL, NULL, NULL);
201 /* win2000 uses host$@REALM, which we will probably use eventually,
202 but for now this works */
203 asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
204 blob = spnego_gen_negTokenInit(guid,
205 lp_security()==SEC_ADS ? OIDs_krb5 : OIDs_plain,
210 memcpy(p, blob.data, blob.length);
212 data_blob_free(&blob);
218 /****************************************************************************
219 reply for the nt protocol
220 ****************************************************************************/
221 static int reply_nt1(char *inbuf, char *outbuf)
223 /* dual names + lock_and_read + nt SMBs + remote API calls */
224 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
225 CAP_LEVEL_II_OPLOCKS|CAP_STATUS32;
228 time_t t = time(NULL);
230 BOOL negotiate_spnego = False;
232 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
234 /* do spnego in user level security if the client
235 supports it and we can do encrypted passwords */
237 if (global_encrypted_passwords_negotiated &&
238 (lp_security() != SEC_SHARE) &&
240 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
241 negotiate_spnego = True;
242 capabilities |= CAP_EXTENDED_SECURITY;
245 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
247 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64)) {
248 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
251 if (SMB_OFF_T_BITS == 64) {
252 capabilities |= CAP_LARGE_FILES;
255 if (lp_readraw() && lp_writeraw()) {
256 capabilities |= CAP_RAW_MODE;
259 /* allow for disabling unicode */
261 capabilities |= CAP_UNICODE;
265 capabilities |= CAP_DFS;
267 if (lp_security() >= SEC_USER) secword |= 1;
268 if (global_encrypted_passwords_negotiated) secword |= 2;
270 set_message(outbuf,17,0,True);
272 CVAL(outbuf,smb_vwv1) = secword;
274 Protocol = PROTOCOL_NT1;
276 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
277 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
278 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
279 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
280 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
281 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
282 put_long_date(outbuf+smb_vwv11+1,t);
283 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
285 p = q = smb_buf(outbuf);
286 if (!negotiate_spnego) {
287 /* Create a token value and add it to the outgoing packet. */
288 if (global_encrypted_passwords_negotiated) {
291 SSVALS(outbuf,smb_vwv16+1,8);
293 p += srvstr_push(outbuf, p, global_myworkgroup, -1,
294 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
295 DEBUG(3,("not using SPNEGO\n"));
297 int len = negprot_spnego(p);
299 SSVALS(outbuf,smb_vwv16+1,len);
301 DEBUG(3,("using SPNEGO\n"));
304 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
305 set_message_end(outbuf, p);
307 return (smb_len(outbuf)+4);
310 /* these are the protocol lists used for auto architecture detection:
313 protocol [PC NETWORK PROGRAM 1.0]
314 protocol [XENIX CORE]
315 protocol [MICROSOFT NETWORKS 1.03]
317 protocol [Windows for Workgroups 3.1a]
320 protocol [NT LM 0.12]
323 protocol [PC NETWORK PROGRAM 1.0]
324 protocol [XENIX CORE]
325 protocol [MICROSOFT NETWORKS 1.03]
327 protocol [Windows for Workgroups 3.1a]
330 protocol [NT LM 0.12]
333 protocol [PC NETWORK PROGRAM 1.0]
335 protocol [Windows for Workgroups 3.1a]
338 protocol [NT LM 0.12]
341 protocol [PC NETWORK PROGRAM 1.0]
342 protocol [XENIX CORE]
349 * Modified to recognize the architecture of the remote machine better.
351 * This appears to be the matrix of which protocol is used by which
353 Protocol WfWg Win95 WinNT Win2K OS/2
354 PC NETWORK PROGRAM 1.0 1 1 1 1 1
356 MICROSOFT NETWORKS 3.0 2 2
358 MICROSOFT NETWORKS 1.03 3
361 Windows for Workgroups 3.1a 5 5 5 3
366 * tim@fsg.com 09/29/95
367 * Win2K added by matty 17/7/99
370 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
371 #define ARCH_WIN95 0x2
372 #define ARCH_WINNT 0x4
373 #define ARCH_WIN2K 0xC /* Win2K is like NT */
374 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
375 #define ARCH_SAMBA 0x20
377 #define ARCH_ALL 0x3F
379 /* List of supported protocols, most desired first */
383 int (*proto_reply_fn)(char *, char *);
385 } supported_protocols[] = {
386 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
387 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
388 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
389 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
390 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
391 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
392 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
393 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
394 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
399 /****************************************************************************
401 ****************************************************************************/
402 int reply_negprot(connection_struct *conn,
403 char *inbuf,char *outbuf, int dum_size,
406 int outsize = set_message(outbuf,1,0,True);
411 int bcc = SVAL(smb_buf(inbuf),-2);
413 START_PROFILE(SMBnegprot);
415 p = smb_buf(inbuf)+1;
416 while (p < (smb_buf(inbuf) + bcc))
419 DEBUG(3,("Requested protocol [%s]\n",p));
420 if (strcsequal(p,"Windows for Workgroups 3.1a"))
421 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
422 else if (strcsequal(p,"DOS LM1.2X002"))
423 arch &= ( ARCH_WFWG | ARCH_WIN95 );
424 else if (strcsequal(p,"DOS LANMAN2.1"))
425 arch &= ( ARCH_WFWG | ARCH_WIN95 );
426 else if (strcsequal(p,"NT LM 0.12"))
427 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
428 else if (strcsequal(p,"LANMAN2.1"))
429 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
430 else if (strcsequal(p,"LM1.2X002"))
431 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
432 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
434 else if (strcsequal(p,"XENIX CORE"))
435 arch &= ( ARCH_WINNT | ARCH_OS2 );
436 else if (strcsequal(p,"Samba")) {
446 set_remote_arch(RA_SAMBA);
449 set_remote_arch(RA_WFWG);
452 set_remote_arch(RA_WIN95);
455 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
456 set_remote_arch(RA_WIN2K);
458 set_remote_arch(RA_WINNT);
461 set_remote_arch(RA_WIN2K);
464 set_remote_arch(RA_OS2);
467 set_remote_arch(RA_UNKNOWN);
471 /* possibly reload - change of architecture */
472 reload_services(True);
474 /* Check for protocols, most desirable first */
475 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++)
477 p = smb_buf(inbuf)+1;
479 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
480 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
481 while (p < (smb_buf(inbuf) + bcc))
483 if (strequal(p,supported_protocols[protocol].proto_name))
492 SSVAL(outbuf,smb_vwv0,choice);
494 extern fstring remote_proto;
495 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
496 reload_services(True);
497 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
498 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
501 DEBUG(0,("No protocol supported !\n"));
503 SSVAL(outbuf,smb_vwv0,choice);
505 DEBUG( 5, ( "negprot index=%d\n", choice ) );
507 END_PROFILE(SMBnegprot);