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 *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 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 choice)
70 uint16 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 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 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 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() && (SMB_OFF_T_BITS == 64)) {
260 capabilities |= CAP_LARGE_READX | CAP_LARGE_WRITEX | CAP_W2K_SMBS;
263 if (SMB_OFF_T_BITS >= 64) {
264 capabilities |= CAP_LARGE_FILES;
267 if (lp_readraw() && lp_writeraw()) {
268 capabilities |= CAP_RAW_MODE;
271 /* allow for disabling unicode */
273 capabilities |= CAP_UNICODE;
276 if (lp_nt_status_support()) {
277 capabilities |= CAP_STATUS32;
280 if (lp_host_msdfs()) {
281 capabilities |= CAP_DFS;
284 if (lp_security() != SEC_SHARE) {
285 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
288 if (req->smb->negotiate.encrypted_passwords) {
289 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
292 req->smb->signing.signing_state = lp_server_signing();
294 switch (req->smb->signing.signing_state) {
295 case SMB_SIGNING_OFF:
297 case SMB_SIGNING_SUPPORTED:
298 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
300 case SMB_SIGNING_REQUIRED:
301 secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED |
302 NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
306 req->smb->negotiate.protocol = PROTOCOL_NT1;
308 req_setup_reply(req, 17, 0);
310 SSVAL(req->out.vwv, VWV(0), choice);
311 SCVAL(req->out.vwv, VWV(1), secword);
313 /* notice the strange +1 on vwv here? That's because
314 this is the one and only SMB packet that is malformed in
315 the specification - all the command words after the secword
316 are offset by 1 byte */
317 SSVAL(req->out.vwv+1, VWV(1), lp_maxmux());
318 SSVAL(req->out.vwv+1, VWV(2), 1); /* num vcs */
319 SIVAL(req->out.vwv+1, VWV(3), req->smb->negotiate.max_recv);
320 SIVAL(req->out.vwv+1, VWV(5), 0x10000); /* raw size. full 64k */
321 SIVAL(req->out.vwv+1, VWV(7), req->smb->pid); /* session key */
322 SIVAL(req->out.vwv+1, VWV(9), capabilities);
323 push_nttime(req->out.vwv+1, VWV(11), &nttime);
324 SSVALS(req->out.vwv+1,VWV(15), req->smb->negotiate.zone_offset/60);
326 if (!negotiate_spnego) {
327 /* Create a token value and add it to the outgoing packet. */
328 if (req->smb->negotiate.encrypted_passwords) {
329 req_grow_data(req, 8);
330 /* note that we do not send a challenge at all if
331 we are using plaintext */
332 get_challenge(req->smb, req->out.ptr);
334 SCVAL(req->out.vwv+1, VWV(16), 8);
336 req_push_str(req, NULL, lp_workgroup(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
337 req_push_str(req, NULL, lp_netbios_name(), -1, STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
338 DEBUG(3,("not using SPNEGO\n"));
341 DATA_BLOB blob = negprot_spnego(req->smb);
343 req_grow_data(req, blob.length);
344 memcpy(req->out.ptr, blob.data, blob.length);
345 DEBUG(3,("using SPNEGO\n"));
347 exit_server(req->smb, "no SPNEGO please");
351 req_send_reply_nosign(req);
354 /* these are the protocol lists used for auto architecture detection:
357 protocol [PC NETWORK PROGRAM 1.0]
358 protocol [XENIX CORE]
359 protocol [MICROSOFT NETWORKS 1.03]
361 protocol [Windows for Workgroups 3.1a]
364 protocol [NT LM 0.12]
367 protocol [PC NETWORK PROGRAM 1.0]
368 protocol [XENIX CORE]
369 protocol [MICROSOFT NETWORKS 1.03]
371 protocol [Windows for Workgroups 3.1a]
374 protocol [NT LM 0.12]
377 protocol [PC NETWORK PROGRAM 1.0]
379 protocol [Windows for Workgroups 3.1a]
382 protocol [NT LM 0.12]
385 protocol [PC NETWORK PROGRAM 1.0]
386 protocol [XENIX CORE]
393 * Modified to recognize the architecture of the remote machine better.
395 * This appears to be the matrix of which protocol is used by which
397 Protocol WfWg Win95 WinNT Win2K OS/2
398 PC NETWORK PROGRAM 1.0 1 1 1 1 1
400 MICROSOFT NETWORKS 3.0 2 2
402 MICROSOFT NETWORKS 1.03 3
405 Windows for Workgroups 3.1a 5 5 5 3
410 * tim@fsg.com 09/29/95
411 * Win2K added by matty 17/7/99
414 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
415 #define ARCH_WIN95 0x2
416 #define ARCH_WINNT 0x4
417 #define ARCH_WIN2K 0xC /* Win2K is like NT */
418 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
419 #define ARCH_SAMBA 0x20
421 #define ARCH_ALL 0x3F
423 /* List of supported protocols, most desired first */
424 static const struct {
425 const char *proto_name;
426 const char *short_name;
427 void (*proto_reply_fn)(struct request_context *req, uint16 choice);
429 } supported_protocols[] = {
430 {"NT LANMAN 1.0", "NT1", reply_nt1, PROTOCOL_NT1},
431 {"NT LM 0.12", "NT1", reply_nt1, PROTOCOL_NT1},
432 {"LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
433 {"Samba", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
434 {"DOS LM1.2X002", "LANMAN2", reply_lanman2, PROTOCOL_LANMAN2},
435 {"LANMAN1.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
436 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1, PROTOCOL_LANMAN1},
437 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus, PROTOCOL_COREPLUS},
438 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep, PROTOCOL_CORE},
442 /****************************************************************************
444 ****************************************************************************/
446 void reply_negprot(struct request_context *req)
454 if (req->smb->negotiate.done_negprot) {
455 exit_server(req->smb, "multiple negprot's are not permitted");
457 req->smb->negotiate.done_negprot = True;
459 p = req->in.data + 1;
461 while (p < req->in.data + req->in.data_size) {
463 DEBUG(3,("Requested protocol [%s]\n",p));
464 if (strcmp(p,"Windows for Workgroups 3.1a") == 0)
465 arch &= ( ARCH_WFWG | ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
466 else if (strcmp(p,"DOS LM1.2X002") == 0)
467 arch &= ( ARCH_WFWG | ARCH_WIN95 );
468 else if (strcmp(p,"DOS LANMAN2.1") == 0)
469 arch &= ( ARCH_WFWG | ARCH_WIN95 );
470 else if (strcmp(p,"NT LM 0.12") == 0)
471 arch &= ( ARCH_WIN95 | ARCH_WINNT | ARCH_WIN2K );
472 else if (strcmp(p,"LANMAN2.1") == 0)
473 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
474 else if (strcmp(p,"LM1.2X002") == 0)
475 arch &= ( ARCH_WINNT | ARCH_WIN2K | ARCH_OS2 );
476 else if (strcmp(p,"MICROSOFT NETWORKS 1.03") == 0)
478 else if (strcmp(p,"XENIX CORE") == 0)
479 arch &= ( ARCH_WINNT | ARCH_OS2 );
480 else if (strcmp(p,"Samba") == 0) {
490 set_remote_arch(req->smb, RA_SAMBA);
493 set_remote_arch(req->smb, RA_WFWG);
496 set_remote_arch(req->smb, RA_WIN95);
499 if (req->flags2==FLAGS2_WIN2K_SIGNATURE)
500 set_remote_arch(req->smb, RA_WIN2K);
502 set_remote_arch(req->smb, RA_WINNT);
505 set_remote_arch(req->smb, RA_WIN2K);
508 set_remote_arch(req->smb, RA_OS2);
511 set_remote_arch(req->smb, RA_UNKNOWN);
515 /* possibly reload - change of architecture */
516 reload_services(req->smb, True);
518 /* Check for protocols, most desirable first */
519 for (protocol = 0; supported_protocols[protocol].proto_name; protocol++) {
522 if ((supported_protocols[protocol].protocol_level <= lp_maxprotocol()) &&
523 (supported_protocols[protocol].protocol_level >= lp_minprotocol()))
524 while (p < (req->in.data + req->in.data_size)) {
525 if (strequal(p,supported_protocols[protocol].proto_name))
535 sub_set_remote_proto(supported_protocols[protocol].short_name);
536 reload_services(req->smb, True);
537 supported_protocols[protocol].proto_reply_fn(req, choice);
538 DEBUG(3,("Selected protocol %s\n",supported_protocols[protocol].proto_name));
540 DEBUG(0,("No protocol supported !\n"));
543 DEBUG(5,("negprot index=%d\n", choice));