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 extern fstring global_myworkgroup;
26 extern fstring remote_machine;
27 BOOL global_encrypted_passwords_negotiated = False;
28 BOOL global_spnego_negotiated = False;
29 struct auth_context *negprot_global_auth_context = NULL;
31 static void get_challenge(char buff[8])
34 const uint8 *cryptkey;
36 /* We might be called more than once, muliple negprots are premitted */
37 if (negprot_global_auth_context) {
38 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
39 (negprot_global_auth_context->free)(&negprot_global_auth_context);
42 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
43 if (!NT_STATUS_IS_OK(nt_status = make_auth_context_subsystem(&negprot_global_auth_context))) {
44 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
45 smb_panic("cannot make_negprot_global_auth_context!\n");
47 DEBUG(10, ("get challenge: getting challenge\n"));
48 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
49 memcpy(buff, cryptkey, 8);
52 /****************************************************************************
53 Reply for the core protocol.
54 ****************************************************************************/
56 static int reply_corep(char *inbuf, char *outbuf)
58 int outsize = set_message(outbuf,1,0,True);
60 Protocol = PROTOCOL_CORE;
65 /****************************************************************************
66 Reply for the coreplus protocol.
67 ****************************************************************************/
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;
84 /****************************************************************************
85 Reply for the lanman 1.0 protocol.
86 ****************************************************************************/
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)
97 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
98 if (global_encrypted_passwords_negotiated)
99 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
101 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
102 SSVAL(outbuf,smb_vwv1,secword);
103 /* Create a token value and add it to the outgoing packet. */
104 if (global_encrypted_passwords_negotiated) {
105 get_challenge(smb_buf(outbuf));
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));
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)
172 extern pstring global_myname;
174 const char *OIDs_krb5[] = {OID_NTLMSSP,
178 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
182 global_spnego_negotiated = True;
185 safe_strcpy((char *)guid, global_myname, 16);
186 strlower((char *)guid);
189 /* strangely enough, NT does not sent the single OID NTLMSSP when
190 not a ADS member, it sends no OIDs at all
192 we can't do this until we teach our sesssion setup parser to know
193 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
195 if (lp_security() != SEC_ADS) {
200 if (lp_security() != SEC_ADS) {
201 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
204 ads = ads_init_simple();
205 /* win2000 uses host$@REALM, which we will probably use eventually,
206 but for now this works */
207 asprintf(&principal, "HOST/%s@%s", guid, ads->realm);
208 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
212 memcpy(p, blob.data, blob.length);
214 data_blob_free(&blob);
218 /****************************************************************************
219 Reply for the nt protocol.
220 ****************************************************************************/
222 static int reply_nt1(char *inbuf, char *outbuf)
224 /* dual names + lock_and_read + nt SMBs + remote API calls */
225 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
226 CAP_LEVEL_II_OPLOCKS;
229 time_t t = time(NULL);
231 BOOL negotiate_spnego = False;
233 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
235 /* do spnego in user level security if the client
236 supports it and we can do encrypted passwords */
238 if (global_encrypted_passwords_negotiated &&
239 (lp_security() != SEC_SHARE) &&
241 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
242 negotiate_spnego = True;
243 capabilities |= CAP_EXTENDED_SECURITY;
246 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNIX;
248 if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
249 capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
251 if (SMB_OFF_T_BITS == 64)
252 capabilities |= CAP_LARGE_FILES;
254 if (lp_readraw() && lp_writeraw())
255 capabilities |= CAP_RAW_MODE;
257 /* allow for disabling unicode */
259 capabilities |= CAP_UNICODE;
261 if (lp_nt_status_support())
262 capabilities |= CAP_STATUS32;
265 capabilities |= CAP_DFS;
267 if (lp_security() >= SEC_USER)
268 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
269 if (global_encrypted_passwords_negotiated)
270 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
272 set_message(outbuf,17,0,True);
274 SCVAL(outbuf,smb_vwv1,secword);
276 Protocol = PROTOCOL_NT1;
278 SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
279 SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
280 SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
281 SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
282 SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
283 SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
284 put_long_date(outbuf+smb_vwv11+1,t);
285 SSVALS(outbuf,smb_vwv15+1,TimeDiff(t)/60);
287 p = q = smb_buf(outbuf);
288 if (!negotiate_spnego) {
289 /* Create a token value and add it to the outgoing packet. */
290 if (global_encrypted_passwords_negotiated) {
291 /* note that we do not send a challenge at all if
292 we are using plaintext */
294 SSVALS(outbuf,smb_vwv16+1,8);
297 p += srvstr_push(outbuf, p, global_myworkgroup, -1,
298 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
299 DEBUG(3,("not using SPNEGO\n"));
301 int len = negprot_spnego(p);
303 SSVALS(outbuf,smb_vwv16+1,len);
305 DEBUG(3,("using SPNEGO\n"));
308 SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
309 set_message_end(outbuf, p);
311 return (smb_len(outbuf)+4);
314 /* these are the protocol lists used for auto architecture detection:
317 protocol [PC NETWORK PROGRAM 1.0]
318 protocol [XENIX CORE]
319 protocol [MICROSOFT NETWORKS 1.03]
321 protocol [Windows for Workgroups 3.1a]
324 protocol [NT LM 0.12]
327 protocol [PC NETWORK PROGRAM 1.0]
328 protocol [XENIX CORE]
329 protocol [MICROSOFT NETWORKS 1.03]
331 protocol [Windows for Workgroups 3.1a]
334 protocol [NT LM 0.12]
337 protocol [PC NETWORK PROGRAM 1.0]
339 protocol [Windows for Workgroups 3.1a]
342 protocol [NT LM 0.12]
345 protocol [PC NETWORK PROGRAM 1.0]
346 protocol [XENIX CORE]
353 * Modified to recognize the architecture of the remote machine better.
355 * This appears to be the matrix of which protocol is used by which
357 Protocol WfWg Win95 WinNT Win2K OS/2
358 PC NETWORK PROGRAM 1.0 1 1 1 1 1
360 MICROSOFT NETWORKS 3.0 2 2
362 MICROSOFT NETWORKS 1.03 3
365 Windows for Workgroups 3.1a 5 5 5 3
370 * tim@fsg.com 09/29/95
371 * Win2K added by matty 17/7/99
374 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
375 #define ARCH_WIN95 0x2
376 #define ARCH_WINNT 0x4
377 #define ARCH_WIN2K 0xC /* Win2K is like NT */
378 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
379 #define ARCH_SAMBA 0x20
381 #define ARCH_ALL 0x3F
383 /* List of supported protocols, most desired first */
387 int (*proto_reply_fn)(char *, char *);
389 } supported_protocols[] = {
390 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
391 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
392 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
393 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
394 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
395 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
396 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
397 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
398 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
402 /****************************************************************************
404 ****************************************************************************/
406 int reply_negprot(connection_struct *conn,
407 char *inbuf,char *outbuf, int dum_size,
410 int outsize = set_message(outbuf,1,0,True);
415 int bcc = SVAL(smb_buf(inbuf),-2);
418 static BOOL done_negprot = False;
420 START_PROFILE(SMBnegprot);
423 END_PROFILE(SMBnegprot);
424 exit_server("multiple negprot's are not permitted");
428 p = smb_buf(inbuf)+1;
429 while (p < (smb_buf(inbuf) + bcc)) {
431 DEBUG(3,("Requested protocol [%s]\n",p));
432 if (strcsequal(p,"Windows for Workgroups 3.1a"))
433 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
434 else if (strcsequal(p,"DOS LM1.2X002"))
435 arch &= ( ARCH_WFWG | ARCH_WIN95 );
436 else if (strcsequal(p,"DOS LANMAN2.1"))
437 arch &= ( ARCH_WFWG | ARCH_WIN95 );
438 else if (strcsequal(p,"NT LM 0.12"))
439 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
440 else if (strcsequal(p,"LANMAN2.1"))
441 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
442 else if (strcsequal(p,"LM1.2X002"))
443 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
444 else if (strcsequal(p,"MICROSOFT NETWORKS 1.03"))
446 else if (strcsequal(p,"XENIX CORE"))
447 arch &= ( ARCH_WINNT | ARCH_OS2 );
448 else if (strcsequal(p,"Samba")) {
458 set_remote_arch(RA_SAMBA);
461 set_remote_arch(RA_WFWG);
464 set_remote_arch(RA_WIN95);
467 if(SVAL(inbuf,smb_flg2)==FLAGS2_WIN2K_SIGNATURE)
468 set_remote_arch(RA_WIN2K);
470 set_remote_arch(RA_WINNT);
473 set_remote_arch(RA_WIN2K);
476 set_remote_arch(RA_OS2);
479 set_remote_arch(RA_UNKNOWN);
483 /* possibly reload - change of architecture */
484 reload_services(True);
486 /* Check for protocols, most desirable first */
487 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
488 p = smb_buf(inbuf)+1;
490 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
491 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
492 while (p < (smb_buf(inbuf) + bcc)) {
493 if (strequal(p,supported_protocols[protocol].proto_name))
502 SSVAL(outbuf,smb_vwv0,choice);
504 extern fstring remote_proto;
505 fstrcpy(remote_proto,supported_protocols[protocol].short_name);
506 reload_services(True);
507 outsize = supported_protocols[protocol].proto_reply_fn(inbuf, outbuf);
508 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
510 DEBUG(0,("No protocol supported !\n"));
512 SSVAL(outbuf,smb_vwv0,choice);
514 DEBUG( 5, ( "negprot index=%d\n", choice ) );
516 END_PROFILE(SMBnegprot);