source: branches/samba-3.0/source/smbd/negprot.c@ 710

Last change on this file since 710 was 105, checked in by Paul Smedley, 18 years ago

Update source to 3.0.27a

File size: 19.7 KB
Line 
1/*
2 Unix SMB/CIFS implementation.
3 negprot reply code
4 Copyright (C) Andrew Tridgell 1992-1998
5
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.
10
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.
15
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.
19*/
20
21#include "includes.h"
22
23extern fstring remote_proto;
24extern enum protocol_types Protocol;
25extern int max_recv;
26
27BOOL global_encrypted_passwords_negotiated = False;
28BOOL global_spnego_negotiated = False;
29struct auth_context *negprot_global_auth_context = NULL;
30
31static void get_challenge(char buff[8])
32{
33 NTSTATUS nt_status;
34 const uint8 *cryptkey;
35
36 /* We might be called more than once, multiple negprots are
37 * permitted */
38 if (negprot_global_auth_context) {
39 DEBUG(3, ("get challenge: is this a secondary negprot? negprot_global_auth_context is non-NULL!\n"));
40 (negprot_global_auth_context->free)(&negprot_global_auth_context);
41 }
42
43 DEBUG(10, ("get challenge: 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", nt_errstr(nt_status)));
46 smb_panic("cannot make_negprot_global_auth_context!\n");
47 }
48 DEBUG(10, ("get challenge: getting challenge\n"));
49 cryptkey = negprot_global_auth_context->get_ntlm_challenge(negprot_global_auth_context);
50 memcpy(buff, cryptkey, 8);
51}
52
53/****************************************************************************
54 Reply for the core protocol.
55****************************************************************************/
56
57static int reply_corep(char *inbuf, char *outbuf)
58{
59 int outsize = set_message(outbuf,1,0,True);
60
61 Protocol = PROTOCOL_CORE;
62
63 return outsize;
64}
65
66/****************************************************************************
67 Reply for the coreplus protocol.
68****************************************************************************/
69
70static int reply_coreplus(char *inbuf, char *outbuf)
71{
72 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
73 int outsize = set_message(outbuf,13,0,True);
74 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
75 readbraw and writebraw (possibly) */
76 /* Reply, SMBlockread, SMBwritelock supported. */
77 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
78 SSVAL(outbuf,smb_vwv1,0x1); /* user level security, don't encrypt */
79
80 Protocol = PROTOCOL_COREPLUS;
81
82 return outsize;
83}
84
85/****************************************************************************
86 Reply for the lanman 1.0 protocol.
87****************************************************************************/
88
89static int reply_lanman1(char *inbuf, char *outbuf)
90{
91 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
92 int secword=0;
93 time_t t = time(NULL);
94
95 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
96
97 if (lp_security()>=SEC_USER)
98 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
99 if (global_encrypted_passwords_negotiated)
100 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
101
102 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
103 SSVAL(outbuf,smb_vwv1,secword);
104 /* Create a token value and add it to the outgoing packet. */
105 if (global_encrypted_passwords_negotiated) {
106 get_challenge(smb_buf(outbuf));
107 SSVAL(outbuf,smb_vwv11, 8);
108 }
109
110 Protocol = PROTOCOL_LANMAN1;
111
112 /* Reply, SMBlockread, SMBwritelock supported. */
113 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
114 SSVAL(outbuf,smb_vwv2,max_recv);
115 SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
116 SSVAL(outbuf,smb_vwv4,1);
117 SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
118 readbraw writebraw (possibly) */
119 SIVAL(outbuf,smb_vwv6,sys_getpid());
120 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
121
122 srv_put_dos_date(outbuf,smb_vwv8,t);
123
124 return (smb_len(outbuf)+4);
125}
126
127/****************************************************************************
128 Reply for the lanman 2.0 protocol.
129****************************************************************************/
130
131static int reply_lanman2(char *inbuf, char *outbuf)
132{
133 int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
134 int secword=0;
135 time_t t = time(NULL);
136
137 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
138
139 if (lp_security()>=SEC_USER)
140 secword |= NEGOTIATE_SECURITY_USER_LEVEL;
141 if (global_encrypted_passwords_negotiated)
142 secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
143
144 set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
145 SSVAL(outbuf,smb_vwv1,secword);
146 SIVAL(outbuf,smb_vwv6,sys_getpid());
147
148 /* Create a token value and add it to the outgoing packet. */
149 if (global_encrypted_passwords_negotiated) {
150 get_challenge(smb_buf(outbuf));
151 SSVAL(outbuf,smb_vwv11, 8);
152 }
153
154 Protocol = PROTOCOL_LANMAN2;
155
156 /* Reply, SMBlockread, SMBwritelock supported. */
157 SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
158 SSVAL(outbuf,smb_vwv2,max_recv);
159 SSVAL(outbuf,smb_vwv3,lp_maxmux());
160 SSVAL(outbuf,smb_vwv4,1);
161 SSVAL(outbuf,smb_vwv5,raw); /* readbraw and/or writebraw */
162 SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);
163 srv_put_dos_date(outbuf,smb_vwv8,t);
164
165 return (smb_len(outbuf)+4);
166}
167
168/****************************************************************************
169 Generate the spnego negprot reply blob. Return the number of bytes used.
170****************************************************************************/
171
172static DATA_BLOB negprot_spnego(void)
173{
174 DATA_BLOB blob;
175 nstring dos_name;
176 fstring unix_name;
177#ifdef DEVELOPER
178 size_t slen;
179#endif
180 char guid[17];
181 const char *OIDs_krb5[] = {OID_KERBEROS5,
182 OID_KERBEROS5_OLD,
183 OID_NTLMSSP,
184 NULL};
185 const char *OIDs_plain[] = {OID_NTLMSSP, NULL};
186
187 global_spnego_negotiated = True;
188
189 memset(guid, '\0', sizeof(guid));
190
191 safe_strcpy(unix_name, global_myname(), sizeof(unix_name)-1);
192 strlower_m(unix_name);
193 push_ascii_nstring(dos_name, unix_name);
194 safe_strcpy(guid, dos_name, sizeof(guid)-1);
195
196#ifdef DEVELOPER
197 /* Fix valgrind 'uninitialized bytes' issue. */
198 slen = strlen(dos_name);
199 if (slen < sizeof(guid)) {
200 memset(guid+slen, '\0', sizeof(guid) - slen);
201 }
202#endif
203
204 /* strangely enough, NT does not sent the single OID NTLMSSP when
205 not a ADS member, it sends no OIDs at all
206
207 OLD COMMENT : "we can't do this until we teach our sesssion setup parser to know
208 about raw NTLMSSP (clients send no ASN.1 wrapping if we do this)"
209
210 Our sessionsetup code now handles raw NTLMSSP connects, so we can go
211 back to doing what W2K3 does here. This is needed to make PocketPC 2003
212 CIFS connections work with SPNEGO. See bugzilla bugs #1828 and #3133
213 for details. JRA.
214
215 */
216
217 if (lp_security() != SEC_ADS && !lp_use_kerberos_keytab()) {
218#if 0
219 /* Code for PocketPC client */
220 blob = data_blob(guid, 16);
221#else
222 /* Code for standalone WXP client */
223 blob = spnego_gen_negTokenInit(guid, OIDs_plain, "NONE");
224#endif
225 } else {
226 fstring myname;
227 char *host_princ_s = NULL;
228 name_to_fqdn(myname, global_myname());
229 strlower_m(myname);
230 asprintf(&host_princ_s, "cifs/%s@%s", myname, lp_realm());
231 blob = spnego_gen_negTokenInit(guid, OIDs_krb5, host_princ_s);
232 SAFE_FREE(host_princ_s);
233 }
234
235 return blob;
236}
237
238/****************************************************************************
239 Reply for the nt protocol.
240****************************************************************************/
241
242static int reply_nt1(char *inbuf, char *outbuf)
243{
244 /* dual names + lock_and_read + nt SMBs + remote API calls */
245 int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
246 CAP_LEVEL_II_OPLOCKS;
247
248 int secword=0;
249 char *p, *q;
250 BOOL negotiate_spnego = False;
251 time_t t = time(NULL);
252
253 global_encrypted_passwords_negotiated = lp_encrypted_passwords();
254
255 /* Check the flags field to see if this is Vista.
256 WinXP sets it and Vista does not. But we have to
257 distinguish from NT which doesn't set it either. */
258
259 if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) &&
260 ((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) )
261 {
262 if (get_remote_arch() != RA_SAMBA) {
263 set_remote_arch( RA_VISTA );
264 }
265 }
266
267 /* do spnego in user level security if the client
268 supports it and we can do encrypted passwords */
269
270 if (global_encrypted_passwords_negotiated &&
271 (lp_security() != SEC_SHARE) &&
272 lp_use_spnego() &&
273 (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
274 negotiate_spnego = True;
275 capabilities |= CAP_EXTENDED_SECURITY;
276 add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
277 /* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
278 partially constructed. */
279 SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
280 }
281
282 capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;
283
284 if (lp_unix_extensions()) {
285 capabilities |= CAP_UNIX;
286 }
287