OpenWrt – Blame information for rev 1
?pathlinks?
Rev | Author | Line No. | Line |
---|---|---|---|
1 | office | 1 | From ee105156fa151ebfd34b8febc2928e144b3b7b0e Mon Sep 17 00:00:00 2001 |
2 | From: =?UTF-8?q?G=C3=BCnther=20Deschner?= <gd@samba.org> |
||
3 | Date: Sat, 26 Sep 2015 01:29:10 +0200 |
||
4 | Subject: [PATCH 01/15] CVE-2016-2111: s3:rpc_server/netlogon: always go |
||
5 | through netr_creds_server_step_check() |
||
6 | |||
7 | The ensures we apply the "server schannel = yes" restrictions. |
||
8 | |||
9 | BUG: https://bugzilla.samba.org/show_bug.cgi?id=11749 |
||
10 | |||
11 | Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
||
12 | |||
13 | Signed-off-by: Guenther Deschner <gd@samba.org> |
||
14 | Signed-off-by: Stefan Metzmacher <metze@samba.org> |
||
15 | --- |
||
16 | source3/rpc_server/netlogon/srv_netlog_nt.c | 24 ++++++++++++++---------- |
||
17 | 1 file changed, 14 insertions(+), 10 deletions(-) |
||
18 | |||
19 | --- a/source3/rpc_server/netlogon/srv_netlog_nt.c |
||
20 | +++ b/source3/rpc_server/netlogon/srv_netlog_nt.c |
||
21 | @@ -1508,6 +1508,7 @@ static NTSTATUS _netr_LogonSamLogon_base |
||
22 | case NetlogonNetworkTransitiveInformation: |
||
23 | { |
||
24 | const char *wksname = nt_workstation; |
||
25 | + const char *workgroup = lp_workgroup(); |
||
26 | |||
27 | status = make_auth_context_fixed(talloc_tos(), &auth_context, |
||
28 | logon->network->challenge); |
||
29 | @@ -1532,6 +1533,14 @@ static NTSTATUS _netr_LogonSamLogon_base |
||
30 | logon->network->nt.length)) { |
||
31 | status = NT_STATUS_NO_MEMORY; |
||
32 | } |
||
33 | + |
||
34 | + if (NT_STATUS_IS_OK(status)) { |
||
35 | + status = NTLMv2_RESPONSE_verify_netlogon_creds( |
||
36 | + user_info->client.account_name, |
||
37 | + user_info->client.domain_name, |
||
38 | + user_info->password.response.nt, |
||
39 | + creds, workgroup); |
||
40 | + } |
||
41 | break; |
||
42 | } |
||
43 | case NetlogonInteractiveInformation: |
||
44 | @@ -1636,6 +1645,14 @@ static NTSTATUS _netr_LogonSamLogon_base |
||
45 | r->out.validation->sam3); |
||
46 | break; |
||
47 | case 6: |
||
48 | + /* Only allow this if the pipe is protected. */ |
||
49 | + if (p->auth.auth_level < DCERPC_AUTH_LEVEL_PRIVACY) { |
||
50 | + DEBUG(0,("netr_Validation6: client %s not using privacy for netlogon\n", |
||
51 | + get_remote_machine_name())); |
||
52 | + status = NT_STATUS_INVALID_PARAMETER; |
||
53 | + break; |
||
54 | + } |
||
55 | + |
||
56 | status = serverinfo_to_SamInfo6(server_info, pipe_session_key, 16, |
||
57 | r->out.validation->sam6); |
||
58 | break; |
||
59 | @@ -2271,11 +2288,13 @@ NTSTATUS _netr_GetForestTrustInformation |
||
60 | |||
61 | /* TODO: check server name */ |
||
62 | |||
63 | - status = schannel_check_creds_state(p->mem_ctx, lp_private_dir(), |
||
64 | - r->in.computer_name, |
||
65 | - r->in.credential, |
||
66 | - r->out.return_authenticator, |
||
67 | - &creds); |
||
68 | + become_root(); |
||
69 | + status = netr_creds_server_step_check(p, p->mem_ctx, |
||
70 | + r->in.computer_name, |
||
71 | + r->in.credential, |
||
72 | + r->out.return_authenticator, |
||
73 | + &creds); |
||
74 | + unbecome_root(); |
||
75 | if (!NT_STATUS_IS_OK(status)) { |
||
76 | return status; |
||
77 | } |
||
78 | @@ -2371,11 +2390,13 @@ NTSTATUS _netr_ServerGetTrustInfo(struct |
||
79 | |||
80 | /* TODO: check server name */ |
||
81 | |||
82 | - status = schannel_check_creds_state(p->mem_ctx, lp_private_dir(), |
||
83 | - r->in.computer_name, |
||
84 | - r->in.credential, |
||
85 | - r->out.return_authenticator, |
||
86 | - &creds); |
||
87 | + become_root(); |
||
88 | + status = netr_creds_server_step_check(p, p->mem_ctx, |
||
89 | + r->in.computer_name, |
||
90 | + r->in.credential, |
||
91 | + r->out.return_authenticator, |
||
92 | + &creds); |
||
93 | + unbecome_root(); |
||
94 | if (!NT_STATUS_IS_OK(status)) { |
||
95 | return status; |
||
96 | } |
||
97 | --- a/source4/torture/rpc/samba3rpc.c |
||
98 | +++ b/source4/torture/rpc/samba3rpc.c |
||
99 | @@ -1122,8 +1122,8 @@ static bool schan(struct torture_context |
||
100 | generate_random_buffer(chal.data, chal.length); |
||
101 | names_blob = NTLMv2_generate_names_blob( |
||
102 | mem_ctx, |
||
103 | - cli_credentials_get_workstation(user_creds), |
||
104 | - cli_credentials_get_domain(user_creds)); |
||
105 | + cli_credentials_get_workstation(wks_creds), |
||
106 | + cli_credentials_get_domain(wks_creds)); |
||
107 | status = cli_credentials_get_ntlm_response( |
||
108 | user_creds, mem_ctx, &flags, chal, names_blob, |
||
109 | &lm_resp, &nt_resp, NULL, NULL); |
||
110 | --- a/libcli/auth/proto.h |
||
111 | +++ b/libcli/auth/proto.h |
||
112 | @@ -139,6 +139,11 @@ bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ct |
||
113 | const DATA_BLOB *names_blob, |
||
114 | DATA_BLOB *lm_response, DATA_BLOB *nt_response, |
||
115 | DATA_BLOB *lm_session_key, DATA_BLOB *user_session_key) ; |
||
116 | +NTSTATUS NTLMv2_RESPONSE_verify_netlogon_creds(const char *account_name, |
||
117 | + const char *account_domain, |
||
118 | + const DATA_BLOB response, |
||
119 | + const struct netlogon_creds_CredentialState *creds, |
||
120 | + const char *workgroup); |
||
121 | |||
122 | /*********************************************************** |
||
123 | encode a password buffer with a unicode password. The buffer |
||
124 | --- a/libcli/auth/smbencrypt.c |
||
125 | +++ b/libcli/auth/smbencrypt.c |
||
126 | @@ -26,7 +26,7 @@ |
||
127 | #include "../libcli/auth/msrpc_parse.h" |
||
128 | #include "../lib/crypto/crypto.h" |
||
129 | #include "../libcli/auth/libcli_auth.h" |
||
130 | -#include "../librpc/gen_ndr/ntlmssp.h" |
||
131 | +#include "../librpc/gen_ndr/ndr_ntlmssp.h" |
||
132 | |||
133 | void SMBencrypt_hash(const uint8_t lm_hash[16], const uint8_t *c8, uint8_t p24[24]) |
||
134 | { |
||
135 | @@ -522,6 +522,146 @@ bool SMBNTLMv2encrypt(TALLOC_CTX *mem_ct |
||
136 | lm_response, nt_response, lm_session_key, user_session_key); |
||
137 | } |
||
138 | |||
139 | +NTSTATUS NTLMv2_RESPONSE_verify_netlogon_creds(const char *account_name, |
||
140 | + const char *account_domain, |
||
141 | + const DATA_BLOB response, |
||
142 | + const struct netlogon_creds_CredentialState *creds, |
||
143 | + const char *workgroup) |
||
144 | +{ |
||
145 | + TALLOC_CTX *frame = NULL; |
||
146 | + /* RespType + HiRespType */ |
||
147 | + static const char *magic = "\x01\x01"; |
||
148 | + int cmp; |
||
149 | + struct NTLMv2_RESPONSE v2_resp; |
||
150 | + enum ndr_err_code err; |
||
151 | + const struct AV_PAIR *av_nb_cn = NULL; |
||
152 | + const struct AV_PAIR *av_nb_dn = NULL; |
||
153 | + |
||
154 | + if (response.length < 48) { |
||
155 | + /* |
||
156 | + * NTLMv2_RESPONSE has at least 48 bytes. |
||
157 | + */ |
||
158 | + return NT_STATUS_OK; |
||
159 | + } |
||
160 | + |
||
161 | + cmp = memcmp(response.data + 16, magic, 2); |
||
162 | + if (cmp != 0) { |
||
163 | + /* |
||
164 | + * It doesn't look like a valid NTLMv2_RESPONSE |
||
165 | + */ |
||
166 | + return NT_STATUS_OK; |
||
167 | + } |
||
168 | + |
||
169 | + frame = talloc_stackframe(); |
||
170 | + |
||
171 | + err = ndr_pull_struct_blob(&response, frame, &v2_resp, |
||
172 | + (ndr_pull_flags_fn_t)ndr_pull_NTLMv2_RESPONSE); |
||
173 | + if (!NDR_ERR_CODE_IS_SUCCESS(err)) { |
||
174 | + NTSTATUS status; |
||
175 | + status = ndr_map_error2ntstatus(err); |
||
176 | + DEBUG(2,("Failed to parse NTLMv2_RESPONSE " |
||
177 | + "length %u - %s - %s\n", |
||
178 | + (unsigned)response.length, |
||
179 | + ndr_map_error2string(err), |
||
180 | + nt_errstr(status))); |
||
181 | + dump_data(2, response.data, response.length); |
||
182 | + TALLOC_FREE(frame); |
||
183 | + return status; |
||
184 | + } |
||
185 | + |
||
186 | + if (DEBUGLVL(10)) { |
||
187 | + NDR_PRINT_DEBUG(NTLMv2_RESPONSE, &v2_resp); |
||
188 | + } |
||
189 | + |
||
190 | + /* |
||
191 | + * Make sure the netbios computer name in the |
||
192 | + * NTLMv2_RESPONSE matches the computer name |
||
193 | + * in the secure channel credentials for workstation |
||
194 | + * trusts. |
||
195 | + * |
||
196 | + * And the netbios domain name matches our |
||
197 | + * workgroup. |
||
198 | + * |
||
199 | + * This prevents workstations from requesting |
||
200 | + * the session key of NTLMSSP sessions of clients |
||
201 | + * to other hosts. |
||
202 | + */ |
||
203 | + if (creds->secure_channel_type == SEC_CHAN_WKSTA) { |
||
204 | + av_nb_cn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs, |
||
205 | + MsvAvNbComputerName); |
||
206 | + av_nb_dn = ndr_ntlmssp_find_av(&v2_resp.Challenge.AvPairs, |
||
207 | + MsvAvNbDomainName); |
||
208 | + } |
||
209 | + |
||
210 | + if (av_nb_cn != NULL) { |
||
211 | + const char *v = NULL; |
||
212 | + char *a = NULL; |
||
213 | + size_t len; |
||
214 | + |
||
215 | + v = av_nb_cn->Value.AvNbComputerName; |
||
216 | + |
||
217 | + a = talloc_strdup(frame, creds->account_name); |
||
218 | + if (a == NULL) { |
||
219 | + TALLOC_FREE(frame); |
||
220 | + return NT_STATUS_NO_MEMORY; |
||
221 | + } |
||
222 | + len = strlen(a); |
||
223 | + if (len > 0 && a[len - 1] == '$') { |
||
224 | + a[len - 1] = '\0'; |
||
225 | + } |
||
226 | + |
||
227 | +#ifdef SAMBA4_INTERNAL_HEIMDAL /* smbtorture4 for make test */ |
||
228 | + cmp = strcasecmp_m(a, v); |
||
229 | +#else /* smbd */ |
||
230 | + cmp = StrCaseCmp(a, v); |
||
231 | +#endif |
||
232 | + if (cmp != 0) { |
||
233 | + DEBUG(2,("%s: NTLMv2_RESPONSE with " |
||
234 | + "NbComputerName[%s] rejected " |
||
235 | + "for user[%s\\%s] " |
||
236 | + "against SEC_CHAN_WKSTA[%s/%s] " |
||
237 | + "in workgroup[%s]\n", |
||
238 | + __func__, v, |
||
239 | + account_domain, |
||
240 | + account_name, |
||
241 | + creds->computer_name, |
||
242 | + creds->account_name, |
||
243 | + workgroup)); |
||
244 | + TALLOC_FREE(frame); |
||
245 | + return NT_STATUS_LOGON_FAILURE; |
||
246 | + } |
||
247 | + } |
||
248 | + if (av_nb_dn != NULL) { |
||
249 | + const char *v = NULL; |
||
250 | + |
||
251 | + v = av_nb_dn->Value.AvNbDomainName; |
||
252 | + |
||
253 | +#ifdef SAMBA4_INTERNAL_HEIMDAL /* smbtorture4 for make test */ |
||
254 | + cmp = strcasecmp_m(workgroup, v); |
||
255 | +#else /* smbd */ |
||
256 | + cmp = StrCaseCmp(workgroup, v); |
||
257 | +#endif |
||
258 | + if (cmp != 0) { |
||
259 | + DEBUG(2,("%s: NTLMv2_RESPONSE with " |
||
260 | + "NbDomainName[%s] rejected " |
||
261 | + "for user[%s\\%s] " |
||
262 | + "against SEC_CHAN_WKSTA[%s/%s] " |
||
263 | + "in workgroup[%s]\n", |
||
264 | + __func__, v, |
||
265 | + account_domain, |
||
266 | + account_name, |
||
267 | + creds->computer_name, |
||
268 | + creds->account_name, |
||
269 | + workgroup)); |
||
270 | + TALLOC_FREE(frame); |
||
271 | + return NT_STATUS_LOGON_FAILURE; |
||
272 | + } |
||
273 | + } |
||
274 | + |
||
275 | + TALLOC_FREE(frame); |
||
276 | + return NT_STATUS_OK; |
||
277 | +} |
||
278 | + |
||
279 | /*********************************************************** |
||
280 | encode a password buffer with a unicode password. The buffer |
||
281 | is filled with random data to make it harder to attack. |
||
282 | --- a/libcli/auth/wscript_build |
||
283 | +++ b/libcli/auth/wscript_build |
||
284 | @@ -19,7 +19,7 @@ bld.SAMBA_SUBSYSTEM('MSRPC_PARSE', |
||
285 | |||
286 | bld.SAMBA_SUBSYSTEM('LIBCLI_AUTH', |
||
287 | source='credentials.c session.c smbencrypt.c smbdes.c', |
||
288 | - public_deps='MSRPC_PARSE', |
||
289 | + public_deps='MSRPC_PARSE NDR_NTLMSSP', |
||
290 | public_headers='credentials.h:domain_credentials.h' |
||
291 | ) |
||
292 | |||
293 | --- a/source3/Makefile.in |
||
294 | +++ b/source3/Makefile.in |
||
295 | @@ -783,6 +783,7 @@ GROUPDB_OBJ = groupdb/mapping.o groupdb/ |
||
296 | PROFILE_OBJ = profile/profile.o |
||
297 | PROFILES_OBJ = utils/profiles.o \ |
||
298 | $(LIBSMB_ERR_OBJ) \ |
||
299 | + $(LIBNDR_NTLMSSP_OBJ) \ |
||
300 | $(PARAM_OBJ) \ |
||
301 | $(LIB_OBJ) $(LIB_DUMMY_OBJ) \ |
||
302 | $(POPT_LIB_OBJ) \ |
||
303 | @@ -995,10 +996,10 @@ SWAT_OBJ = $(SWAT_OBJ1) $(PARAM_OBJ) $(P |
||
304 | STATUS_OBJ = utils/status.o utils/status_profile.o \ |
||
305 | $(LOCKING_OBJ) $(PARAM_OBJ) \ |
||
306 | $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ |
||
307 | - $(LIBSMB_ERR_OBJ) $(FNAME_UTIL_OBJ) |
||
308 | + $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) $(FNAME_UTIL_OBJ) |
||
309 | |||
310 | SMBCONTROL_OBJ = utils/smbcontrol.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ |
||
311 | - $(LIBSMB_ERR_OBJ) $(POPT_LIB_OBJ) $(PRINTBASE_OBJ) |
||
312 | + $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) $(POPT_LIB_OBJ) $(PRINTBASE_OBJ) |
||
313 | |||
314 | SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \ |
||
315 | $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_OBJ) \ |
||
316 | @@ -1012,11 +1013,11 @@ SMBTREE_OBJ = utils/smbtree.o $(PARAM_OB |
||
317 | |||
318 | TESTPARM_OBJ = utils/testparm.o \ |
||
319 | $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \ |
||
320 | - $(LIBSMB_ERR_OBJ) |
||
321 | + $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) |
||
322 | |||
323 | SMBTA_UTIL_OBJ = utils/smbta-util.o $(PARAM_OBJ) $(POPT_LIB_OBJ) \ |
||
324 | $(LIB_NONSMBD_OBJ) \ |
||
325 | - $(LIBSMB_ERR_OBJ) $(FNAME_UTIL_OBJ) |
||
326 | + $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) $(FNAME_UTIL_OBJ) |
||
327 | |||
328 | TEST_LP_LOAD_OBJ = param/test_lp_load.o \ |
||
329 | $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ |
||
330 | @@ -1146,6 +1147,7 @@ SMBCONFTORT_OBJ = $(SMBCONFTORT_OBJ0) \ |
||
331 | $(LIB_NONSMBD_OBJ) \ |
||
332 | $(PARAM_OBJ) \ |
||
333 | $(LIBSMB_ERR_OBJ) \ |
||
334 | + $(LIBNDR_NTLMSSP_OBJ) \ |
||
335 | $(POPT_LIB_OBJ) |
||
336 | |||
337 | PTHREADPOOLTEST_OBJ = lib/pthreadpool/pthreadpool.o \ |
||
338 | @@ -1229,7 +1231,7 @@ CUPS_OBJ = client/smbspool.o $(PARAM_OBJ |
||
339 | $(LIBNDR_GEN_OBJ0) |
||
340 | |||
341 | NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(LIBNMB_OBJ) \ |
||
342 | - $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSMB_ERR_OBJ) |
||
343 | + $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) |
||
344 | |||
345 | SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \ |
||
346 | torture/denytest.o torture/mangle_test.o \ |
||
347 | @@ -1253,6 +1255,7 @@ MASKTEST_OBJ = torture/masktest.o $(PARA |
||
348 | $(LIBNDR_GEN_OBJ0) |
||
349 | |||
350 | MSGTEST_OBJ = torture/msgtest.o $(PARAM_OBJ) $(LIBSMB_ERR_OBJ) \ |
||
351 | + $(LIBNDR_NTLMSSP_OBJ) \ |
||
352 | $(LIB_NONSMBD_OBJ) \ |
||
353 | $(LIBNDR_GEN_OBJ0) |
||
354 | |||
355 | @@ -1269,7 +1272,7 @@ PDBTEST_OBJ = torture/pdbtest.o $(PARAM_ |
||
356 | |||
357 | VFSTEST_OBJ = torture/cmd_vfs.o torture/vfstest.o $(SMBD_OBJ_BASE) $(READLINE_OBJ) |
||
358 | |||
359 | -SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSMB_ERR_OBJ) |
||
360 | +SMBICONV_OBJ = $(PARAM_OBJ) torture/smbiconv.o $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) |
||
361 | |||
362 | LOG2PCAP_OBJ = utils/log2pcaphex.o |
||
363 | |||
364 | @@ -1297,17 +1300,17 @@ SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LI |
||
365 | EVTLOGADM_OBJ0 = utils/eventlogadm.o |
||
366 | |||
367 | EVTLOGADM_OBJ = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ |
||
368 | - $(LIBSMB_ERR_OBJ) $(LIB_EVENTLOG_OBJ) \ |
||
369 | + $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) $(LIB_EVENTLOG_OBJ) \ |
||
370 | librpc/gen_ndr/ndr_eventlog.o \ |
||
371 | librpc/gen_ndr/ndr_lsa.o |
||
372 | |||
373 | SHARESEC_OBJ0 = utils/sharesec.o |
||
374 | SHARESEC_OBJ = $(SHARESEC_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \ |
||
375 | - $(LIBSMB_ERR_OBJ) \ |
||
376 | + $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) \ |
||
377 | $(POPT_LIB_OBJ) |
||
378 | |||
379 | TALLOCTORT_OBJ = @tallocdir@/testsuite.o @tallocdir@/testsuite_main.o \ |
||
380 | - $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_ERR_OBJ) |
||
381 | + $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) |
||
382 | |||
383 | REPLACETORT_OBJ = @libreplacedir@/test/testsuite.o \ |
||
384 | @libreplacedir@/test/getifaddrs.o \ |
||
385 | @@ -1323,7 +1326,7 @@ SMBFILTER_OBJ = utils/smbfilter.o $(PARA |
||
386 | $(LIBNDR_GEN_OBJ0) |
||
387 | |||
388 | WINBIND_WINS_NSS_OBJ = ../nsswitch/wins.o $(PARAM_OBJ) \ |
||
389 | - $(LIB_NONSMBD_OBJ) $(LIBSMB_ERR_OBJ) $(LIBNMB_OBJ) |
||
390 | + $(LIB_NONSMBD_OBJ) $(LIBSMB_ERR_OBJ) $(LIBNDR_NTLMSSP_OBJ) $(LIBNMB_OBJ) |
||
391 | |||
392 | PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ |
||
393 | pam_smbpass/pam_smb_acct.o pam_smbpass/support.o ../lib/util/asn1.o |
||
394 | @@ -1531,12 +1534,14 @@ RPC_OPEN_TCP_OBJ = torture/rpc_open_tcp. |
||
395 | DBWRAP_TOOL_OBJ = utils/dbwrap_tool.o \ |
||
396 | $(PARAM_OBJ) \ |
||
397 | $(LIB_NONSMBD_OBJ) \ |
||
398 | - $(LIBSMB_ERR_OBJ) |
||
399 | + $(LIBSMB_ERR_OBJ) \ |
||
400 | + $(LIBNDR_NTLMSSP_OBJ) |
||
401 | |||
402 | DBWRAP_TORTURE_OBJ = utils/dbwrap_torture.o \ |
||
403 | $(PARAM_OBJ) \ |
||
404 | $(LIB_NONSMBD_OBJ) \ |
||
405 | $(LIBSMB_ERR_OBJ) \ |
||
406 | + $(LIBNDR_NTLMSSP_OBJ) \ |
||
407 | $(POPT_LIB_OBJ) |
||
408 | |||
409 | SPLIT_TOKENS_OBJ = utils/split_tokens.o \ |
||
410 | --- a/source4/torture/raw/samba3misc.c |
||
411 | +++ b/source4/torture/raw/samba3misc.c |
||
412 | @@ -340,6 +340,7 @@ bool torture_samba3_badpath(struct tortu |
||
413 | bool ret = true; |
||
414 | TALLOC_CTX *mem_ctx; |
||
415 | bool nt_status_support; |
||
416 | + bool client_ntlmv2_auth; |
||
417 | |||
418 | if (!(mem_ctx = talloc_init("torture_samba3_badpath"))) { |
||
419 | d_printf("talloc_init failed\n"); |
||
420 | @@ -347,20 +348,17 @@ bool torture_samba3_badpath(struct tortu |
||
421 | } |
||
422 | |||
423 | nt_status_support = lpcfg_nt_status_support(torture->lp_ctx); |
||
424 | + client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(torture->lp_ctx); |
||
425 | |||
426 | - if (!lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes")) { |
||
427 | - printf("Could not set 'nt status support = yes'\n"); |
||
428 | - goto fail; |
||
429 | - } |
||
430 | + torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "yes"), ret, fail, "Could not set 'nt status support = yes'\n"); |
||
431 | + torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", "yes"), ret, fail, "Could not set 'client ntlmv2 auth = yes'\n"); |
||
432 | |||
433 | if (!torture_open_connection(&cli_nt, torture, 0)) { |
||
434 | goto fail; |
||
435 | } |
||
436 | |||
437 | - if (!lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no")) { |
||
438 | - printf("Could not set 'nt status support = yes'\n"); |
||
439 | - goto fail; |
||
440 | - } |
||
441 | + torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", "no"), ret, fail, "Could not set 'nt status support = no'\n"); |
||
442 | + torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", "no"), ret, fail, "Could not set 'client ntlmv2 auth = no'\n"); |
||
443 | |||
444 | if (!torture_open_connection(&cli_dos, torture, 1)) { |
||
445 | goto fail; |
||
446 | @@ -373,6 +371,12 @@ bool torture_samba3_badpath(struct tortu |
||
447 | } |
||
448 | |||
449 | smbcli_deltree(cli_nt->tree, dirname); |
||
450 | + torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "nt status support", |
||
451 | + nt_status_support ? "yes":"no"), |
||
452 | + ret, fail, "Could not set 'nt status support' back to where it was\n"); |
||
453 | + torture_assert_goto(torture, lpcfg_set_cmdline(torture->lp_ctx, "client ntlmv2 auth", |
||
454 | + client_ntlmv2_auth ? "yes":"no"), |
||
455 | + ret, fail, "Could not set 'client ntlmv2 auth' back to where it was\n"); |
||
456 | |||
457 | status = smbcli_mkdir(cli_nt->tree, dirname); |
||
458 | if (!NT_STATUS_IS_OK(status)) { |
||
459 | --- a/source4/torture/basic/base.c |
||
460 | +++ b/source4/torture/basic/base.c |
||
461 | @@ -1476,6 +1476,7 @@ static bool torture_chkpath_test(struct |
||
462 | static bool torture_samba3_errorpaths(struct torture_context *tctx) |
||
463 | { |
||
464 | bool nt_status_support; |
||
465 | + bool client_ntlmv2_auth; |
||
466 | struct smbcli_state *cli_nt = NULL, *cli_dos = NULL; |
||
467 | bool result = false; |
||
468 | int fnum; |
||
469 | @@ -1485,18 +1486,27 @@ static bool torture_samba3_errorpaths(st |
||
470 | NTSTATUS status; |
||
471 | |||
472 | nt_status_support = lpcfg_nt_status_support(tctx->lp_ctx); |
||
473 | + client_ntlmv2_auth = lpcfg_client_ntlmv2_auth(tctx->lp_ctx); |
||
474 | |||
475 | if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "yes")) { |
||
476 | torture_comment(tctx, "Could not set 'nt status support = yes'\n"); |
||
477 | goto fail; |
||
478 | } |
||
479 | + if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "yes")) { |
||
480 | + torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = yes'\n"); |
||
481 | + goto fail; |
||
482 | + } |
||
483 | |||
484 | if (!torture_open_connection(&cli_nt, tctx, 0)) { |
||
485 | goto fail; |
||
486 | } |
||
487 | |||
488 | if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", "no")) { |
||
489 | - torture_comment(tctx, "Could not set 'nt status support = yes'\n"); |
||
490 | + torture_result(tctx, TORTURE_FAIL, "Could not set 'nt status support = no'\n"); |
||
491 | + goto fail; |
||
492 | + } |
||
493 | + if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", "no")) { |
||
494 | + torture_result(tctx, TORTURE_FAIL, "Could not set 'client ntlmv2 auth = no'\n"); |
||
495 | goto fail; |
||
496 | } |
||
497 | |||
498 | @@ -1506,7 +1516,12 @@ static bool torture_samba3_errorpaths(st |
||
499 | |||
500 | if (!lpcfg_set_cmdline(tctx->lp_ctx, "nt status support", |
||
501 | nt_status_support ? "yes":"no")) { |
||
502 | - torture_comment(tctx, "Could not reset 'nt status support = yes'"); |
||
503 | + torture_result(tctx, TORTURE_FAIL, "Could not reset 'nt status support'"); |
||
504 | + goto fail; |
||
505 | + } |
||
506 | + if (!lpcfg_set_cmdline(tctx->lp_ctx, "client ntlmv2 auth", |
||
507 | + client_ntlmv2_auth ? "yes":"no")) { |
||
508 | + torture_result(tctx, TORTURE_FAIL, "Could not reset 'client ntlmv2 auth'"); |
||
509 | goto fail; |
||
510 | } |
||
511 | |||
512 | --- a/source3/libsmb/cliconnect.c |
||
513 | +++ b/source3/libsmb/cliconnect.c |
||
514 | @@ -2077,6 +2077,17 @@ NTSTATUS cli_session_setup(struct cli_st |
||
515 | NTSTATUS status; |
||
516 | |||
517 | /* otherwise do a NT1 style session setup */ |
||
518 | + if (lp_client_ntlmv2_auth() && lp_client_use_spnego()) { |
||
519 | + /* |
||
520 | + * Don't send an NTLMv2 response without NTLMSSP |
||
521 | + * if we want to use spnego support |
||
522 | + */ |
||
523 | + DEBUG(1, ("Server does not support EXTENDED_SECURITY " |
||
524 | + " but 'client use spnego = yes" |
||
525 | + " and 'client ntlmv2 auth = yes'\n")); |
||
526 | + return NT_STATUS_ACCESS_DENIED; |
||
527 | + } |
||
528 | + |
||
529 | status = cli_session_setup_nt1(cli, user, pass, passlen, |
||
530 | ntpass, ntpasslen, workgroup); |
||
531 | if (!NT_STATUS_IS_OK(status)) { |
||
532 | --- a/docs-xml/smbdotconf/protocol/clientusespnego.xml |
||
533 | +++ b/docs-xml/smbdotconf/protocol/clientusespnego.xml |
||
534 | @@ -9,6 +9,11 @@ |
||
535 | supporting servers (including WindowsXP, Windows2000 and Samba |
||
536 | 3.0) to agree upon an authentication |
||
537 | mechanism. This enables Kerberos authentication in particular.</para> |
||
538 | + |
||
539 | + <para>When <smbconfoption name="client NTLMv2 auth"/> is also set to |
||
540 | + <constant>yes</constant> extended security (SPNEGO) is required |
||
541 | + in order to use NTLMv2 only within NTLMSSP. This behavior was |
||
542 | + introduced with the patches for CVE-2016-2111.</para> |
||
543 | </description> |
||
544 | |||
545 | <value type="default">yes</value> |
||
546 | --- a/docs-xml/smbdotconf/security/clientntlmv2auth.xml |
||
547 | +++ b/docs-xml/smbdotconf/security/clientntlmv2auth.xml |
||
548 | @@ -28,6 +28,11 @@ |
||
549 | NTLMv2 by default, and some sites (particularly those following |
||
550 | 'best practice' security polices) only allow NTLMv2 responses, and |
||
551 | not the weaker LM or NTLM.</para> |
||
552 | + |
||
553 | + <para>When <smbconfoption name="client use spnego"/> is also set to |
||
554 | + <constant>yes</constant> extended security (SPNEGO) is required |
||
555 | + in order to use NTLMv2 only within NTLMSSP. This behavior was |
||
556 | + introduced with the patches for CVE-2016-2111.</para> |
||
557 | </description> |
||
558 | <value type="default">yes</value> |
||
559 | </samba:parameter> |
||
560 | --- /dev/null |
||
561 | +++ b/docs-xml/smbdotconf/security/rawntlmv2auth.xml |
||
562 | @@ -0,0 +1,19 @@ |
||
563 | +<samba:parameter name="raw NTLMv2 auth" |
||
564 | + context="G" |
||
565 | + type="boolean" |
||
566 | + xmlns:samba="http://www.samba.org/samba/DTD/samba-doc"> |
||
567 | +<description> |
||
568 | + <para>This parameter determines whether or not <citerefentry><refentrytitle>smbd</refentrytitle> |
||
569 | + <manvolnum>8</manvolnum></citerefentry> will allow SMB1 clients without |
||
570 | + extended security (without SPNEGO) to use NTLMv2 authentication.</para> |
||
571 | + |
||
572 | + <para>If this option, <command moreinfo="none">lanman auth</command> |
||
573 | + and <command moreinfo="none">ntlm auth</command> are all disabled, |
||
574 | + then only clients with SPNEGO support will be permitted. |
||
575 | + That means NTLMv2 is only supported within NTLMSSP.</para> |
||
576 | +</description> |
||
577 | + |
||
578 | +<related>lanman auth</related> |
||
579 | +<related>ntlm auth</related> |
||
580 | +<value type="default">no</value> |
||
581 | +</samba:parameter> |
||
582 | --- a/source3/include/proto.h |
||
583 | +++ b/source3/include/proto.h |
||
584 | @@ -1489,6 +1489,7 @@ bool lp_map_untrusted_to_domain(void); |
||
585 | int lp_restrict_anonymous(void); |
||
586 | bool lp_lanman_auth(void); |
||
587 | bool lp_ntlm_auth(void); |
||
588 | +bool lp_raw_ntlmv2_auth(void); |
||
589 | bool lp_client_plaintext_auth(void); |
||
590 | bool lp_client_lanman_auth(void); |
||
591 | bool lp_client_ntlmv2_auth(void); |
||
592 | --- a/source3/param/loadparm.c |
||
593 | +++ b/source3/param/loadparm.c |
||
594 | @@ -336,6 +336,7 @@ struct global { |
||
595 | bool bAllowTrustedDomains; |
||
596 | bool bLanmanAuth; |
||
597 | bool bNTLMAuth; |
||
598 | + bool bRawNTLMv2Auth; |
||
599 | bool bUseSpnego; |
||
600 | bool bClientLanManAuth; |
||
601 | bool bClientNTLMv2Auth; |
||
602 | @@ -1383,6 +1384,15 @@ static struct parm_struct parm_table[] = |
||
603 | .flags = FLAG_ADVANCED, |
||
604 | }, |
||
605 | { |
||
606 | + .label = "raw NTLMv2 auth", |
||
607 | + .type = P_BOOL, |
||
608 | + .p_class = P_GLOBAL, |
||
609 | + .ptr = &Globals.bRawNTLMv2Auth, |
||
610 | + .special = NULL, |
||
611 | + .enum_list = NULL, |
||
612 | + .flags = FLAG_ADVANCED, |
||
613 | + }, |
||
614 | + { |
||
615 | .label = "client NTLMv2 auth", |
||
616 | .type = P_BOOL, |
||
617 | .p_class = P_GLOBAL, |
||
618 | @@ -5337,6 +5347,7 @@ static void init_globals(bool reinit_glo |
||
619 | Globals.bClientPlaintextAuth = False; /* Do NOT use a plaintext password even if is requested by the server */ |
||
620 | Globals.bLanmanAuth = False; /* Do NOT use the LanMan hash, even if it is supplied */ |
||
621 | Globals.bNTLMAuth = True; /* Do use NTLMv1 if it is supplied by the client (otherwise NTLMv2) */ |
||
622 | + Globals.bRawNTLMv2Auth = false; /* Allow NTLMv2 without NTLMSSP */ |
||
623 | Globals.bClientNTLMv2Auth = True; /* Client should always use use NTLMv2, as we can't tell that the server supports it, but most modern servers do */ |
||
624 | /* Note, that we will also use NTLM2 session security (which is different), if it is available */ |
||
625 | |||
626 | @@ -5819,6 +5830,7 @@ FN_GLOBAL_BOOL(lp_map_untrusted_to_domai |
||
627 | FN_GLOBAL_INTEGER(lp_restrict_anonymous, &Globals.restrict_anonymous) |
||
628 | FN_GLOBAL_BOOL(lp_lanman_auth, &Globals.bLanmanAuth) |
||
629 | FN_GLOBAL_BOOL(lp_ntlm_auth, &Globals.bNTLMAuth) |
||
630 | +FN_GLOBAL_BOOL(lp_raw_ntlmv2_auth, &Globals.bRawNTLMv2Auth) |
||
631 | FN_GLOBAL_BOOL(lp_client_plaintext_auth, &Globals.bClientPlaintextAuth) |
||
632 | FN_GLOBAL_BOOL(lp_client_lanman_auth, &Globals.bClientLanManAuth) |
||
633 | FN_GLOBAL_BOOL(lp_client_ntlmv2_auth, &Globals.bClientNTLMv2Auth) |
||
634 | --- a/source3/auth/auth_util.c |
||
635 | +++ b/source3/auth/auth_util.c |
||
636 | @@ -30,6 +30,7 @@ |
||
637 | #include "../lib/util/util_pw.h" |
||
638 | #include "lib/winbind_util.h" |
||
639 | #include "passdb.h" |
||
640 | +#include "../lib/tsocket/tsocket.h" |
||
641 | |||
642 | #undef DBGC_CLASS |
||
643 | #define DBGC_CLASS DBGC_AUTH |
||
644 | @@ -367,6 +368,19 @@ NTSTATUS make_user_info_for_reply_enc(st |
||
645 | const char *client_domain, |
||
646 | DATA_BLOB lm_resp, DATA_BLOB nt_resp) |
||
647 | { |
||
648 | + bool allow_raw = lp_raw_ntlmv2_auth(); |
||
649 | + |
||
650 | + if (!allow_raw && nt_resp.length >= 48) { |
||
651 | + /* |
||
652 | + * NTLMv2_RESPONSE has at least 48 bytes |
||
653 | + * and should only be supported via NTLMSSP. |
||
654 | + */ |
||
655 | + DEBUG(2,("Rejecting raw NTLMv2 authentication with " |
||
656 | + "user [%s\\%s]\n", |
||
657 | + client_domain, smb_name)); |
||
658 | + return NT_STATUS_INVALID_PARAMETER; |
||
659 | + } |
||
660 | + |
||
661 | return make_user_info_map(user_info, smb_name, |
||
662 | client_domain, |
||
663 | get_remote_machine_name(), |
||
664 | --- a/selftest/target/Samba3.pm |
||
665 | +++ b/selftest/target/Samba3.pm |
||
666 | @@ -127,6 +127,7 @@ sub setup_dc($$) |
||
667 | domain master = yes |
||
668 | domain logons = yes |
||
669 | lanman auth = yes |
||
670 | + raw NTLMv2 auth = yes |
||
671 | "; |
||
672 | |||
673 | my $vars = $self->provision($path, |
||
674 | @@ -230,6 +231,7 @@ sub setup_secserver($$$) |
||
675 | my $secserver_options = " |
||
676 | security = server |
||
677 | password server = $s3dcvars->{SERVER_IP} |
||
678 | + client ntlmv2 auth = no |
||
679 | "; |
||
680 | |||
681 | my $ret = $self->provision($prefix, |