2
0

024-CVE-2016-2111-v3-6.patch 24 KB

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