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", get_nt_error_msg(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 ****************************************************************************/
55 static int reply_corep(char *inbuf
, char *outbuf
)
57 int outsize
= set_message(outbuf
,1,0,True
);
59 Protocol
= PROTOCOL_CORE
;
65 /****************************************************************************
66 reply for the coreplus protocol
67 ****************************************************************************/
68 static int reply_coreplus(char *inbuf
, char *outbuf
)
70 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
71 int outsize
= set_message(outbuf
,13,0,True
);
72 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
73 readbraw and writebraw (possibly) */
74 /* Reply, SMBlockread, SMBwritelock supported. */
75 SCVAL(outbuf
,smb_flg
,FLAG_REPLY
|FLAG_SUPPORT_LOCKREAD
);
76 SSVAL(outbuf
,smb_vwv1
,0x1); /* user level security, don't encrypt */
78 Protocol
= PROTOCOL_COREPLUS
;
84 /****************************************************************************
85 reply for the lanman 1.0 protocol
86 ****************************************************************************/
87 static int reply_lanman1(char *inbuf
, char *outbuf
)
89 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
91 time_t t
= time(NULL
);
93 global_encrypted_passwords_negotiated
= lp_encrypted_passwords();
95 if (lp_security()>=SEC_USER
) secword
|= 1;
96 if (global_encrypted_passwords_negotiated
) secword
|= 2;
98 set_message(outbuf
,13,global_encrypted_passwords_negotiated
?8:0,True
);
99 SSVAL(outbuf
,smb_vwv1
,secword
);
100 /* Create a token value and add it to the outgoing packet. */
101 if (global_encrypted_passwords_negotiated
) {
102 get_challenge(smb_buf(outbuf
));
105 Protocol
= PROTOCOL_LANMAN1
;
107 /* Reply, SMBlockread, SMBwritelock supported. */
108 SCVAL(outbuf
,smb_flg
,FLAG_REPLY
|FLAG_SUPPORT_LOCKREAD
);
109 SSVAL(outbuf
,smb_vwv2
,max_recv
);
110 SSVAL(outbuf
,smb_vwv3
,lp_maxmux()); /* maxmux */
111 SSVAL(outbuf
,smb_vwv4
,1);
112 SSVAL(outbuf
,smb_vwv5
,raw
); /* tell redirector we support
113 readbraw writebraw (possibly) */
114 SIVAL(outbuf
,smb_vwv6
,sys_getpid());
115 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
117 put_dos_date(outbuf
,smb_vwv8
,t
);
119 return (smb_len(outbuf
)+4);
123 /****************************************************************************
124 reply for the lanman 2.0 protocol
125 ****************************************************************************/
126 static int reply_lanman2(char *inbuf
, char *outbuf
)
128 int raw
= (lp_readraw()?1:0) | (lp_writeraw()?2:0);
130 time_t t
= time(NULL
);
132 global_encrypted_passwords_negotiated
= lp_encrypted_passwords();
134 if (lp_security()>=SEC_USER
) secword
|= 1;
135 if (global_encrypted_passwords_negotiated
) secword
|= 2;
137 set_message(outbuf
,13,global_encrypted_passwords_negotiated
?8:0,True
);
138 SSVAL(outbuf
,smb_vwv1
,secword
);
139 SIVAL(outbuf
,smb_vwv6
,sys_getpid());
141 /* Create a token value and add it to the outgoing packet. */
142 if (global_encrypted_passwords_negotiated
) {
143 get_challenge(smb_buf(outbuf
));
146 Protocol
= PROTOCOL_LANMAN2
;
148 /* Reply, SMBlockread, SMBwritelock supported. */
149 SCVAL(outbuf
,smb_flg
,FLAG_REPLY
|FLAG_SUPPORT_LOCKREAD
);
150 SSVAL(outbuf
,smb_vwv2
,max_recv
);
151 SSVAL(outbuf
,smb_vwv3
,lp_maxmux());
152 SSVAL(outbuf
,smb_vwv4
,1);
153 SSVAL(outbuf
,smb_vwv5
,raw
); /* readbraw and/or writebraw */
154 SSVAL(outbuf
,smb_vwv10
, TimeDiff(t
)/60);
155 put_dos_date(outbuf
,smb_vwv8
,t
);
157 return (smb_len(outbuf
)+4);
163 generate the spnego negprot reply blob. Return the number of bytes used
165 static int negprot_spnego(char *p
)
168 extern pstring global_myname
;
170 const char *OIDs_krb5
[] = {OID_NTLMSSP
,
174 const char *OIDs_plain
[] = {OID_NTLMSSP
, NULL
};
178 global_spnego_negotiated
= True
;
181 safe_strcpy((char *)guid
, global_myname
, 16);
182 strlower((char *)guid
);
185 /* strangely enough, NT does not sent the single OID NTLMSSP when
186 not a ADS member, it sends no OIDs at all
188 we can't do this until we teach our sesssion setup parser to know
189 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)
191 if (lp_security() != SEC_ADS
) {
198 ads
= ads_init(NULL
, NULL
, NULL
, NULL
);
200 /* win2000 uses host$@REALM, which we will probably use eventually,
201 but for now this works */
202 asprintf(&principal
, "HOST/%s@%s", guid
, ads
->realm
);
203 blob
= spnego_gen_negTokenInit(guid
,
204 lp_security()==SEC_ADS
? OIDs_krb5
: OIDs_plain
,
209 memcpy(p
, blob
.data
, blob
.length
);
211 data_blob_free(&blob
);
217 /****************************************************************************
218 reply for the nt protocol
219 ****************************************************************************/
220 static int reply_nt1(char *inbuf
, char *outbuf
)
222 /* dual names + lock_and_read + nt SMBs + remote API calls */
223 int capabilities
= CAP_NT_FIND
|CAP_LOCK_AND_READ
|
224 CAP_LEVEL_II_OPLOCKS
|CAP_STATUS32
;
227 time_t t
= time(NULL
);
229 BOOL negotiate_spnego
= False
;
231 global_encrypted_passwords_negotiated
= lp_encrypted_passwords();
233 /* do spnego in user level security if the client
234 supports it and we can do encrypted passwords */
236 if (global_encrypted_passwords_negotiated
&&
237 (lp_security() != SEC_SHARE
) &&
239 (SVAL(inbuf
, smb_flg2
) & FLAGS2_EXTENDED_SECURITY
)) {
240 negotiate_spnego
= True
;
241 capabilities
|= CAP_EXTENDED_SECURITY
;
244 capabilities
|= CAP_NT_SMBS
|CAP_RPC_REMOTE_APIS
|CAP_UNIX
;
246 if (lp_large_readwrite() && (SMB_OFF_T_BITS
== 64)) {
247 capabilities
|= CAP_LARGE_READX
|CAP_LARGE_WRITEX
|CAP_W2K_SMBS
;
250 if (SMB_OFF_T_BITS
== 64) {
251 capabilities
|= CAP_LARGE_FILES
;
254 if (lp_readraw() && lp_writeraw()) {
255 capabilities
|= CAP_RAW_MODE
;
258 /* allow for disabling unicode */
260 capabilities
|= CAP_UNICODE
;
264 capabilities
|= CAP_DFS
;
266 if (lp_security() >= SEC_USER
) secword
|= 1;
267 if (global_encrypted_passwords_negotiated
) secword
|= 2;
269 set_message(outbuf
,17,0,True
);
271 SCVAL(outbuf
,smb_vwv1
,secword
);
273 Protocol
= PROTOCOL_NT1
;
275 SSVAL(outbuf
,smb_vwv1
+1,lp_maxmux()); /* maxmpx */
276 SSVAL(outbuf
,smb_vwv2
+1,1); /* num vcs */
277 SIVAL(outbuf
,smb_vwv3
+1,0xffff); /* max buffer. LOTS! */
278 SIVAL(outbuf
,smb_vwv5
+1,0x10000); /* raw size. full 64k */
279 SIVAL(outbuf
,smb_vwv7
+1,sys_getpid()); /* session key */
280 SIVAL(outbuf
,smb_vwv9
+1,capabilities
); /* capabilities */
281 put_long_date(outbuf
+smb_vwv11
+1,t
);
282 SSVALS(outbuf
,smb_vwv15
+1,TimeDiff(t
)/60);
284 p
= q
= smb_buf(outbuf
);
285 if (!negotiate_spnego
) {
286 /* Create a token value and add it to the outgoing packet. */
287 if (global_encrypted_passwords_negotiated
) {
290 SSVALS(outbuf
,smb_vwv16
+1,8);
292 p
+= srvstr_push(outbuf
, p
, global_myworkgroup
, -1,
293 STR_UNICODE
|STR_TERMINATE
|STR_NOALIGN
);
294 DEBUG(3,("not using SPNEGO\n"));
296 int len
= negprot_spnego(p
);
298 SSVALS(outbuf
,smb_vwv16
+1,len
);
300 DEBUG(3,("using SPNEGO\n"));
303 SSVAL(outbuf
,smb_vwv17
, p
- q
); /* length of challenge+domain strings */
304 set_message_end(outbuf
, p
);
306 return (smb_len(outbuf
)+4);
309 /* these are the protocol lists used for auto architecture detection:
312 protocol [PC NETWORK PROGRAM 1.0]
313 protocol [XENIX CORE]
314 protocol [MICROSOFT NETWORKS 1.03]
316 protocol [Windows for Workgroups 3.1a]
319 protocol [NT LM 0.12]
322 protocol [PC NETWORK PROGRAM 1.0]
323 protocol [XENIX CORE]
324 protocol [MICROSOFT NETWORKS 1.03]
326 protocol [Windows for Workgroups 3.1a]
329 protocol [NT LM 0.12]
332 protocol [PC NETWORK PROGRAM 1.0]
334 protocol [Windows for Workgroups 3.1a]
337 protocol [NT LM 0.12]
340 protocol [PC NETWORK PROGRAM 1.0]
341 protocol [XENIX CORE]
348 * Modified to recognize the architecture of the remote machine better.
350 * This appears to be the matrix of which protocol is used by which
352 Protocol WfWg Win95 WinNT Win2K OS/2
353 PC NETWORK PROGRAM 1.0 1 1 1 1 1
355 MICROSOFT NETWORKS 3.0 2 2
357 MICROSOFT NETWORKS 1.03 3
360 Windows for Workgroups 3.1a 5 5 5 3
365 * tim@fsg.com 09/29/95
366 * Win2K added by matty 17/7/99
369 #define ARCH_WFWG 0x3 /* This is a fudge because WfWg is like Win95 */
370 #define ARCH_WIN95 0x2
371 #define ARCH_WINNT 0x4
372 #define ARCH_WIN2K 0xC /* Win2K is like NT */
373 #define ARCH_OS2 0x14 /* Again OS/2 is like NT */
374 #define ARCH_SAMBA 0x20
376 #define ARCH_ALL 0x3F
378 /* List of supported protocols, most desired first */
382 int (*proto_reply_fn
)(char *, char *);
384 } supported_protocols
[] = {
385 {"NT LANMAN 1.0", "NT1", reply_nt1
, PROTOCOL_NT1
},
386 {"NT LM 0.12", "NT1", reply_nt1
, PROTOCOL_NT1
},
387 {"LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
388 {"Samba", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
389 {"DOS LM1.2X002", "LANMAN2", reply_lanman2
, PROTOCOL_LANMAN2
},
390 {"LANMAN1.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
391 {"MICROSOFT NETWORKS 3.0", "LANMAN1", reply_lanman1
, PROTOCOL_LANMAN1
},
392 {"MICROSOFT NETWORKS 1.03", "COREPLUS", reply_coreplus
, PROTOCOL_COREPLUS
},
393 {"PC NETWORK PROGRAM 1.0", "CORE", reply_corep
, PROTOCOL_CORE
},
398 /****************************************************************************
400 ****************************************************************************/
401 int reply_negprot(connection_struct
*conn
,
402 char *inbuf
,char *outbuf
, int dum_size
,
405 int outsize
= set_message(outbuf
,1,0,True
);
410 int bcc
= SVAL(smb_buf(inbuf
),-2);
412 START_PROFILE(SMBnegprot
);
414 p
= smb_buf(inbuf
)+1;
415 while (p
< (smb_buf(inbuf
) + bcc
))
418 DEBUG(3,("Requested protocol [%s]\n",p
));
419 if (strcsequal(p
,"Windows for Workgroups 3.1a"))
420 arch
&= ( ARCH_WFWG
| ARCH_WIN95
| ARCH_WINNT
| ARCH_WIN2K
);
421 else if (strcsequal(p
,"DOS LM1.2X002"))
422 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
423 else if (strcsequal(p
,"DOS LANMAN2.1"))
424 arch
&= ( ARCH_WFWG
| ARCH_WIN95
);
425 else if (strcsequal(p
,"NT LM 0.12"))
426 arch
&= ( ARCH_WIN95
| ARCH_WINNT
| ARCH_WIN2K
);
427 else if (strcsequal(p
,"LANMAN2.1"))
428 arch
&= ( ARCH_WINNT
| ARCH_WIN2K
| ARCH_OS2
);
429 else if (strcsequal(p
,"LM1.2X002"))
430 arch
&= ( ARCH_WINNT
| ARCH_WIN2K
| ARCH_OS2
);
431 else if (strcsequal(p
,"MICROSOFT NETWORKS 1.03"))
433 else if (strcsequal(p
,"XENIX CORE"))
434 arch
&= ( ARCH_WINNT
| ARCH_OS2
);
435 else if (strcsequal(p
,"Samba")) {
445 set_remote_arch(RA_SAMBA
);
448 set_remote_arch(RA_WFWG
);
451 set_remote_arch(RA_WIN95
);
454 if(SVAL(inbuf
,smb_flg2
)==FLAGS2_WIN2K_SIGNATURE
)
455 set_remote_arch(RA_WIN2K
);
457 set_remote_arch(RA_WINNT
);
460 set_remote_arch(RA_WIN2K
);
463 set_remote_arch(RA_OS2
);
466 set_remote_arch(RA_UNKNOWN
);
470 /* possibly reload - change of architecture */
471 reload_services(True
);
473 /* Check for protocols, most desirable first */
474 for (protocol
= 0; supported_protocols
[protocol
].proto_name
; protocol
++)
476 p
= smb_buf(inbuf
)+1;
478 if ((supported_protocols
[protocol
].protocol_level
<= lp_maxprotocol()) &&
479 (supported_protocols
[protocol
].protocol_level
>= lp_minprotocol()))
480 while (p
< (smb_buf(inbuf
) + bcc
))
482 if (strequal(p
,supported_protocols
[protocol
].proto_name
))
491 SSVAL(outbuf
,smb_vwv0
,choice
);
493 extern fstring remote_proto
;
494 fstrcpy(remote_proto
,supported_protocols
[protocol
].short_name
);
495 reload_services(True
);
496 outsize
= supported_protocols
[protocol
].proto_reply_fn(inbuf
, outbuf
);
497 DEBUG(3,("Selected protocol %s\n",supported_protocols
[protocol
].proto_name
));
500 DEBUG(0,("No protocol supported !\n"));
502 SSVAL(outbuf
,smb_vwv0
,choice
);
504 DEBUG( 5, ( "negprot index=%d\n", choice
) );
506 END_PROFILE(SMBnegprot
);