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 /* initialise the auth_context for this server and return the cryptkey */
24 static void get_challenge(struct server_context *smb, char buff[8])
27 const uint8_t *cryptkey;
29 /* muliple negprots are not premitted */
30 if (smb->negotiate.auth_context) {
31 DEBUG(3,("get challenge: is this a secondary negprot? auth_context is non-NULL!\n"));
32 smb_panic("secondary negprot");
35 DEBUG(10, ("get challenge: creating negprot_global_auth_context\n"));
37 nt_status = make_auth_context_subsystem(&smb->negotiate.auth_context);
39 if (!NT_STATUS_IS_OK(nt_status)) {
40 DEBUG(0, ("make_auth_context_subsystem returned %s", nt_errstr(nt_status)));
41 smb_panic("cannot make_negprot_global_auth_context!\n");
44 DEBUG(10, ("get challenge: getting challenge\n"));
45 cryptkey = smb->negotiate.auth_context->get_ntlm_challenge(smb->negotiate.auth_context);
46 memcpy(buff, cryptkey, 8);
49 /****************************************************************************
50 Reply for the core protocol.
51 ****************************************************************************/
52 static void reply_corep(struct request_context *req, uint16_t choice)
54 req_setup_reply(req, 1, 0);
56 SSVAL(req->out.vwv, VWV(0), choice);
58 req->smb->negotiate.protocol = PROTOCOL_CORE;
63 /****************************************************************************
64 Reply for the coreplus protocol.
65 this is quite incomplete - we only fill in a small part of the reply, but as nobody uses
66 this any more it probably doesn't matter
67 ****************************************************************************/
68 static void reply_coreplus(struct request_context *req, uint16_t choice)
70 uint16_t raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
72 req_setup_reply(req, 13, 0);
74 /* Reply, SMBlockread, SMBwritelock supported. */
75 SCVAL(req->out.hdr,HDR_FLG,
76 CVAL(req->out.hdr, HDR_FLG) | FLAG_SUPPORT_LOCKREAD);
78 SSVAL(req->out.vwv, VWV(0), choice);
79 SSVAL(req->out.vwv, VWV(1), 0x1); /* user level security, don't encrypt */
81 /* tell redirector we support
82 readbraw and writebraw (possibly) */
83 SSVAL(req->out.vwv, VWV(5), raw);
85 req->smb->negotiate.protocol = PROTOCOL_COREPLUS;
90 /****************************************************************************
91 Reply for the lanman 1.0 protocol.
92 ****************************************************************************/
93 static void reply_lanman1(struct request_context *req, uint16_t choice)
95 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
97 time_t t = req->request_time.tv_sec;
99 req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
101 if (lp_security() != SEC_SHARE)
102 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
104 if (req->smb->negotiate.encrypted_passwords)
105 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
107 req->smb->negotiate.protocol = PROTOCOL_LANMAN1;
109 req_setup_reply(req, 13, req->smb->negotiate.encrypted_passwords ? 8 : 0);
111 /* SMBlockread, SMBwritelock supported. */
112 SCVAL(req->out.hdr,HDR_FLG,
113 CVAL(req->out.hdr, HDR_FLG) | FLAG_SUPPORT_LOCKREAD);
115 SSVAL(req->out.vwv, VWV(0), choice);
116 SSVAL(req->out.vwv, VWV(1), secword);
117 SSVAL(req->out.vwv, VWV(2), req->smb->negotiate.max_recv);
118 SSVAL(req->out.vwv, VWV(3), lp_maxmux());
119 SSVAL(req->out.vwv, VWV(4), 1);
120 SSVAL(req->out.vwv, VWV(5), raw);
121 SIVAL(req->out.vwv, VWV(6), req->smb->pid);
122 srv_push_dos_date(req->smb, req->out.vwv, VWV(8), t);
123 SSVAL(req->out.vwv, VWV(10), req->smb->negotiate.zone_offset/60);
125 /* Create a token value and add it to the outgoing packet. */
126 if (req->smb->negotiate.encrypted_passwords) {
127 SSVAL(req->out.vwv, VWV(11), 8);
128 get_challenge(req->smb, req->out.data);
134 /****************************************************************************
135 Reply for the lanman 2.0 protocol.
136 ****************************************************************************/
137 static void reply_lanman2(struct request_context *req, uint16_t choice)
139 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
141 time_t t = req->request_time.tv_sec;
143 req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
145 if (lp_security() != SEC_SHARE)
146 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
148 if (req->smb->negotiate.encrypted_passwords)
149 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
151 req->smb->negotiate.protocol = PROTOCOL_LANMAN2;
153 req_setup_reply(req, 13, 0);
155 SSVAL(req->out.vwv, VWV(0), choice);
156 SSVAL(req->out.vwv, VWV(1), secword);
157 SSVAL(req->out.vwv, VWV(2), req->smb->negotiate.max_recv);
158 SSVAL(req->out.vwv, VWV(3), lp_maxmux());
159 SSVAL(req->out.vwv, VWV(4), 1);
160 SSVAL(req->out.vwv, VWV(5), raw);
161 SIVAL(req->out.vwv, VWV(6), req->smb->pid);
162 srv_push_dos_date(req->smb, req->out.vwv, VWV(8), t);
163 SSVAL(req->out.vwv, VWV(10), req->smb->negotiate.zone_offset/60);
165 /* Create a token value and add it to the outgoing packet. */
166 if (req->smb->negotiate.encrypted_passwords) {
167 SSVAL(req->out.vwv, VWV(11), 8);
168 req_grow_data(req, 8);
169 get_challenge(req->smb, req->out.data);
172 req_push_str(req, NULL, lp_workgroup(), -1, STR_TERMINATE);
179 /****************************************************************************
180 Generate the spnego negprot reply blob. Return the number of bytes used.
181 ****************************************************************************/
182 static DATA_BLOB negprot_spnego(struct server_context *smb)
186 const char *OIDs_krb5[] = {OID_KERBEROS5,
190 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
193 smb->negotiate.spnego_negotiated = True;
196 safe_strcpy((char *)guid, lp_netbios_name(), 16);
197 strlower((char *)guid);
200 /* strangely enough, NT does not send the single OID NTLMSSP when
201 not a ADS member, it sends no OIDs at all
203 we can't do this until we teach our sesssion setup parser to know
204 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
206 if (lp_security() != SEC_ADS) {
211 if (lp_security() != SEC_ADS) {
212 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
214 asprintf(&principal, "%s$@%s", guid, lp_realm());
215 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, principal);
223 /****************************************************************************
224 Reply for the nt protocol.
225 ****************************************************************************/
226 static void reply_nt1(struct request_context *req, uint16_t choice)
228 /* dual names + lock_and_read + nt SMBs + remote API calls */
231 time_t t = req->request_time.tv_sec;
233 BOOL negotiate_spnego = False;
235 unix_to_nt_time(&nttime, t);
238 CAP_NT_FIND | CAP_LOCK_AND_READ |
239 CAP_LEVEL_II_OPLOCKS | CAP_NT_SMBS | CAP_RPC_REMOTE_APIS;
241 req->smb->negotiate.encrypted_passwords = lp_encrypted_passwords();
243 /* do spnego in user level security if the client
244 supports it and we can do encrypted passwords */
246 if (req->smb->negotiate.encrypted_passwords &&
247 (lp_security() != SEC_SHARE) &&
249 (req->flags2 & FLAGS2_EXTENDED_SECURITY)) {
250 /* REWRITE negotiate_spnego = True;
251 capabilities |= CAP_EXTENDED_SECURITY;
255 if (lp_unix_extensions()) {
256 capabilities |= CAP_UNIX;
259 if (lp_large_readwrite()) {
260 capabilities |= CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS;
263 capabilities |= CAP_LARGE_FILES;
265 if (lp_readraw() && lp_writeraw()) {
266 capabilities |= CAP_RAW_MODE;
269 /* allow for disabling unicode */
271 capabilities |= CAP_UNICODE;
274 if (lp_nt_status_support()) {
275 capabilities |= CAP_STATUS32;
278 if (lp_host_msdfs()) {
279 capabilities |= CAP_DFS;
282 if (lp_security() != SEC_SHARE) {
283 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
286 if (req->smb->negotiate.encrypted_passwords) {
287 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
290 req->smb->signing.signing_state = lp_server_signing();
292 switch (req->smb->signing.signing_state) {
293 case SMB_SIGNING_OFF:
295 case SMB_SIGNING_SUPPORTED:
296 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
298 case SMB_SIGNING_REQUIRED:
299 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED |
300 NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
304 req->smb->negotiate.protocol = PROTOCOL_NT1;
306 req_setup_reply(req, 17, 0);
308 SSVAL(req->out.vwv, VWV(0), choice);
309 SCVAL(req->out.vwv, VWV(1), secword);
311 /* notice the strange +1 on vwv here? That's because
312 this is the one and only SMB packet that is malformed in
313 the specification - all the command words after the secword
314 are offset by 1 byte */
315 SSVAL(req->out.vwv+1, VWV(1), lp_maxmux());
316 SSVAL(req->out.vwv+1, VWV(2), 1); /* num vcs */
317 SIVAL(req->out.vwv+1, VWV(3), req->smb->negotiate.max_recv);
318 SIVAL(req->out.vwv+1, VWV(5), 0x10000); /* raw size. full 64k */
319 SIVAL(req->out.vwv+1, VWV(7), req->smb->pid); /* session key */
320 SIVAL(req->out.vwv+1, VWV(9), capabilities);
321 push_nttime(req->out.vwv+1, VWV(11), nttime);
322 SSVALS(req->out.vwv+1,VWV(15), req->smb->negotiate.zone_offset/60);
324 if (!negotiate_spnego) {
325 /* Create a token value and add it to the outgoing packet. */
326 if (req->smb->negotiate.encrypted_passwords) {
327 req_grow_data(req, 8);
328 /* note that we do not send a challenge at all if
329 we are using plaintext */
330 get_challenge(req->smb, req->out.ptr);
332 SCVAL(req->out.vwv+1, VWV(16), 8);
334 req_push_str(req, NULL, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
335 req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
336 DEBUG(3,("not using SPNEGO\n"));
339 DATA_BLOB blob = negprot_spnego(req->smb);
341 req_grow_data(req, blob.length);
342 memcpy(req->out.ptr, blob.data, blob.length);
343 DEBUG(3,("using SPNEGO\n"));
345 exit_server(req->smb, "no SPNEGO please");
349 req_send_reply_nosign(req);
352 /* these are the protocol lists used for auto architecture detection:
355 protocol [PC NETWORK PROGRAM 1.0]
356 protocol [XENIX CORE]
357 protocol [MICROSOFT NETWORKS 1.03]
359 protocol [Windows for Workgroups 3.1a]
362 protocol [NT LM 0.12]
365 protocol [PC NETWORK PROGRAM 1.0]
366 protocol [XENIX CORE]
367 protocol [MICROSOFT NETWORKS 1.03]
369 protocol [Windows for Workgroups 3.1a]
372 protocol [NT LM 0.12]
375 protocol [PC NETWORK PROGRAM 1.0]
377 protocol [Windows for Workgroups 3.1a]
380 protocol [NT LM 0.12]
383 protocol [PC NETWORK PROGRAM 1.0]
384 protocol [XENIX CORE]
391 * Modified to recognize the architecture of the remote machine better.
393 * This appears to be the matrix of which protocol is used by which
395 Protocol WfWg Win95 WinNT Win2K OS/2
396 PC NETWORK PROGRAM 1.0 1 1 1 1 1
398 MICROSOFT NETWORKS 3.0 2 2
400 MICROSOFT NETWORKS 1.03 3
403 Windows for Workgroups 3.1a 5 5 5 3
408 * tim@fsg.com 09/29/95
409 * Win2K added by matty 17/7/99
412 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
413 #define ARCH_WIN95 0x2
414 #define ARCH_WINNT 0x4
415 #define ARCH_WIN2K 0xC /* Win2K is like NT */
416 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
417 #define ARCH_SAMBA 0x20
419 #define ARCH_ALL 0x3F
421 /* List of supported protocols, most desired first */
422 static const struct {
423 const char *proto_name;
424 const char *short_name;
425 void (*proto_reply_fn)(struct request_context *req, uint16_t choice);
427 } supported_protocols[] = {
428 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
429 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
430 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
431 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
432 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
433 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
434 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
435 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
436 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
440 /****************************************************************************
442 ****************************************************************************/
444 void reply_negprot(struct request_context *req)
452 if (req->smb->negotiate.done_negprot) {
453 exit_server(req->smb, "multiple negprot's are not permitted");
455 req->smb->negotiate.done_negprot = True;
457 p = req->in.data + 1;
459 while (p < req->in.data + req->in.data_size) {
461 DEBUG(3,("Requested protocol [%s]\n",p));
462 if (strcmp(p,"Windows for Workgroups 3.1a") == 0)
463 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
464 else if (strcmp(p,"DOS LM1.2X002") == 0)
465 arch &= ( ARCH_WFWG | ARCH_WIN95 );
466 else if (strcmp(p,"DOS LANMAN2.1") == 0)
467 arch &= ( ARCH_WFWG | ARCH_WIN95 );
468 else if (strcmp(p,"NT LM 0.12") == 0)
469 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
470 else if (strcmp(p,"LANMAN2.1") == 0)
471 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
472 else if (strcmp(p,"LM1.2X002") == 0)
473 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
474 else if (strcmp(p,"MICROSOFT NETWORKS 1.03") == 0)
476 else if (strcmp(p,"XENIX CORE") == 0)
477 arch &= ( ARCH_WINNT | ARCH_OS2 );
478 else if (strcmp(p,"Samba") == 0) {
488 set_remote_arch(req->smb, RA_SAMBA);
491 set_remote_arch(req->smb, RA_WFWG);
494 set_remote_arch(req->smb, RA_WIN95);
497 if (req->flags2==FLAGS2_WIN2K_SIGNATURE)
498 set_remote_arch(req->smb, RA_WIN2K);
500 set_remote_arch(req->smb, RA_WINNT);
503 set_remote_arch(req->smb, RA_WIN2K);
506 set_remote_arch(req->smb, RA_OS2);
509 set_remote_arch(req->smb, RA_UNKNOWN);
513 /* possibly reload - change of architecture */
514 reload_services(req->smb, True);
516 /* Check for protocols, most desirable first */
517 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
520 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
521 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
522 while (p < (req->in.data + req->in.data_size)) {
523 if (strequal(p,supported_protocols[protocol].proto_name))
533 sub_set_remote_proto(supported_protocols[protocol].short_name);
534 reload_services(req->smb, True);
535 supported_protocols[protocol].proto_reply_fn(req, choice);
536 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
538 DEBUG(0,("No protocol supported !\n"));
541 DEBUG(5,("negprot index=%d\n", choice));