View | Details | Raw Unified | Return to bug 266641
Collapse All | Expand All

(-)b/net/samba413/Makefile (-4 / +4 lines)
Lines 1-6 Link Here
1
PORTNAME=			${SAMBA4_BASENAME}413
1
PORTNAME=			${SAMBA4_BASENAME}413
2
PORTVERSION=			${SAMBA4_VERSION}
2
PORTVERSION=			${SAMBA4_VERSION}
3
PORTREVISION=			1
3
PORTREVISION=			2
4
CATEGORIES?=			net
4
CATEGORIES?=			net
5
MASTER_SITES=			SAMBA/samba/stable SAMBA/samba/rc
5
MASTER_SITES=			SAMBA/samba/stable SAMBA/samba/rc
6
DISTNAME=			${SAMBA4_DISTNAME}
6
DISTNAME=			${SAMBA4_DISTNAME}
Lines 96-102 OPTIONS_SINGLE_GSSAPI= GSSAPI_BUILTIN GSSAPI_MIT Link Here
96
OPTIONS_SINGLE_ZEROCONF=	ZEROCONF_NONE AVAHI MDNSRESPONDER
96
OPTIONS_SINGLE_ZEROCONF=	ZEROCONF_NONE AVAHI MDNSRESPONDER
97
97
98
OPTIONS_RADIO=			DNS
98
OPTIONS_RADIO=			DNS
99
OPTIONS_RADIO_DNS=		NSUPDATE BIND911 BIND916
99
OPTIONS_RADIO_DNS=		NSUPDATE BIND916 BIND918
100
# Make those default options
100
# Make those default options
101
OPTIONS_DEFAULT=		AD_DC ADS DOCS FAM LDAP \
101
OPTIONS_DEFAULT=		AD_DC ADS DOCS FAM LDAP \
102
				PROFILE PYTHON3 QUOTAS SYSLOG UTMP \
102
				PROFILE PYTHON3 QUOTAS SYSLOG UTMP \
Lines 129-136 ZEROCONF_DESC= Zero configuration networking Link Here
129
ZEROCONF_NONE_DESC=		Zeroconf support is absent
129
ZEROCONF_NONE_DESC=		Zeroconf support is absent
130
130
131
DNS_DESC=			DNS frontend
131
DNS_DESC=			DNS frontend
132
BIND911_DESC=			Use Bind 9.11 as AD DC DNS server frontend
133
BIND916_DESC=			Use Bind 9.16 as AD DC DNS server frontend
132
BIND916_DESC=			Use Bind 9.16 as AD DC DNS server frontend
133
BIND918_DESC=			Use Bind 9.18 as AD DC DNS server frontend
134
NSUPDATE_DESC=			Use samba NSUPDATE utility for AD DC
134
NSUPDATE_DESC=			Use samba NSUPDATE utility for AD DC
135
##############################################################################
135
##############################################################################
136
# XXX: Unconditional dependencies which can't be switched off(if present in
136
# XXX: Unconditional dependencies which can't be switched off(if present in
Lines 299-306 MDNSRESPONDER_CONFIGURE_ENABLE= dnssd Link Here
299
MDNSRESPONDER_LIB_DEPENDS=	libdns_sd.so:net/mDNSResponder
299
MDNSRESPONDER_LIB_DEPENDS=	libdns_sd.so:net/mDNSResponder
300
MDNSRESPONDER_VARS=		SAMBA4_SERVICES+=mdnsd
300
MDNSRESPONDER_VARS=		SAMBA4_SERVICES+=mdnsd
301
##############################################################################
301
##############################################################################
302
BIND911_RUN_DEPENDS=		bind911>=9.11.0.0:dns/bind911
303
BIND916_RUN_DEPENDS=		bind916>=9.16.0.0:dns/bind916
302
BIND916_RUN_DEPENDS=		bind916>=9.16.0.0:dns/bind916
303
BIND918_RUN_DEPENDS=		bind918>=9.18.0.0:dns/bind918
304
NSUPDATE_RUN_DEPENDS=		samba-nsupdate:dns/samba-nsupdate
304
NSUPDATE_RUN_DEPENDS=		samba-nsupdate:dns/samba-nsupdate
305
##############################################################################
305
##############################################################################
306
MEMORY_DEBUG_IMPLIES=		DEBUG
306
MEMORY_DEBUG_IMPLIES=		DEBUG
(-)b/net/samba413/files/patch-samba-4.14.14 (+13366 lines)
Added Link Here
1
From 5d958156c7e5d6c1da61d18fe4fd105b22639b56 Mon Sep 17 00:00:00 2001
2
From: Joseph Sutton <josephsutton@catalyst.net.nz>
3
Date: Tue, 14 Jun 2022 21:09:53 +1200
4
Subject: [PATCH 01/99] CVE-2022-32746 s4/dsdb/objectclass_attrs: Fix typo
5
6
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
7
8
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
9
---
10
 source4/dsdb/samdb/ldb_modules/objectclass_attrs.c | 2 +-
11
 1 file changed, 1 insertion(+), 1 deletion(-)
12
13
diff --git source4/dsdb/samdb/ldb_modules/objectclass_attrs.c source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
14
index 6ab46a729a2..2a77353cdfc 100644
15
--- source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
16
+++ source4/dsdb/samdb/ldb_modules/objectclass_attrs.c
17
@@ -263,7 +263,7 @@ static int attr_handler(struct oc_context *ac)
18
 												LDB_CONTROL_AS_SYSTEM_OID);
19
 					if (!dsdb_module_am_system(ac->module) && !as_system) {
20
 						ldb_asprintf_errstring(ldb,
21
-								       "objectclass_attrs: attribute '%s' on entry '%s' must can only be modified as system",
22
+								       "objectclass_attrs: attribute '%s' on entry '%s' can only be modified as system",
23
 								       msg->elements[i].name,
24
 								       ldb_dn_get_linearized(msg->dn));
25
 						return LDB_ERR_CONSTRAINT_VIOLATION;
26
-- 
27
2.25.1
28
29
30
From 51cbeff886fe01db463448f8655a43d10040dc8b Mon Sep 17 00:00:00 2001
31
From: Joseph Sutton <josephsutton@catalyst.net.nz>
32
Date: Tue, 21 Jun 2022 15:37:15 +1200
33
Subject: [PATCH 02/99] CVE-2022-32746 s4:dsdb:tests: Add test for deleting a
34
 disallowed SPN
35
36
If an account has an SPN that requires Write Property to set, we should
37
still be able to delete it with just Validated Write.
38
39
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
40
41
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
42
---
43
 selftest/knownfail.d/acl-spn-delete |  1 +
44
 source4/dsdb/tests/python/acl.py    | 26 ++++++++++++++++++++++++++
45
 2 files changed, 27 insertions(+)
46
 create mode 100644 selftest/knownfail.d/acl-spn-delete
47
48
diff --git selftest/knownfail.d/acl-spn-delete selftest/knownfail.d/acl-spn-delete
49
new file mode 100644
50
index 00000000000..32018413c49
51
--- /dev/null
52
+++ selftest/knownfail.d/acl-spn-delete
53
@@ -0,0 +1 @@
54
+^samba4.ldap.acl.python.*__main__.AclSPNTests.test_delete_disallowed_spn\(
55
diff --git source4/dsdb/tests/python/acl.py source4/dsdb/tests/python/acl.py
56
index df0fe12bf29..d90d3b3923f 100755
57
--- source4/dsdb/tests/python/acl.py
58
+++ source4/dsdb/tests/python/acl.py
59
@@ -2286,6 +2286,32 @@ class AclSPNTests(AclTests):
60
         else:
61
             self.fail(f'able to add disallowed SPN {not_allowed_spn}')
62
 
63
+    def test_delete_disallowed_spn(self):
64
+        # Grant Validated-SPN property.
65
+        mod = f'(OA;;SW;{security.GUID_DRS_VALIDATE_SPN};;{self.user_sid1})'
66
+        self.sd_utils.dacl_add_ace(self.computerdn, mod)
67
+
68
+        spn_base = f'HOST/{self.computername}'
69
+
70
+        not_allowed_spn = f'{spn_base}/{self.dcctx.get_domain_name()}'
71
+
72
+        # Add a disallowed SPN as admin.
73
+        msg = Message(Dn(self.ldb_admin, self.computerdn))
74
+        msg['servicePrincipalName'] = MessageElement(not_allowed_spn,
75
+                                                     FLAG_MOD_ADD,
76
+                                                     'servicePrincipalName')
77
+        self.ldb_admin.modify(msg)
78
+
79
+        # Ensure we are able to delete a disallowed SPN.
80
+        msg = Message(Dn(self.ldb_user1, self.computerdn))
81
+        msg['servicePrincipalName'] = MessageElement(not_allowed_spn,
82
+                                                     FLAG_MOD_DELETE,
83
+                                                     'servicePrincipalName')
84
+        try:
85
+            self.ldb_user1.modify(msg)
86
+        except LdbError:
87
+            self.fail(f'unable to delete disallowed SPN {not_allowed_spn}')
88
+
89
 
90
 # tests SEC_ADS_LIST vs. SEC_ADS_LIST_OBJECT
91
 @DynamicTestCase
92
-- 
93
2.25.1
94
95
96
From a68553792a8512a2d266bbb86f064f78b5482a65 Mon Sep 17 00:00:00 2001
97
From: Joseph Sutton <josephsutton@catalyst.net.nz>
98
Date: Tue, 21 Jun 2022 14:41:02 +1200
99
Subject: [PATCH 03/99] CVE-2022-32746 s4/dsdb/partition: Fix LDB flags
100
 comparison
101
102
LDB_FLAG_MOD_* values are not actually flags, and the previous
103
comparison was equivalent to
104
105
(req_msg->elements[el_idx].flags & LDB_FLAG_MOD_MASK) != 0
106
107
which is true whenever any of the LDB_FLAG_MOD_* values are set. Correct
108
the expression to what it was probably intended to be.
109
110
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
111
112
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
113
---
114
 source4/dsdb/samdb/ldb_modules/partition.c | 4 ++--
115
 1 file changed, 2 insertions(+), 2 deletions(-)
116
117
diff --git source4/dsdb/samdb/ldb_modules/partition.c source4/dsdb/samdb/ldb_modules/partition.c
118
index 2544a106d13..2d90ca5d1b3 100644
119
--- source4/dsdb/samdb/ldb_modules/partition.c
120
+++ source4/dsdb/samdb/ldb_modules/partition.c
121
@@ -493,8 +493,8 @@ static int partition_copy_all_callback_action(
122
 			 * them here too
123
 			 */
124
 			for (el_idx=0; el_idx < req_msg->num_elements; el_idx++) {
125
-				if (req_msg->elements[el_idx].flags & LDB_FLAG_MOD_DELETE
126
-				    || ((req_msg->elements[el_idx].flags & LDB_FLAG_MOD_REPLACE) &&
127
+				if (LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_DELETE
128
+				    || ((LDB_FLAG_MOD_TYPE(req_msg->elements[el_idx].flags) == LDB_FLAG_MOD_REPLACE) &&
129
 					req_msg->elements[el_idx].num_values == 0)) {
130
 					if (ldb_msg_find_element(modify_msg,
131
 								 req_msg->elements[el_idx].name) != NULL) {
132
-- 
133
2.25.1
134
135
136
From 582ac171364f0c28f54eaf4f21b5bfa7569b5233 Mon Sep 17 00:00:00 2001
137
From: Joseph Sutton <josephsutton@catalyst.net.nz>
138
Date: Tue, 21 Jun 2022 14:49:51 +1200
139
Subject: [PATCH 04/99] CVE-2022-32746 s4:torture: Fix LDB flags comparison
140
141
LDB_FLAG_MOD_* values are not actually flags, and the previous
142
comparison was equivalent to
143
144
(el->flags & LDB_FLAG_MOD_MASK) == 0
145
146
which is only true if none of the LDB_FLAG_MOD_* values are set. Correct
147
the expression to what it was probably intended to be.
148
149
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
150
151
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
152
---
153
 source4/torture/drs/rpc/dssync.c | 4 +++-
154
 1 file changed, 3 insertions(+), 1 deletion(-)
155
156
diff --git source4/torture/drs/rpc/dssync.c source4/torture/drs/rpc/dssync.c
157
index cde9f78692b..ff7ce2d9074 100644
158
--- source4/torture/drs/rpc/dssync.c
159
+++ source4/torture/drs/rpc/dssync.c
160
@@ -527,7 +527,9 @@ static bool test_analyse_objects(struct torture_context *tctx,
161
 				el = &new_msg->elements[idx];
162
 				a = dsdb_attribute_by_lDAPDisplayName(ldap_schema,
163
 				                                      el->name);
164
-				if (!(el->flags & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE))) {
165
+				if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD &&
166
+				    LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE)
167
+				{
168
 					/* DRS only value */
169
 					is_warning = false;
170
 				} else if (a->linkID & 1) {
171
-- 
172
2.25.1
173
174
175
From 0526d27e9eddd9c2a54434cf0dcdb136a6c659e4 Mon Sep 17 00:00:00 2001
176
From: Joseph Sutton <josephsutton@catalyst.net.nz>
177
Date: Tue, 21 Jun 2022 15:22:47 +1200
178
Subject: [PATCH 05/99] CVE-2022-32746 s4/dsdb/acl: Fix LDB flags comparison
179
180
LDB_FLAG_MOD_* values are not actually flags, and the previous
181
comparison was equivalent to
182
183
(el->flags & LDB_FLAG_MOD_MASK) == 0
184
185
which is only true if none of the LDB_FLAG_MOD_* values are set, so we
186
would not successfully return if the element was a DELETE. Correct the
187
expression to what it was intended to be.
188
189
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
190
191
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
192
---
193
 selftest/knownfail.d/acl-spn-delete  | 1 -
194
 source4/dsdb/samdb/ldb_modules/acl.c | 5 +++--
195
 2 files changed, 3 insertions(+), 3 deletions(-)
196
 delete mode 100644 selftest/knownfail.d/acl-spn-delete
197
198
diff --git selftest/knownfail.d/acl-spn-delete selftest/knownfail.d/acl-spn-delete
199
deleted file mode 100644
200
index 32018413c49..00000000000
201
--- selftest/knownfail.d/acl-spn-delete
202
+++ /dev/null
203
@@ -1 +0,0 @@
204
-^samba4.ldap.acl.python.*__main__.AclSPNTests.test_delete_disallowed_spn\(
205
diff --git source4/dsdb/samdb/ldb_modules/acl.c source4/dsdb/samdb/ldb_modules/acl.c
206
index 21e83276bfd..8016a2d4bd0 100644
207
--- source4/dsdb/samdb/ldb_modules/acl.c
208
+++ source4/dsdb/samdb/ldb_modules/acl.c
209
@@ -734,8 +734,9 @@ static int acl_check_spn(TALLOC_CTX *mem_ctx,
210
 		 * If not add or replace (eg delete),
211
 		 * return success
212
 		 */
213
-		if ((el->flags
214
-		     & (LDB_FLAG_MOD_ADD|LDB_FLAG_MOD_REPLACE)) == 0) {
215
+		if (LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_ADD &&
216
+		    LDB_FLAG_MOD_TYPE(el->flags) != LDB_FLAG_MOD_REPLACE)
217
+		{
218
 			talloc_free(tmp_ctx);
219
 			return LDB_SUCCESS;
220
 		}
221
-- 
222
2.25.1
223
224
225
From 2869b5aa3148869edf0d079266542aef6e64608e Mon Sep 17 00:00:00 2001
226
From: Joseph Sutton <josephsutton@catalyst.net.nz>
227
Date: Wed, 16 Feb 2022 12:43:52 +1300
228
Subject: [PATCH 06/99] CVE-2022-32746 ldb:rdn_name: Use LDB_FLAG_MOD_TYPE()
229
 for flags equality check
230
231
Now unrelated flags will no longer affect the result.
232
233
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
234
235
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
236
---
237
 lib/ldb/modules/rdn_name.c | 2 +-
238
 1 file changed, 1 insertion(+), 1 deletion(-)
239
240
diff --git lib/ldb/modules/rdn_name.c lib/ldb/modules/rdn_name.c
241
index e69ad9315ae..25cffe07591 100644
242
--- lib/ldb/modules/rdn_name.c
243
+++ lib/ldb/modules/rdn_name.c
244
@@ -545,7 +545,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
245
 	if (e != NULL) {
246
 		ldb_asprintf_errstring(ldb, "Modify of 'distinguishedName' on %s not permitted, must use 'rename' operation instead",
247
 				       ldb_dn_get_linearized(req->op.mod.message->dn));
248
-		if (e->flags == LDB_FLAG_MOD_REPLACE) {
249
+		if (LDB_FLAG_MOD_TYPE(e->flags) == LDB_FLAG_MOD_REPLACE) {
250
 			return LDB_ERR_CONSTRAINT_VIOLATION;
251
 		} else {
252
 			return LDB_ERR_UNWILLING_TO_PERFORM;
253
-- 
254
2.25.1
255
256
257
From 535b5a366a2ad054f729e57e282e402cf13b2efc Mon Sep 17 00:00:00 2001
258
From: Joseph Sutton <josephsutton@catalyst.net.nz>
259
Date: Tue, 14 Jun 2022 19:49:19 +1200
260
Subject: [PATCH 07/99] CVE-2022-32746 s4/dsdb/repl_meta_data: Use
261
 LDB_FLAG_MOD_TYPE() for flags equality check
262
263
Now unrelated flags will no longer affect the result.
264
265
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
266
267
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
268
---
269
 source4/dsdb/samdb/ldb_modules/repl_meta_data.c | 8 ++++----
270
 1 file changed, 4 insertions(+), 4 deletions(-)
271
272
diff --git source4/dsdb/samdb/ldb_modules/repl_meta_data.c source4/dsdb/samdb/ldb_modules/repl_meta_data.c
273
index ab506cec488..29ffda75c87 100644
274
--- source4/dsdb/samdb/ldb_modules/repl_meta_data.c
275
+++ source4/dsdb/samdb/ldb_modules/repl_meta_data.c
276
@@ -3525,7 +3525,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
277
 			return ldb_module_operr(module);
278
 		}
279
 
280
-		if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_REPLACE) {
281
+		if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_REPLACE) {
282
 			return ldb_module_operr(module);
283
 		}
284
 
285
@@ -3558,11 +3558,11 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
286
 			return ldb_module_operr(module);
287
 		}
288
 
289
-		if (req->op.mod.message->elements[0].flags != LDB_FLAG_MOD_DELETE) {
290
+		if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[0].flags) != LDB_FLAG_MOD_DELETE) {
291
 			return ldb_module_operr(module);
292
 		}
293
 
294
-		if (req->op.mod.message->elements[1].flags != LDB_FLAG_MOD_ADD) {
295
+		if (LDB_FLAG_MOD_TYPE(req->op.mod.message->elements[1].flags) != LDB_FLAG_MOD_ADD) {
296
 			return ldb_module_operr(module);
297
 		}
298
 
299
@@ -3645,7 +3645,7 @@ static int replmd_modify(struct ldb_module *module, struct ldb_request *req)
300
 			return ldb_module_operr(module);
301
 		}
302
 
303
-		if (msg->elements[0].flags != LDB_FLAG_MOD_ADD) {
304
+		if (LDB_FLAG_MOD_TYPE(msg->elements[0].flags) != LDB_FLAG_MOD_ADD) {
305
 			talloc_free(ac);
306
 			return ldb_module_operr(module);
307
 		}
308
-- 
309
2.25.1
310
311
312
From bedd0b768c3f92645af033399aefd7ee971d9150 Mon Sep 17 00:00:00 2001
313
From: Joseph Sutton <josephsutton@catalyst.net.nz>
314
Date: Tue, 14 Jun 2022 21:11:33 +1200
315
Subject: [PATCH 08/99] CVE-2022-32746 s4/dsdb/tombstone_reanimate: Use
316
 LDB_FLAG_MOD_TYPE() for flags equality check
317
318
Now unrelated flags will no longer affect the result.
319
320
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
321
322
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
323
---
324
 source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c | 4 ++--
325
 1 file changed, 2 insertions(+), 2 deletions(-)
326
327
diff --git source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c
328
index 64e05195798..5f8911c66be 100644
329
--- source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c
330
+++ source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c
331
@@ -104,7 +104,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req,
332
 	if (el_dn == NULL) {
333
 		return false;
334
 	}
335
-	if (el_dn->flags != LDB_FLAG_MOD_REPLACE) {
336
+	if (LDB_FLAG_MOD_TYPE(el_dn->flags) != LDB_FLAG_MOD_REPLACE) {
337
 		return false;
338
 	}
339
 	if (el_dn->num_values != 1) {
340
@@ -117,7 +117,7 @@ static bool is_tombstone_reanimate_request(struct ldb_request *req,
341
 		return false;
342
 	}
343
 
344
-	if (el_deleted->flags != LDB_FLAG_MOD_DELETE) {
345
+	if (LDB_FLAG_MOD_TYPE(el_deleted->flags) != LDB_FLAG_MOD_DELETE) {
346
 		return false;
347
 	}
348
 
349
-- 
350
2.25.1
351
352
353
From 49dd9042f4ee380fa1dafcebcb54d0e1f0852463 Mon Sep 17 00:00:00 2001
354
From: Joseph Sutton <josephsutton@catalyst.net.nz>
355
Date: Tue, 14 Jun 2022 21:12:39 +1200
356
Subject: [PATCH 09/99] CVE-2022-32746 s4/registry: Use LDB_FLAG_MOD_TYPE() for
357
 flags equality check
358
359
Now unrelated flags will no longer affect the result.
360
361
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
362
363
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
364
---
365
 source4/lib/registry/ldb.c | 2 +-
366
 1 file changed, 1 insertion(+), 1 deletion(-)
367
368
diff --git source4/lib/registry/ldb.c source4/lib/registry/ldb.c
369
index e089355975b..db383a560da 100644
370
--- source4/lib/registry/ldb.c
371
+++ source4/lib/registry/ldb.c
372
@@ -859,7 +859,7 @@ static WERROR ldb_set_value(struct hive_key *parent,
373
 
374
 	/* Try first a "modify" and if this doesn't work do try an "add" */
375
 	for (i = 0; i < msg->num_elements; i++) {
376
-		if (msg->elements[i].flags != LDB_FLAG_MOD_DELETE) {
377
+		if (LDB_FLAG_MOD_TYPE(msg->elements[i].flags) != LDB_FLAG_MOD_DELETE) {
378
 			msg->elements[i].flags = LDB_FLAG_MOD_REPLACE;
379
 		}
380
 	}
381
-- 
382
2.25.1
383
384
385
From faa61ab3053d077ac9d0aa67e955217e85b660f4 Mon Sep 17 00:00:00 2001
386
From: Joseph Sutton <josephsutton@catalyst.net.nz>
387
Date: Mon, 21 Feb 2022 16:10:32 +1300
388
Subject: [PATCH 10/99] CVE-2022-32746 ldb: Add flag to mark message element
389
 values as shared
390
391
When making a shallow copy of an ldb message, mark the message elements
392
of the copy as sharing their values with the message elements in the
393
original message.
394
395
This flag value will be heeded in the next commit.
396
397
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
398
399
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
400
---
401
 lib/ldb/common/ldb_msg.c     | 43 +++++++++++++++++++++++++++++++-----
402
 lib/ldb/include/ldb_module.h |  6 +++++
403
 2 files changed, 43 insertions(+), 6 deletions(-)
404
405
diff --git lib/ldb/common/ldb_msg.c lib/ldb/common/ldb_msg.c
406
index 57dfc5a04c2..2a9ce384bb9 100644
407
--- lib/ldb/common/ldb_msg.c
408
+++ lib/ldb/common/ldb_msg.c
409
@@ -833,11 +833,7 @@ void ldb_msg_sort_elements(struct ldb_message *msg)
410
 		       ldb_msg_element_compare_name);
411
 }
412
 
413
-/*
414
-  shallow copy a message - copying only the elements array so that the caller
415
-  can safely add new elements without changing the message
416
-*/
417
-struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
418
+static struct ldb_message *ldb_msg_copy_shallow_impl(TALLOC_CTX *mem_ctx,
419
 					 const struct ldb_message *msg)
420
 {
421
 	struct ldb_message *msg2;
422
@@ -863,6 +859,35 @@ failed:
423
 	return NULL;
424
 }
425
 
426
+/*
427
+  shallow copy a message - copying only the elements array so that the caller
428
+  can safely add new elements without changing the message
429
+*/
430
+struct ldb_message *ldb_msg_copy_shallow(TALLOC_CTX *mem_ctx,
431
+					 const struct ldb_message *msg)
432
+{
433
+	struct ldb_message *msg2;
434
+	unsigned int i;
435
+
436
+	msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
437
+	if (msg2 == NULL) {
438
+		return NULL;
439
+	}
440
+
441
+	for (i = 0; i < msg2->num_elements; ++i) {
442
+		/*
443
+		 * Mark this message's elements as sharing their values with the
444
+		 * original message, so that we don't inadvertently modify or
445
+		 * free them. We don't mark the original message element as
446
+		 * shared, so the original message element should not be
447
+		 * modified or freed while the shallow copy lives.
448
+		 */
449
+		struct ldb_message_element *el = &msg2->elements[i];
450
+		el->flags |= LDB_FLAG_INTERNAL_SHARED_VALUES;
451
+	}
452
+
453
+        return msg2;
454
+}
455
 
456
 /*
457
   copy a message, allocating new memory for all parts
458
@@ -873,7 +898,7 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
459
 	struct ldb_message *msg2;
460
 	unsigned int i, j;
461
 
462
-	msg2 = ldb_msg_copy_shallow(mem_ctx, msg);
463
+	msg2 = ldb_msg_copy_shallow_impl(mem_ctx, msg);
464
 	if (msg2 == NULL) return NULL;
465
 
466
 	if (msg2->dn != NULL) {
467
@@ -894,6 +919,12 @@ struct ldb_message *ldb_msg_copy(TALLOC_CTX *mem_ctx,
468
 				goto failed;
469
 			}
470
 		}
471
+
472
+                /*
473
+                 * Since we copied this element's values, we can mark them as
474
+                 * not shared.
475
+		 */
476
+		el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
477
 	}
478
 
479
 	return msg2;
480
diff --git lib/ldb/include/ldb_module.h lib/ldb/include/ldb_module.h
481
index 8c1e5ee7936..4c7c85a17f0 100644
482
--- lib/ldb/include/ldb_module.h
483
+++ lib/ldb/include/ldb_module.h
484
@@ -96,6 +96,12 @@ struct ldb_module;
485
  */
486
 #define LDB_FLAG_INTERNAL_FORCE_UNIQUE_INDEX 0x100
487
 
488
+/*
489
+ * indicates that this element's values are shared with another element (for
490
+ * example, in a shallow copy of an ldb_message) and should not be freed
491
+ */
492
+#define LDB_FLAG_INTERNAL_SHARED_VALUES 0x200
493
+
494
 /* an extended match rule that always fails to match */
495
 #define SAMBA_LDAP_MATCH_ALWAYS_FALSE "1.3.6.1.4.1.7165.4.5.1"
496
 
497
-- 
498
2.25.1
499
500
501
From 4e5fb78c3dcff60aa8fd4b07dad4660bbb30532b Mon Sep 17 00:00:00 2001
502
From: Joseph Sutton <josephsutton@catalyst.net.nz>
503
Date: Wed, 16 Feb 2022 12:35:13 +1300
504
Subject: [PATCH 11/99] CVE-2022-32746 ldb: Ensure shallow copy modifications
505
 do not affect original message
506
507
Using the newly added ldb flag, we can now detect when a message has
508
been shallow-copied so that its elements share their values with the
509
original message elements. Then when adding values to the copied
510
message, we now make a copy of the shared values array first.
511
512
This should prevent a use-after-free that occurred in LDB modules when
513
new values were added to a shallow copy of a message by calling
514
talloc_realloc() on the original values array, invalidating the 'values'
515
pointer in the original message element. The original values pointer can
516
later be used in the database audit logging module which logs database
517
requests, and potentially cause a crash.
518
519
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
520
521
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
522
---
523
 lib/ldb/common/ldb_msg.c   | 52 ++++++++++++++++++++++++++++++++------
524
 lib/ldb/include/ldb.h      |  6 +++++
525
 source4/dsdb/common/util.c | 20 +++++----------
526
 3 files changed, 56 insertions(+), 22 deletions(-)
527
528
diff --git lib/ldb/common/ldb_msg.c lib/ldb/common/ldb_msg.c
529
index 2a9ce384bb9..44d3b29e9a7 100644
530
--- lib/ldb/common/ldb_msg.c
531
+++ lib/ldb/common/ldb_msg.c
532
@@ -417,6 +417,47 @@ int ldb_msg_add(struct ldb_message *msg,
533
 	return LDB_SUCCESS;
534
 }
535
 
536
+/*
537
+ * add a value to a message element
538
+ */
539
+int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
540
+			      struct ldb_message_element *el,
541
+			      const struct ldb_val *val)
542
+{
543
+	struct ldb_val *vals;
544
+
545
+	if (el->flags & LDB_FLAG_INTERNAL_SHARED_VALUES) {
546
+		/*
547
+		 * Another message is using this message element's values array,
548
+		 * so we don't want to make any modifications to the original
549
+		 * message, or potentially invalidate its own values by calling
550
+		 * talloc_realloc(). Make a copy instead.
551
+		 */
552
+		el->flags &= ~LDB_FLAG_INTERNAL_SHARED_VALUES;
553
+
554
+		vals = talloc_array(mem_ctx, struct ldb_val,
555
+				    el->num_values + 1);
556
+		if (vals == NULL) {
557
+			return LDB_ERR_OPERATIONS_ERROR;
558
+		}
559
+
560
+		if (el->values != NULL) {
561
+			memcpy(vals, el->values, el->num_values * sizeof(struct ldb_val));
562
+		}
563
+	} else {
564
+		vals = talloc_realloc(mem_ctx, el->values, struct ldb_val,
565
+				      el->num_values + 1);
566
+		if (vals == NULL) {
567
+			return LDB_ERR_OPERATIONS_ERROR;
568
+		}
569
+	}
570
+	el->values = vals;
571
+	el->values[el->num_values] = *val;
572
+	el->num_values++;
573
+
574
+	return LDB_SUCCESS;
575
+}
576
+
577
 /*
578
   add a value to a message
579
 */
580
@@ -426,7 +467,6 @@ int ldb_msg_add_value(struct ldb_message *msg,
581
 		      struct ldb_message_element **return_el)
582
 {
583
 	struct ldb_message_element *el;
584
-	struct ldb_val *vals;
585
 	int ret;
586
 
587
 	el = ldb_msg_find_element(msg, attr_name);
588
@@ -437,14 +477,10 @@ int ldb_msg_add_value(struct ldb_message *msg,
589
 		}
590
 	}
591
 
592
-	vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
593
-			      el->num_values+1);
594
-	if (!vals) {
595
-		return LDB_ERR_OPERATIONS_ERROR;
596
+	ret = ldb_msg_element_add_value(msg->elements, el, val);
597
+	if (ret != LDB_SUCCESS) {
598
+		return ret;
599
 	}
600
-	el->values = vals;
601
-	el->values[el->num_values] = *val;
602
-	el->num_values++;
603
 
604
 	if (return_el) {
605
 		*return_el = el;
606
diff --git lib/ldb/include/ldb.h lib/ldb/include/ldb.h
607
index bc44157eaf4..129beefeaf5 100644
608
--- lib/ldb/include/ldb.h
609
+++ lib/ldb/include/ldb.h
610
@@ -1981,6 +1981,12 @@ int ldb_msg_add_empty(struct ldb_message *msg,
611
 		int flags,
612
 		struct ldb_message_element **return_el);
613
 
614
+/**
615
+   add a value to a message element
616
+*/
617
+int ldb_msg_element_add_value(TALLOC_CTX *mem_ctx,
618
+			      struct ldb_message_element *el,
619
+			      const struct ldb_val *val);
620
 /**
621
    add a element to a ldb_message
622
 */
623
diff --git source4/dsdb/common/util.c source4/dsdb/common/util.c
624
index 5ce4c0a5e33..577b2a33873 100644
625
--- source4/dsdb/common/util.c
626
+++ source4/dsdb/common/util.c
627
@@ -816,7 +816,7 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
628
 			 const char *value)
629
 {
630
 	struct ldb_message_element *el;
631
-	struct ldb_val val, *vals;
632
+	struct ldb_val val;
633
 	char *v;
634
 	unsigned int i;
635
 	bool found = false;
636
@@ -851,14 +851,10 @@ int samdb_msg_add_addval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
637
 		}
638
 	}
639
 
640
-	vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
641
-			      el->num_values + 1);
642
-	if (vals == NULL) {
643
+	ret = ldb_msg_element_add_value(msg->elements, el, &val);
644
+	if (ret != LDB_SUCCESS) {
645
 		return ldb_oom(sam_ldb);
646
 	}
647
-	el->values = vals;
648
-	el->values[el->num_values] = val;
649
-	++(el->num_values);
650
 
651
 	return LDB_SUCCESS;
652
 }
653
@@ -872,7 +868,7 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
654
 			 const char *value)
655
 {
656
 	struct ldb_message_element *el;
657
-	struct ldb_val val, *vals;
658
+	struct ldb_val val;
659
 	char *v;
660
 	unsigned int i;
661
 	bool found = false;
662
@@ -907,14 +903,10 @@ int samdb_msg_add_delval(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx,
663
 		}
664
 	}
665
 
666
-	vals = talloc_realloc(msg->elements, el->values, struct ldb_val,
667
-			      el->num_values + 1);
668
-	if (vals == NULL) {
669
+	ret = ldb_msg_element_add_value(msg->elements, el, &val);
670
+	if (ret != LDB_SUCCESS) {
671
 		return ldb_oom(sam_ldb);
672
 	}
673
-	el->values = vals;
674
-	el->values[el->num_values] = val;
675
-	++(el->num_values);
676
 
677
 	return LDB_SUCCESS;
678
 }
679
-- 
680
2.25.1
681
682
683
From 512a2617b1593bdc16caeeeda4312a581cbb34e9 Mon Sep 17 00:00:00 2001
684
From: Joseph Sutton <josephsutton@catalyst.net.nz>
685
Date: Wed, 16 Feb 2022 16:30:03 +1300
686
Subject: [PATCH 12/99] CVE-2022-32746 ldb: Add functions for appending to an
687
 ldb_message
688
689
Currently, there are many places where we use ldb_msg_add_empty() to add
690
an empty element to a message, and then call ldb_msg_add_value() or
691
similar to add values to that element. However, this performs an
692
unnecessary search of the message's elements to locate the new element.
693
Moreover, if an element with the same attribute name already exists
694
earlier in the message, the values will be added to that element,
695
instead of to the intended newly added element.
696
697
A similar pattern exists where we add values to a message, and then call
698
ldb_msg_find_element() to locate that message element and sets its flags
699
to (e.g.) LDB_FLAG_MOD_REPLACE. This also performs an unnecessary
700
search, and may locate the wrong message element for setting the flags.
701
702
To avoid these problems, add functions for appending a value to a
703
message, so that a particular value can be added to the end of a message
704
in a single operation.
705
706
For ADD requests, it is important that no two message elements share the
707
same attribute name, otherwise things will break. (Normally,
708
ldb_msg_normalize() is called before processing the request to help
709
ensure this.) Thus, we must be careful not to append an attribute to an
710
ADD message, unless we are sure (e.g. through ldb_msg_find_element())
711
that an existing element for that attribute is not present.
712
713
These functions will be used in the next commit.
714
715
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
716
717
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
718
---
719
 lib/ldb/common/ldb_msg.c | 165 ++++++++++++++++++++++++++++++++++++++-
720
 lib/ldb/include/ldb.h    |  24 ++++++
721
 2 files changed, 185 insertions(+), 4 deletions(-)
722
723
diff --git lib/ldb/common/ldb_msg.c lib/ldb/common/ldb_msg.c
724
index 44d3b29e9a7..9cd7998e21c 100644
725
--- lib/ldb/common/ldb_msg.c
726
+++ lib/ldb/common/ldb_msg.c
727
@@ -509,12 +509,15 @@ int ldb_msg_add_steal_value(struct ldb_message *msg,
728
 
729
 
730
 /*
731
-  add a string element to a message
732
+  add a string element to a message, specifying flags
733
 */
734
-int ldb_msg_add_string(struct ldb_message *msg,
735
-		       const char *attr_name, const char *str)
736
+int ldb_msg_add_string_flags(struct ldb_message *msg,
737
+			     const char *attr_name, const char *str,
738
+			     int flags)
739
 {
740
 	struct ldb_val val;
741
+	int ret;
742
+	struct ldb_message_element *el = NULL;
743
 
744
 	val.data = discard_const_p(uint8_t, str);
745
 	val.length = strlen(str);
746
@@ -524,7 +527,25 @@ int ldb_msg_add_string(struct ldb_message *msg,
747
 		return LDB_SUCCESS;
748
 	}
749
 
750
-	return ldb_msg_add_value(msg, attr_name, &val, NULL);
751
+	ret = ldb_msg_add_value(msg, attr_name, &val, &el);
752
+	if (ret != LDB_SUCCESS) {
753
+		return ret;
754
+	}
755
+
756
+	if (flags != 0) {
757
+		el->flags = flags;
758
+	}
759
+
760
+	return LDB_SUCCESS;
761
+}
762
+
763
+/*
764
+  add a string element to a message
765
+*/
766
+int ldb_msg_add_string(struct ldb_message *msg,
767
+		       const char *attr_name, const char *str)
768
+{
769
+	return ldb_msg_add_string_flags(msg, attr_name, str, 0);
770
 }
771
 
772
 /*
773
@@ -586,6 +607,142 @@ int ldb_msg_add_fmt(struct ldb_message *msg,
774
 	return ldb_msg_add_steal_value(msg, attr_name, &val);
775
 }
776
 
777
+static int ldb_msg_append_value_impl(struct ldb_message *msg,
778
+				     const char *attr_name,
779
+				     const struct ldb_val *val,
780
+				     int flags,
781
+				     struct ldb_message_element **return_el)
782
+{
783
+	struct ldb_message_element *el = NULL;
784
+	int ret;
785
+
786
+	ret = ldb_msg_add_empty(msg, attr_name, flags, &el);
787
+	if (ret != LDB_SUCCESS) {
788
+		return ret;
789
+	}
790
+
791
+	ret = ldb_msg_element_add_value(msg->elements, el, val);
792
+	if (ret != LDB_SUCCESS) {
793
+		return ret;
794
+	}
795
+
796
+	if (return_el != NULL) {
797
+		*return_el = el;
798
+	}
799
+
800
+	return LDB_SUCCESS;
801
+}
802
+
803
+/*
804
+  append a value to a message
805
+*/
806
+int ldb_msg_append_value(struct ldb_message *msg,
807
+			 const char *attr_name,
808
+			 const struct ldb_val *val,
809
+			 int flags)
810
+{
811
+	return ldb_msg_append_value_impl(msg, attr_name, val, flags, NULL);
812
+}
813
+
814
+/*
815
+  append a value to a message, stealing it into the 'right' place
816
+*/
817
+int ldb_msg_append_steal_value(struct ldb_message *msg,
818
+			       const char *attr_name,
819
+			       struct ldb_val *val,
820
+			       int flags)
821
+{
822
+	int ret;
823
+	struct ldb_message_element *el = NULL;
824
+
825
+	ret = ldb_msg_append_value_impl(msg, attr_name, val, flags, &el);
826
+	if (ret == LDB_SUCCESS) {
827
+		talloc_steal(el->values, val->data);
828
+	}
829
+	return ret;
830
+}
831
+
832
+/*
833
+  append a string element to a message, stealing it into the 'right' place
834
+*/
835
+int ldb_msg_append_steal_string(struct ldb_message *msg,
836
+				const char *attr_name, char *str,
837
+				int flags)
838
+{
839
+	struct ldb_val val;
840
+
841
+	val.data = (uint8_t *)str;
842
+	val.length = strlen(str);
843
+
844
+	if (val.length == 0) {
845
+		/* allow empty strings as non-existent attributes */
846
+		return LDB_SUCCESS;
847
+	}
848
+
849
+	return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
850
+}
851
+
852
+/*
853
+  append a string element to a message
854
+*/
855
+int ldb_msg_append_string(struct ldb_message *msg,
856
+			  const char *attr_name, const char *str, int flags)
857
+{
858
+	struct ldb_val val;
859
+
860
+	val.data = discard_const_p(uint8_t, str);
861
+	val.length = strlen(str);
862
+
863
+	if (val.length == 0) {
864
+		/* allow empty strings as non-existent attributes */
865
+		return LDB_SUCCESS;
866
+	}
867
+
868
+	return ldb_msg_append_value(msg, attr_name, &val, flags);
869
+}
870
+
871
+/*
872
+  append a DN element to a message
873
+  WARNING: this uses the linearized string from the dn, and does not
874
+  copy the string.
875
+*/
876
+int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
877
+				 struct ldb_dn *dn, int flags)
878
+{
879
+	char *str = ldb_dn_alloc_linearized(msg, dn);
880
+
881
+	if (str == NULL) {
882
+		/* we don't want to have unknown DNs added */
883
+		return LDB_ERR_OPERATIONS_ERROR;
884
+	}
885
+
886
+	return ldb_msg_append_steal_string(msg, attr_name, str, flags);
887
+}
888
+
889
+/*
890
+  append a printf formatted element to a message
891
+*/
892
+int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
893
+		       const char *attr_name, const char *fmt, ...)
894
+{
895
+	struct ldb_val val;
896
+	va_list ap;
897
+	char *str = NULL;
898
+
899
+	va_start(ap, fmt);
900
+	str = talloc_vasprintf(msg, fmt, ap);
901
+	va_end(ap);
902
+
903
+	if (str == NULL) {
904
+		return LDB_ERR_OPERATIONS_ERROR;
905
+	}
906
+
907
+	val.data   = (uint8_t *)str;
908
+	val.length = strlen(str);
909
+
910
+	return ldb_msg_append_steal_value(msg, attr_name, &val, flags);
911
+}
912
+
913
 /*
914
   compare two ldb_message_element structures
915
   assumes case sensitive comparison
916
diff --git lib/ldb/include/ldb.h lib/ldb/include/ldb.h
917
index 129beefeaf5..63d8aedd672 100644
918
--- lib/ldb/include/ldb.h
919
+++ lib/ldb/include/ldb.h
920
@@ -2002,12 +2002,36 @@ int ldb_msg_add_steal_value(struct ldb_message *msg,
921
 		      struct ldb_val *val);
922
 int ldb_msg_add_steal_string(struct ldb_message *msg,
923
 			     const char *attr_name, char *str);
924
+int ldb_msg_add_string_flags(struct ldb_message *msg,
925
+			     const char *attr_name, const char *str,
926
+			     int flags);
927
 int ldb_msg_add_string(struct ldb_message *msg,
928
 		       const char *attr_name, const char *str);
929
 int ldb_msg_add_linearized_dn(struct ldb_message *msg, const char *attr_name,
930
 			      struct ldb_dn *dn);
931
 int ldb_msg_add_fmt(struct ldb_message *msg,
932
 		    const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(3,4);
933
+/**
934
+   append a element to a ldb_message
935
+*/
936
+int ldb_msg_append_value(struct ldb_message *msg,
937
+			 const char *attr_name,
938
+			 const struct ldb_val *val,
939
+			 int flags);
940
+int ldb_msg_append_steal_value(struct ldb_message *msg,
941
+			       const char *attr_name,
942
+			       struct ldb_val *val,
943
+			       int flags);
944
+int ldb_msg_append_steal_string(struct ldb_message *msg,
945
+				const char *attr_name, char *str,
946
+				int flags);
947
+int ldb_msg_append_string(struct ldb_message *msg,
948
+			  const char *attr_name, const char *str,
949
+			  int flags);
950
+int ldb_msg_append_linearized_dn(struct ldb_message *msg, const char *attr_name,
951
+				 struct ldb_dn *dn, int flags);
952
+int ldb_msg_append_fmt(struct ldb_message *msg, int flags,
953
+		       const char *attr_name, const char *fmt, ...) PRINTF_ATTRIBUTE(4,5);
954
 
955
 /**
956
    compare two message elements - return 0 on match
957
-- 
958
2.25.1
959
960
961
From f419753d1c7a373fb32ffe20930a6e084e44b44d Mon Sep 17 00:00:00 2001
962
From: Joseph Sutton <josephsutton@catalyst.net.nz>
963
Date: Mon, 21 Feb 2022 16:27:37 +1300
964
Subject: [PATCH 13/99] CVE-2022-32746 ldb: Make use of functions for appending
965
 to an ldb_message
966
967
This aims to minimise usage of the error-prone pattern of searching for
968
a just-added message element in order to make modifications to it (and
969
potentially finding the wrong element).
970
971
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
972
973
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
974
---
975
 lib/ldb/ldb_map/ldb_map.c                     |   5 +-
976
 lib/ldb/ldb_map/ldb_map_inbound.c             |   9 +-
977
 lib/ldb/modules/rdn_name.c                    |  22 +---
978
 source3/passdb/pdb_samba_dsdb.c               |  14 +--
979
 source4/dns_server/dnsserver_common.c         |  12 +-
980
 source4/dsdb/common/util.c                    | 114 ++++++++++++++----
981
 source4/dsdb/samdb/ldb_modules/descriptor.c   |  10 +-
982
 source4/dsdb/samdb/ldb_modules/objectguid.c   |  20 +--
983
 .../dsdb/samdb/ldb_modules/partition_init.c   |  14 +--
984
 .../dsdb/samdb/ldb_modules/repl_meta_data.c   |  24 +---
985
 source4/dsdb/samdb/ldb_modules/samldb.c       |  78 +++++-------
986
 .../samdb/ldb_modules/tombstone_reanimate.c   |  12 +-
987
 source4/nbt_server/wins/winsdb.c              |  13 +-
988
 source4/rpc_server/lsa/dcesrv_lsa.c           |  55 +++------
989
 source4/winbind/idmap.c                       |  10 +-
990
 15 files changed, 183 insertions(+), 229 deletions(-)
991
992
diff --git lib/ldb/ldb_map/ldb_map.c lib/ldb/ldb_map/ldb_map.c
993
index b453dff80d2..c7b0c228631 100644
994
--- lib/ldb/ldb_map/ldb_map.c
995
+++ lib/ldb/ldb_map/ldb_map.c
996
@@ -946,10 +946,7 @@ struct ldb_request *map_build_fixup_req(struct map_context *ac,
997
 	if ( ! dn || ! ldb_dn_validate(msg->dn)) {
998
 		goto failed;
999
 	}
1000
-	if (ldb_msg_add_empty(msg, IS_MAPPED, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1001
-		goto failed;
1002
-	}
1003
-	if (ldb_msg_add_string(msg, IS_MAPPED, dn) != 0) {
1004
+	if (ldb_msg_append_string(msg, IS_MAPPED, dn, LDB_FLAG_MOD_REPLACE) != 0) {
1005
 		goto failed;
1006
 	}
1007
 
1008
diff --git lib/ldb/ldb_map/ldb_map_inbound.c lib/ldb/ldb_map/ldb_map_inbound.c
1009
index 324295737da..50b9427c26c 100644
1010
--- lib/ldb/ldb_map/ldb_map_inbound.c
1011
+++ lib/ldb/ldb_map/ldb_map_inbound.c
1012
@@ -569,12 +569,9 @@ static int map_modify_do_local(struct map_context *ac)
1013
 		/* No local record present, add it instead */
1014
 		/* Add local 'IS_MAPPED' */
1015
 		/* TODO: use GUIDs here instead */
1016
-		if (ldb_msg_add_empty(ac->local_msg, IS_MAPPED,
1017
-					LDB_FLAG_MOD_ADD, NULL) != 0) {
1018
-			return LDB_ERR_OPERATIONS_ERROR;
1019
-		}
1020
-		ret = ldb_msg_add_linearized_dn(ac->local_msg, IS_MAPPED,
1021
-						ac->remote_req->op.mod.message->dn);
1022
+		ret = ldb_msg_append_linearized_dn(ac->local_msg, IS_MAPPED,
1023
+						   ac->remote_req->op.mod.message->dn,
1024
+						   LDB_FLAG_MOD_ADD);
1025
 		if (ret != 0) {
1026
 			return LDB_ERR_OPERATIONS_ERROR;
1027
 		}
1028
diff --git lib/ldb/modules/rdn_name.c lib/ldb/modules/rdn_name.c
1029
index 25cffe07591..3cb62bf567b 100644
1030
--- lib/ldb/modules/rdn_name.c
1031
+++ lib/ldb/modules/rdn_name.c
1032
@@ -308,16 +308,10 @@ static int rdn_rename_callback(struct ldb_request *req, struct ldb_reply *ares)
1033
 	}
1034
 	rdn_val = ldb_val_dup(msg, rdn_val_p);
1035
 
1036
-	if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1037
+	if (ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) {
1038
 		goto error;
1039
 	}
1040
-	if (ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL) != 0) {
1041
-		goto error;
1042
-	}
1043
-	if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1044
-		goto error;
1045
-	}
1046
-	if (ldb_msg_add_value(msg, "name", &rdn_val, NULL) != 0) {
1047
+	if (ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_REPLACE) != 0) {
1048
 		goto error;
1049
 	}
1050
 
1051
@@ -466,11 +460,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
1052
 		if (ret != 0) {
1053
 			return ldb_module_oom(module);
1054
 		}
1055
-		ret = ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_ADD, NULL);
1056
-		if (ret != 0) {
1057
-			return ldb_module_oom(module);
1058
-		}
1059
-		ret = ldb_msg_add_value(msg, rdn_name, &rdn_val, NULL);
1060
+		ret = ldb_msg_append_value(msg, rdn_name, &rdn_val, LDB_FLAG_MOD_ADD);
1061
 		if (ret != 0) {
1062
 			return ldb_module_oom(module);
1063
 		}
1064
@@ -479,11 +469,7 @@ static int rdn_name_modify(struct ldb_module *module, struct ldb_request *req)
1065
 		if (ret != 0) {
1066
 			return ldb_module_oom(module);
1067
 		}
1068
-		ret = ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_ADD, NULL);
1069
-		if (ret != 0) {
1070
-			return ldb_module_oom(module);
1071
-		}
1072
-		ret = ldb_msg_add_value(msg, "name", &rdn_val, NULL);
1073
+		ret = ldb_msg_append_value(msg, "name", &rdn_val, LDB_FLAG_MOD_ADD);
1074
 		if (ret != 0) {
1075
 			return ldb_module_oom(module);
1076
 		}
1077
diff --git source3/passdb/pdb_samba_dsdb.c source3/passdb/pdb_samba_dsdb.c
1078
index 93e8f5bebe6..b2063825c04 100644
1079
--- source3/passdb/pdb_samba_dsdb.c
1080
+++ source3/passdb/pdb_samba_dsdb.c
1081
@@ -2855,18 +2855,10 @@ static bool pdb_samba_dsdb_set_trusteddom_pw(struct pdb_methods *m,
1082
 	}
1083
 
1084
 	msg->num_elements = 0;
1085
-	ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1086
-				LDB_FLAG_MOD_REPLACE, NULL);
1087
+	ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
1088
+				   &new_val, LDB_FLAG_MOD_REPLACE);
1089
 	if (ret != LDB_SUCCESS) {
1090
-		DEBUG(0, ("ldb_msg_add_empty() failed\n"));
1091
-		TALLOC_FREE(tmp_ctx);
1092
-		ldb_transaction_cancel(state->ldb);
1093
-		return false;
1094
-	}
1095
-	ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1096
-				&new_val, NULL);
1097
-	if (ret != LDB_SUCCESS) {
1098
-		DEBUG(0, ("ldb_msg_add_value() failed\n"));
1099
+		DEBUG(0, ("ldb_msg_append_value() failed\n"));
1100
 		TALLOC_FREE(tmp_ctx);
1101
 		ldb_transaction_cancel(state->ldb);
1102
 		return false;
1103
diff --git source4/dns_server/dnsserver_common.c source4/dns_server/dnsserver_common.c
1104
index bcb0d087faf..cb9a082ebf6 100644
1105
--- source4/dns_server/dnsserver_common.c
1106
+++ source4/dns_server/dnsserver_common.c
1107
@@ -1092,15 +1092,9 @@ WERROR dns_common_replace(struct ldb_context *samdb,
1108
 	}
1109
 
1110
 	if (was_tombstoned || become_tombstoned) {
1111
-		ret = ldb_msg_add_empty(msg, "dNSTombstoned",
1112
-					LDB_FLAG_MOD_REPLACE, NULL);
1113
-		if (ret != LDB_SUCCESS) {
1114
-			werr = DNS_ERR(SERVER_FAILURE);
1115
-			goto exit;
1116
-		}
1117
-
1118
-		ret = ldb_msg_add_fmt(msg, "dNSTombstoned", "%s",
1119
-				      become_tombstoned ? "TRUE" : "FALSE");
1120
+		ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE,
1121
+					 "dNSTombstoned", "%s",
1122
+					 become_tombstoned ? "TRUE" : "FALSE");
1123
 		if (ret != LDB_SUCCESS) {
1124
 			werr = DNS_ERR(SERVER_FAILURE);
1125
 			goto exit;
1126
diff --git source4/dsdb/common/util.c source4/dsdb/common/util.c
1127
index 577b2a33873..10d6ea8883b 100644
1128
--- source4/dsdb/common/util.c
1129
+++ source4/dsdb/common/util.c
1130
@@ -924,6 +924,16 @@ int samdb_msg_add_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct l
1131
 	return ldb_msg_add_string(msg, attr_name, s);
1132
 }
1133
 
1134
+int samdb_msg_add_int_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1135
+			    const char *attr_name, int v, int flags)
1136
+{
1137
+	const char *s = talloc_asprintf(mem_ctx, "%d", v);
1138
+	if (s == NULL) {
1139
+		return ldb_oom(sam_ldb);
1140
+	}
1141
+	return ldb_msg_add_string_flags(msg, attr_name, s, flags);
1142
+}
1143
+
1144
 /*
1145
  * Add an unsigned int element to a message
1146
  *
1147
@@ -942,6 +952,12 @@ int samdb_msg_add_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct
1148
 	return samdb_msg_add_int(sam_ldb, mem_ctx, msg, attr_name, (int)v);
1149
 }
1150
 
1151
+int samdb_msg_add_uint_flags(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1152
+			     const char *attr_name, unsigned int v, int flags)
1153
+{
1154
+	return samdb_msg_add_int_flags(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags);
1155
+}
1156
+
1157
 /*
1158
   add a (signed) int64_t element to a message
1159
 */
1160
@@ -973,6 +989,68 @@ int samdb_msg_add_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struc
1161
 	return samdb_msg_add_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v);
1162
 }
1163
 
1164
+/*
1165
+  append a int element to a message
1166
+*/
1167
+int samdb_msg_append_int(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1168
+		      const char *attr_name, int v, int flags)
1169
+{
1170
+	const char *s = talloc_asprintf(mem_ctx, "%d", v);
1171
+	if (s == NULL) {
1172
+		return ldb_oom(sam_ldb);
1173
+	}
1174
+	return ldb_msg_append_string(msg, attr_name, s, flags);
1175
+}
1176
+
1177
+/*
1178
+ * Append an unsigned int element to a message
1179
+ *
1180
+ * The issue here is that we have not yet first cast to int32_t explicitly,
1181
+ * before we cast to an signed int to printf() into the %d or cast to a
1182
+ * int64_t before we then cast to a long long to printf into a %lld.
1183
+ *
1184
+ * There are *no* unsigned integers in Active Directory LDAP, even the RID
1185
+ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1186
+ * (See the schema, and the syntax definitions in schema_syntax.c).
1187
+ *
1188
+ */
1189
+int samdb_msg_append_uint(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1190
+			  const char *attr_name, unsigned int v, int flags)
1191
+{
1192
+	return samdb_msg_append_int(sam_ldb, mem_ctx, msg, attr_name, (int)v, flags);
1193
+}
1194
+
1195
+/*
1196
+  append a (signed) int64_t element to a message
1197
+*/
1198
+int samdb_msg_append_int64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1199
+			   const char *attr_name, int64_t v, int flags)
1200
+{
1201
+	const char *s = talloc_asprintf(mem_ctx, "%lld", (long long)v);
1202
+	if (s == NULL) {
1203
+		return ldb_oom(sam_ldb);
1204
+	}
1205
+	return ldb_msg_append_string(msg, attr_name, s, flags);
1206
+}
1207
+
1208
+/*
1209
+ * Append an unsigned int64_t (uint64_t) element to a message
1210
+ *
1211
+ * The issue here is that we have not yet first cast to int32_t explicitly,
1212
+ * before we cast to an signed int to printf() into the %d or cast to a
1213
+ * int64_t before we then cast to a long long to printf into a %lld.
1214
+ *
1215
+ * There are *no* unsigned integers in Active Directory LDAP, even the RID
1216
+ * allocations and ms-DS-Secondary-KrbTgt-Number are *signed* quantities.
1217
+ * (See the schema, and the syntax definitions in schema_syntax.c).
1218
+ *
1219
+ */
1220
+int samdb_msg_append_uint64(struct ldb_context *sam_ldb, TALLOC_CTX *mem_ctx, struct ldb_message *msg,
1221
+			    const char *attr_name, uint64_t v, int flags)
1222
+{
1223
+	return samdb_msg_append_int64(sam_ldb, mem_ctx, msg, attr_name, (int64_t)v, flags);
1224
+}
1225
+
1226
 /*
1227
   add a samr_Password element to a message
1228
 */
1229
@@ -2814,15 +2892,8 @@ NTSTATUS samdb_set_password_sid(struct ldb_context *ldb, TALLOC_CTX *mem_ctx,
1230
 		tdo_msg->num_elements = 0;
1231
 		TALLOC_FREE(tdo_msg->elements);
1232
 
1233
-		ret = ldb_msg_add_empty(tdo_msg, "trustAuthIncoming",
1234
-					LDB_FLAG_MOD_REPLACE, NULL);
1235
-		if (ret != LDB_SUCCESS) {
1236
-			ldb_transaction_cancel(ldb);
1237
-			TALLOC_FREE(frame);
1238
-			return NT_STATUS_NO_MEMORY;
1239
-		}
1240
-		ret = ldb_msg_add_value(tdo_msg, "trustAuthIncoming",
1241
-					&new_val, NULL);
1242
+		ret = ldb_msg_append_value(tdo_msg, "trustAuthIncoming",
1243
+					   &new_val, LDB_FLAG_MOD_REPLACE);
1244
 		if (ret != LDB_SUCCESS) {
1245
 			ldb_transaction_cancel(ldb);
1246
 			TALLOC_FREE(frame);
1247
@@ -3187,6 +3258,7 @@ int dsdb_find_guid_by_dn(struct ldb_context *ldb,
1248
 /*
1249
  adds the given GUID to the given ldb_message. This value is added
1250
  for the given attr_name (may be either "objectGUID" or "parentGUID").
1251
+ This function is used in processing 'add' requests.
1252
  */
1253
 int dsdb_msg_add_guid(struct ldb_message *msg,
1254
 		struct GUID *guid,
1255
@@ -5656,7 +5728,8 @@ int dsdb_user_obj_set_defaults(struct ldb_context *ldb,
1256
 }
1257
 
1258
 /**
1259
- * Sets 'sAMAccountType on user object based on userAccountControl
1260
+ * Sets 'sAMAccountType on user object based on userAccountControl.
1261
+ * This function is used in processing both 'add' and 'modify' requests.
1262
  * @param ldb Current ldb_context
1263
  * @param usr_obj ldb_message representing User object
1264
  * @param user_account_control Value for userAccountControl flags
1265
@@ -5668,21 +5741,19 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message *
1266
 {
1267
 	int ret;
1268
 	uint32_t account_type;
1269
-	struct ldb_message_element *el;
1270
 
1271
 	account_type = ds_uf2atype(user_account_control);
1272
 	if (account_type == 0) {
1273
 		ldb_set_errstring(ldb, "dsdb: Unrecognized account type!");
1274
 		return LDB_ERR_UNWILLING_TO_PERFORM;
1275
 	}
1276
-	ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj,
1277
-				 "sAMAccountType",
1278
-				 account_type);
1279
+	ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj,
1280
+				       "sAMAccountType",
1281
+				       account_type,
1282
+				       LDB_FLAG_MOD_REPLACE);
1283
 	if (ret != LDB_SUCCESS) {
1284
 		return ret;
1285
 	}
1286
-	el = ldb_msg_find_element(usr_obj, "sAMAccountType");
1287
-	el->flags = LDB_FLAG_MOD_REPLACE;
1288
 
1289
 	if (account_type_p) {
1290
 		*account_type_p = account_type;
1291
@@ -5692,7 +5763,8 @@ int dsdb_user_obj_set_account_type(struct ldb_context *ldb, struct ldb_message *
1292
 }
1293
 
1294
 /**
1295
- * Determine and set primaryGroupID based on userAccountControl value
1296
+ * Determine and set primaryGroupID based on userAccountControl value.
1297
+ * This function is used in processing both 'add' and 'modify' requests.
1298
  * @param ldb Current ldb_context
1299
  * @param usr_obj ldb_message representing User object
1300
  * @param user_account_control Value for userAccountControl flags
1301
@@ -5704,17 +5776,15 @@ int dsdb_user_obj_set_primary_group_id(struct ldb_context *ldb, struct ldb_messa
1302
 {
1303
 	int ret;
1304
 	uint32_t rid;
1305
-	struct ldb_message_element *el;
1306
 
1307
 	rid = ds_uf2prim_group_rid(user_account_control);
1308
 
1309
-	ret = samdb_msg_add_uint(ldb, usr_obj, usr_obj,
1310
-				 "primaryGroupID", rid);
1311
+	ret = samdb_msg_add_uint_flags(ldb, usr_obj, usr_obj,
1312
+				       "primaryGroupID", rid,
1313
+				       LDB_FLAG_MOD_REPLACE);
1314
 	if (ret != LDB_SUCCESS) {
1315
 		return ret;
1316
 	}
1317
-	el = ldb_msg_find_element(usr_obj, "primaryGroupID");
1318
-	el->flags = LDB_FLAG_MOD_REPLACE;
1319
 
1320
 	if (group_rid_p) {
1321
 		*group_rid_p = rid;
1322
diff --git source4/dsdb/samdb/ldb_modules/descriptor.c source4/dsdb/samdb/ldb_modules/descriptor.c
1323
index daa08c2ebc7..4b01961dcb0 100644
1324
--- source4/dsdb/samdb/ldb_modules/descriptor.c
1325
+++ source4/dsdb/samdb/ldb_modules/descriptor.c
1326
@@ -857,14 +857,8 @@ static int descriptor_modify(struct ldb_module *module, struct ldb_request *req)
1327
 			return ldb_module_done(req, NULL, NULL, LDB_SUCCESS);
1328
 		}
1329
 
1330
-		ret = ldb_msg_add_empty(msg, "nTSecurityDescriptor",
1331
-					LDB_FLAG_MOD_REPLACE,
1332
-					&sd_element);
1333
-		if (ret != LDB_SUCCESS) {
1334
-			return ldb_oom(ldb);
1335
-		}
1336
-		ret = ldb_msg_add_value(msg, "nTSecurityDescriptor",
1337
-					sd, NULL);
1338
+		ret = ldb_msg_append_value(msg, "nTSecurityDescriptor",
1339
+					   sd, LDB_FLAG_MOD_REPLACE);
1340
 		if (ret != LDB_SUCCESS) {
1341
 			return ldb_oom(ldb);
1342
 		}
1343
diff --git source4/dsdb/samdb/ldb_modules/objectguid.c source4/dsdb/samdb/ldb_modules/objectguid.c
1344
index bc3260cf0d8..0fe995a5763 100644
1345
--- source4/dsdb/samdb/ldb_modules/objectguid.c
1346
+++ source4/dsdb/samdb/ldb_modules/objectguid.c
1347
@@ -41,7 +41,6 @@
1348
 */
1349
 static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
1350
 {
1351
-	struct ldb_message_element *el;
1352
 	char *s;
1353
 	int ret;
1354
 
1355
@@ -54,16 +53,13 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
1356
 		return LDB_ERR_OPERATIONS_ERROR;
1357
 	}
1358
 
1359
-	ret = ldb_msg_add_string(msg, attr, s);
1360
+	/* always set as replace. This works because on add ops, the flag
1361
+	   is ignored */
1362
+	ret = ldb_msg_append_string(msg, attr, s, LDB_FLAG_MOD_REPLACE);
1363
 	if (ret != LDB_SUCCESS) {
1364
 		return ret;
1365
 	}
1366
 
1367
-	el = ldb_msg_find_element(msg, attr);
1368
-	/* always set as replace. This works because on add ops, the flag
1369
-	   is ignored */
1370
-	el->flags = LDB_FLAG_MOD_REPLACE;
1371
-
1372
 	return LDB_SUCCESS;
1373
 }
1374
 
1375
@@ -73,23 +69,19 @@ static int add_time_element(struct ldb_message *msg, const char *attr, time_t t)
1376
 static int add_uint64_element(struct ldb_context *ldb, struct ldb_message *msg,
1377
 			      const char *attr, uint64_t v)
1378
 {
1379
-	struct ldb_message_element *el;
1380
 	int ret;
1381
 
1382
 	if (ldb_msg_find_element(msg, attr) != NULL) {
1383
 		return LDB_SUCCESS;
1384
 	}
1385
 
1386
-	ret = samdb_msg_add_uint64(ldb, msg, msg, attr, v);
1387
+	/* always set as replace. This works because on add ops, the flag
1388
+	   is ignored */
1389
+	ret = samdb_msg_append_uint64(ldb, msg, msg, attr, v, LDB_FLAG_MOD_REPLACE);
1390
 	if (ret != LDB_SUCCESS) {
1391
 		return ret;
1392
 	}
1393
 
1394
-	el = ldb_msg_find_element(msg, attr);
1395
-	/* always set as replace. This works because on add ops, the flag
1396
-	   is ignored */
1397
-	el->flags = LDB_FLAG_MOD_REPLACE;
1398
-
1399
 	return LDB_SUCCESS;
1400
 }
1401
 
1402
diff --git source4/dsdb/samdb/ldb_modules/partition_init.c source4/dsdb/samdb/ldb_modules/partition_init.c
1403
index 58c65ccedd0..484b5bffb27 100644
1404
--- source4/dsdb/samdb/ldb_modules/partition_init.c
1405
+++ source4/dsdb/samdb/ldb_modules/partition_init.c
1406
@@ -742,10 +742,6 @@ int partition_create(struct ldb_module *module, struct ldb_request *req)
1407
 		}
1408
 		
1409
 		mod_msg->dn = ldb_dn_new(mod_msg, ldb, DSDB_PARTITION_DN);
1410
-		ret = ldb_msg_add_empty(mod_msg, DSDB_PARTITION_ATTR, LDB_FLAG_MOD_ADD, NULL);
1411
-		if (ret != LDB_SUCCESS) {
1412
-			return ret;
1413
-		}
1414
 		
1415
 		casefold_dn = ldb_dn_get_casefold(dn);
1416
 		
1417
@@ -785,18 +781,16 @@ int partition_create(struct ldb_module *module, struct ldb_request *req)
1418
 		}
1419
 		partition_record = talloc_asprintf(mod_msg, "%s:%s", casefold_dn, filename);
1420
 
1421
-		ret = ldb_msg_add_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record);
1422
+		ret = ldb_msg_append_steal_string(mod_msg, DSDB_PARTITION_ATTR, partition_record,
1423
+						  LDB_FLAG_MOD_ADD);
1424
 		if (ret != LDB_SUCCESS) {
1425
 			return ret;
1426
 		}
1427
 
1428
 		if (ldb_request_get_control(req, DSDB_CONTROL_PARTIAL_REPLICA)) {
1429
 			/* this new partition is a partial replica */
1430
-			ret = ldb_msg_add_empty(mod_msg, "partialReplica", LDB_FLAG_MOD_ADD, NULL);
1431
-			if (ret != LDB_SUCCESS) {
1432
-				return ret;
1433
-			}
1434
-			ret = ldb_msg_add_fmt(mod_msg, "partialReplica", "%s", ldb_dn_get_linearized(dn));
1435
+			ret = ldb_msg_append_fmt(mod_msg, LDB_FLAG_MOD_ADD,
1436
+						 "partialReplica", "%s", ldb_dn_get_linearized(dn));
1437
 			if (ret != LDB_SUCCESS) {
1438
 				return ret;
1439
 			}
1440
diff --git source4/dsdb/samdb/ldb_modules/repl_meta_data.c source4/dsdb/samdb/ldb_modules/repl_meta_data.c
1441
index 29ffda75c87..eec1e639856 100644
1442
--- source4/dsdb/samdb/ldb_modules/repl_meta_data.c
1443
+++ source4/dsdb/samdb/ldb_modules/repl_meta_data.c
1444
@@ -3888,22 +3888,12 @@ static int replmd_rename_callback(struct ldb_request *req, struct ldb_reply *are
1445
 				       ldb_operr(ldb));
1446
 	}
1447
 
1448
-	if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1449
+	if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) {
1450
 		talloc_free(ares);
1451
 		return ldb_module_done(ac->req, NULL, NULL,
1452
 				       ldb_oom(ldb));
1453
 	}
1454
-	if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
1455
-		talloc_free(ares);
1456
-		return ldb_module_done(ac->req, NULL, NULL,
1457
-				       ldb_oom(ldb));
1458
-	}
1459
-	if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1460
-		talloc_free(ares);
1461
-		return ldb_module_done(ac->req, NULL, NULL,
1462
-				       ldb_oom(ldb));
1463
-	}
1464
-	if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
1465
+	if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) {
1466
 		talloc_free(ares);
1467
 		return ldb_module_done(ac->req, NULL, NULL,
1468
 				       ldb_oom(ldb));
1469
@@ -5161,16 +5151,10 @@ static int replmd_name_modify(struct replmd_replicated_request *ar,
1470
 		goto failed;
1471
 	}
1472
 
1473
-	if (ldb_msg_add_empty(msg, rdn_name, LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1474
-		goto failed;
1475
-	}
1476
-	if (ldb_msg_add_value(msg, rdn_name, rdn_val, NULL) != 0) {
1477
-		goto failed;
1478
-	}
1479
-	if (ldb_msg_add_empty(msg, "name", LDB_FLAG_MOD_REPLACE, NULL) != 0) {
1480
+	if (ldb_msg_append_value(msg, rdn_name, rdn_val, LDB_FLAG_MOD_REPLACE) != 0) {
1481
 		goto failed;
1482
 	}
1483
-	if (ldb_msg_add_value(msg, "name", rdn_val, NULL) != 0) {
1484
+	if (ldb_msg_append_value(msg, "name", rdn_val, LDB_FLAG_MOD_REPLACE) != 0) {
1485
 		goto failed;
1486
 	}
1487
 
1488
diff --git source4/dsdb/samdb/ldb_modules/samldb.c source4/dsdb/samdb/ldb_modules/samldb.c
1489
index 5fb9c195c9a..107e643e492 100644
1490
--- source4/dsdb/samdb/ldb_modules/samldb.c
1491
+++ source4/dsdb/samdb/ldb_modules/samldb.c
1492
@@ -1103,14 +1103,11 @@ static int samldb_rodc_add(struct samldb_ctx *ac)
1493
 	return LDB_ERR_OTHER;
1494
 
1495
 found:
1496
-	ret = ldb_msg_add_empty(ac->msg, "msDS-SecondaryKrbTgtNumber",
1497
-				LDB_FLAG_INTERNAL_DISABLE_VALIDATION, NULL);
1498
-	if (ret != LDB_SUCCESS) {
1499
-		return ldb_operr(ldb);
1500
-	}
1501
 
1502
-	ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1503
-				 "msDS-SecondaryKrbTgtNumber", krbtgt_number);
1504
+	ldb_msg_remove_attr(ac->msg, "msDS-SecondaryKrbTgtNumber");
1505
+	ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg,
1506
+				    "msDS-SecondaryKrbTgtNumber", krbtgt_number,
1507
+				    LDB_FLAG_INTERNAL_DISABLE_VALIDATION);
1508
 	if (ret != LDB_SUCCESS) {
1509
 		return ldb_operr(ldb);
1510
 	}
1511
@@ -1792,7 +1789,7 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
1512
 	struct ldb_context *ldb = ldb_module_get_ctx(ac->module);
1513
 	void *skip_allocate_sids = ldb_get_opaque(ldb,
1514
 						  "skip_allocate_sids");
1515
-	struct ldb_message_element *el, *el2;
1516
+	struct ldb_message_element *el;
1517
 	struct dom_sid *sid;
1518
 	int ret;
1519
 
1520
@@ -1926,23 +1923,17 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
1521
 		/* "isCriticalSystemObject" might be set */
1522
 		if (user_account_control &
1523
 		    (UF_SERVER_TRUST_ACCOUNT | UF_PARTIAL_SECRETS_ACCOUNT)) {
1524
-			ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1525
-						 "TRUE");
1526
+			ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject",
1527
+						       "TRUE", LDB_FLAG_MOD_REPLACE);
1528
 			if (ret != LDB_SUCCESS) {
1529
 				return ret;
1530
 			}
1531
-			el2 = ldb_msg_find_element(ac->msg,
1532
-						   "isCriticalSystemObject");
1533
-			el2->flags = LDB_FLAG_MOD_REPLACE;
1534
 		} else if (user_account_control & UF_WORKSTATION_TRUST_ACCOUNT) {
1535
-			ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1536
-						 "FALSE");
1537
+			ret = ldb_msg_add_string_flags(ac->msg, "isCriticalSystemObject",
1538
+						       "FALSE", LDB_FLAG_MOD_REPLACE);
1539
 			if (ret != LDB_SUCCESS) {
1540
 				return ret;
1541
 			}
1542
-			el2 = ldb_msg_find_element(ac->msg,
1543
-						   "isCriticalSystemObject");
1544
-			el2->flags = LDB_FLAG_MOD_REPLACE;
1545
 		}
1546
 
1547
 		/* Step 1.4: "userAccountControl" -> "primaryGroupID" mapping */
1548
@@ -2018,14 +2009,13 @@ static int samldb_objectclass_trigger(struct samldb_ctx *ac)
1549
 				ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1550
 				return LDB_ERR_UNWILLING_TO_PERFORM;
1551
 			}
1552
-			ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1553
-						 "sAMAccountType",
1554
-						 account_type);
1555
+			ret = samdb_msg_add_uint_flags(ldb, ac->msg, ac->msg,
1556
+						       "sAMAccountType",
1557
+						       account_type,
1558
+						       LDB_FLAG_MOD_REPLACE);
1559
 			if (ret != LDB_SUCCESS) {
1560
 				return ret;
1561
 			}
1562
-			el2 = ldb_msg_find_element(ac->msg, "sAMAccountType");
1563
-			el2->flags = LDB_FLAG_MOD_REPLACE;
1564
 		}
1565
 		break;
1566
 	}
1567
@@ -2945,26 +2935,23 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
1568
 	}
1569
 
1570
 	if (old_atype != new_atype) {
1571
-		ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1572
-					 "sAMAccountType", new_atype);
1573
+		ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg,
1574
+					    "sAMAccountType", new_atype,
1575
+					    LDB_FLAG_MOD_REPLACE);
1576
 		if (ret != LDB_SUCCESS) {
1577
 			return ret;
1578
 		}
1579
-		el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1580
-		el->flags = LDB_FLAG_MOD_REPLACE;
1581
 	}
1582
 
1583
 	/* As per MS-SAMR 3.1.1.8.10 these flags have not to be set */
1584
 	if ((clear_uac & UF_LOCKOUT) && (old_lockoutTime != 0)) {
1585
 		/* "lockoutTime" reset as per MS-SAMR 3.1.1.8.10 */
1586
 		ldb_msg_remove_attr(ac->msg, "lockoutTime");
1587
-		ret = samdb_msg_add_uint64(ldb, ac->msg, ac->msg, "lockoutTime",
1588
-					   (NTTIME)0);
1589
+		ret = samdb_msg_append_uint64(ldb, ac->msg, ac->msg, "lockoutTime",
1590
+					      (NTTIME)0, LDB_FLAG_MOD_REPLACE);
1591
 		if (ret != LDB_SUCCESS) {
1592
 			return ret;
1593
 		}
1594
-		el = ldb_msg_find_element(ac->msg, "lockoutTime");
1595
-		el->flags = LDB_FLAG_MOD_REPLACE;
1596
 	}
1597
 
1598
 	/*
1599
@@ -2975,14 +2962,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
1600
 	 * creating the attribute.
1601
 	 */
1602
 	if (old_is_critical != new_is_critical || old_atype != new_atype) {
1603
-		ret = ldb_msg_add_string(ac->msg, "isCriticalSystemObject",
1604
-					 new_is_critical ? "TRUE": "FALSE");
1605
+		ret = ldb_msg_append_string(ac->msg, "isCriticalSystemObject",
1606
+					    new_is_critical ? "TRUE": "FALSE",
1607
+					    LDB_FLAG_MOD_REPLACE);
1608
 		if (ret != LDB_SUCCESS) {
1609
 			return ret;
1610
 		}
1611
-		el = ldb_msg_find_element(ac->msg,
1612
-					   "isCriticalSystemObject");
1613
-		el->flags = LDB_FLAG_MOD_REPLACE;
1614
 	}
1615
 
1616
 	if (!ldb_msg_find_element(ac->msg, "primaryGroupID") &&
1617
@@ -2995,14 +2980,12 @@ static int samldb_user_account_control_change(struct samldb_ctx *ac)
1618
 			}
1619
 		}
1620
 
1621
-		ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg,
1622
-					 "primaryGroupID", new_pgrid);
1623
+		ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg,
1624
+					    "primaryGroupID", new_pgrid,
1625
+					    LDB_FLAG_MOD_REPLACE);
1626
 		if (ret != LDB_SUCCESS) {
1627
 			return ret;
1628
 		}
1629
-		el = ldb_msg_find_element(ac->msg,
1630
-					   "primaryGroupID");
1631
-		el->flags = LDB_FLAG_MOD_REPLACE;
1632
 	}
1633
 
1634
 	/* Propagate eventual "userAccountControl" attribute changes */
1635
@@ -3205,13 +3188,12 @@ static int samldb_lockout_time(struct samldb_ctx *ac)
1636
 
1637
 	/* lockoutTime == 0 resets badPwdCount */
1638
 	ldb_msg_remove_attr(ac->msg, "badPwdCount");
1639
-	ret = samdb_msg_add_int(ldb, ac->msg, ac->msg,
1640
-				"badPwdCount", 0);
1641
+	ret = samdb_msg_append_int(ldb, ac->msg, ac->msg,
1642
+				   "badPwdCount", 0,
1643
+				   LDB_FLAG_MOD_REPLACE);
1644
 	if (ret != LDB_SUCCESS) {
1645
 		return ret;
1646
 	}
1647
-	el = ldb_msg_find_element(ac->msg, "badPwdCount");
1648
-	el->flags = LDB_FLAG_MOD_REPLACE;
1649
 
1650
 	return LDB_SUCCESS;
1651
 }
1652
@@ -3309,13 +3291,11 @@ static int samldb_group_type_change(struct samldb_ctx *ac)
1653
 		ldb_set_errstring(ldb, "samldb: Unrecognized account type!");
1654
 		return LDB_ERR_UNWILLING_TO_PERFORM;
1655
 	}
1656
-	ret = samdb_msg_add_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
1657
-				 account_type);
1658
+	ret = samdb_msg_append_uint(ldb, ac->msg, ac->msg, "sAMAccountType",
1659
+				    account_type, LDB_FLAG_MOD_REPLACE);
1660
 	if (ret != LDB_SUCCESS) {
1661
 		return ret;
1662
 	}
1663
-	el = ldb_msg_find_element(ac->msg, "sAMAccountType");
1664
-	el->flags = LDB_FLAG_MOD_REPLACE;
1665
 
1666
 	return LDB_SUCCESS;
1667
 }
1668
diff --git source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c
1669
index 5f8911c66be..99c5955e9e7 100644
1670
--- source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c
1671
+++ source4/dsdb/samdb/ldb_modules/tombstone_reanimate.c
1672
@@ -294,14 +294,13 @@ static int tr_prepare_attributes(struct tr_context *ac)
1673
 			return ldb_error(ldb, LDB_ERR_UNWILLING_TO_PERFORM,
1674
 					 "reanimate: Unrecognized account type!");
1675
 		}
1676
-		ret = samdb_msg_add_uint(ldb, ac->mod_msg, ac->mod_msg,
1677
-					 "sAMAccountType", account_type);
1678
+		ret = samdb_msg_append_uint(ldb, ac->mod_msg, ac->mod_msg,
1679
+					    "sAMAccountType", account_type,
1680
+					    LDB_FLAG_MOD_REPLACE);
1681
 		if (ret != LDB_SUCCESS) {
1682
 			return ldb_error(ldb, LDB_ERR_OPERATIONS_ERROR,
1683
 					 "reanimate: Failed to add sAMAccountType to restored object.");
1684
 		}
1685
-		el = ldb_msg_find_element(ac->mod_msg, "sAMAccountType");
1686
-		el->flags = LDB_FLAG_MOD_REPLACE;
1687
 
1688
 		/* Default values set by Windows */
1689
 		ret = samdb_find_or_add_attribute(ldb, ac->mod_msg,
1690
@@ -324,12 +323,11 @@ static int tr_prepare_attributes(struct tr_context *ac)
1691
 			return ret;
1692
 		}
1693
 
1694
-		ret = ldb_msg_add_string(ac->mod_msg, "objectCategory", value);
1695
+		ret = ldb_msg_append_string(ac->mod_msg, "objectCategory", value,
1696
+					    LDB_FLAG_MOD_ADD);
1697
 		if (ret != LDB_SUCCESS) {
1698
 			return ret;
1699
 		}
1700
-		el = ldb_msg_find_element(ac->mod_msg, "objectCategory");
1701
-		el->flags = LDB_FLAG_MOD_ADD;
1702
 	}
1703
 
1704
 	return LDB_SUCCESS;
1705
diff --git source4/nbt_server/wins/winsdb.c source4/nbt_server/wins/winsdb.c
1706
index e4a7c2042ed..2a05e96bca4 100644
1707
--- source4/nbt_server/wins/winsdb.c
1708
+++ source4/nbt_server/wins/winsdb.c
1709
@@ -102,13 +102,11 @@ uint64_t winsdb_set_maxVersion(struct winsdb_handle *h, uint64_t newMaxVersion)
1710
 	msg->dn = dn;
1711
 
1712
 
1713
-	ret = ldb_msg_add_empty(msg, "objectClass", LDB_FLAG_MOD_REPLACE, NULL);
1714
+	ret = ldb_msg_append_string(msg, "objectClass", "winsMaxVersion",
1715
+				    LDB_FLAG_MOD_REPLACE);
1716
 	if (ret != LDB_SUCCESS) goto failed;
1717
-	ret = ldb_msg_add_string(msg, "objectClass", "winsMaxVersion");
1718
-	if (ret != LDB_SUCCESS) goto failed;
1719
-	ret = ldb_msg_add_empty(msg, "maxVersion", LDB_FLAG_MOD_REPLACE, NULL);
1720
-	if (ret != LDB_SUCCESS) goto failed;
1721
-	ret = ldb_msg_add_fmt(msg, "maxVersion", "%llu", (long long)newMaxVersion);
1722
+	ret = ldb_msg_append_fmt(msg, LDB_FLAG_MOD_REPLACE,
1723
+				 "maxVersion", "%llu", (long long)newMaxVersion);
1724
 	if (ret != LDB_SUCCESS) goto failed;
1725
 
1726
 	ret = ldb_modify(wins_db, msg);
1727
@@ -779,8 +777,7 @@ static struct ldb_message *winsdb_message(struct ldb_context *ldb,
1728
 		ret |= ldb_msg_add_winsdb_addr(msg, rec, "address", rec->addresses[i]);
1729
 	}
1730
 	if (rec->registered_by) {
1731
-		ret |= ldb_msg_add_empty(msg, "registeredBy", 0, NULL);
1732
-		ret |= ldb_msg_add_string(msg, "registeredBy", rec->registered_by);
1733
+		ret |= ldb_msg_append_string(msg, "registeredBy", rec->registered_by, 0);
1734
 	}
1735
 	if (ret != LDB_SUCCESS) goto failed;
1736
 	return msg;
1737
diff --git source4/rpc_server/lsa/dcesrv_lsa.c source4/rpc_server/lsa/dcesrv_lsa.c
1738
index 15b068aec62..a165ab2b9d6 100644
1739
--- source4/rpc_server/lsa/dcesrv_lsa.c
1740
+++ source4/rpc_server/lsa/dcesrv_lsa.c
1741
@@ -1778,12 +1778,7 @@ static NTSTATUS update_uint32_t_value(TALLOC_CTX *mem_ctx,
1742
 		goto done;
1743
 	}
1744
 
1745
-	ret = ldb_msg_add_empty(dest, attribute, flags, NULL);
1746
-	if (ret != LDB_SUCCESS) {
1747
-		return NT_STATUS_NO_MEMORY;
1748
-	}
1749
-
1750
-	ret = samdb_msg_add_uint(sam_ldb, dest, dest, attribute, value);
1751
+	ret = samdb_msg_append_uint(sam_ldb, dest, dest, attribute, value, flags);
1752
 	if (ret != LDB_SUCCESS) {
1753
 		return NT_STATUS_NO_MEMORY;
1754
 	}
1755
@@ -1874,13 +1869,7 @@ static NTSTATUS update_trust_user(TALLOC_CTX *mem_ctx,
1756
 			continue;
1757
 		}
1758
 
1759
-		ret = ldb_msg_add_empty(msg, attribute,
1760
-					LDB_FLAG_MOD_REPLACE, NULL);
1761
-		if (ret != LDB_SUCCESS) {
1762
-			return NT_STATUS_NO_MEMORY;
1763
-		}
1764
-
1765
-		ret = ldb_msg_add_value(msg, attribute, &v, NULL);
1766
+		ret = ldb_msg_append_value(msg, attribute, &v, LDB_FLAG_MOD_REPLACE);
1767
 		if (ret != LDB_SUCCESS) {
1768
 			return NT_STATUS_NO_MEMORY;
1769
 		}
1770
@@ -2166,28 +2155,30 @@ static NTSTATUS setInfoTrustedDomain_base(struct dcesrv_call_state *dce_call,
1771
 	}
1772
 
1773
 	if (add_incoming || del_incoming) {
1774
-		ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1775
-					LDB_FLAG_MOD_REPLACE, NULL);
1776
-		if (ret != LDB_SUCCESS) {
1777
-			return NT_STATUS_NO_MEMORY;
1778
-		}
1779
 		if (add_incoming) {
1780
-			ret = ldb_msg_add_value(msg, "trustAuthIncoming",
1781
-						&trustAuthIncoming, NULL);
1782
+			ret = ldb_msg_append_value(msg, "trustAuthIncoming",
1783
+						   &trustAuthIncoming, LDB_FLAG_MOD_REPLACE);
1784
+			if (ret != LDB_SUCCESS) {
1785
+				return NT_STATUS_NO_MEMORY;
1786
+			}
1787
+		} else {
1788
+			ret = ldb_msg_add_empty(msg, "trustAuthIncoming",
1789
+						LDB_FLAG_MOD_REPLACE, NULL);
1790
 			if (ret != LDB_SUCCESS) {
1791
 				return NT_STATUS_NO_MEMORY;
1792
 			}
1793
 		}
1794
 	}
1795
 	if (add_outgoing || del_outgoing) {
1796
-		ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1797
-					LDB_FLAG_MOD_REPLACE, NULL);
1798
-		if (ret != LDB_SUCCESS) {
1799
-			return NT_STATUS_NO_MEMORY;
1800
-		}
1801
 		if (add_outgoing) {
1802
-			ret = ldb_msg_add_value(msg, "trustAuthOutgoing",
1803
-						&trustAuthOutgoing, NULL);
1804
+			ret = ldb_msg_append_value(msg, "trustAuthOutgoing",
1805
+						   &trustAuthOutgoing, LDB_FLAG_MOD_REPLACE);
1806
+			if (ret != LDB_SUCCESS) {
1807
+				return NT_STATUS_NO_MEMORY;
1808
+			}
1809
+		} else {
1810
+			ret = ldb_msg_add_empty(msg, "trustAuthOutgoing",
1811
+						LDB_FLAG_MOD_REPLACE, NULL);
1812
 			if (ret != LDB_SUCCESS) {
1813
 				return NT_STATUS_NO_MEMORY;
1814
 			}
1815
@@ -4635,14 +4626,8 @@ static NTSTATUS dcesrv_lsa_lsaRSetForestTrustInformation(struct dcesrv_call_stat
1816
 		goto done;
1817
 	}
1818
 
1819
-	ret = ldb_msg_add_empty(msg, "msDS-TrustForestTrustInfo",
1820
-				LDB_FLAG_MOD_REPLACE, NULL);
1821
-	if (ret != LDB_SUCCESS) {
1822
-		status = NT_STATUS_NO_MEMORY;
1823
-		goto done;
1824
-	}
1825
-	ret = ldb_msg_add_value(msg, "msDS-TrustForestTrustInfo",
1826
-				&ft_blob, NULL);
1827
+	ret = ldb_msg_append_value(msg, "msDS-TrustForestTrustInfo",
1828
+				   &ft_blob, LDB_FLAG_MOD_REPLACE);
1829
 	if (ret != LDB_SUCCESS) {
1830
 		status = NT_STATUS_NO_MEMORY;
1831
 		goto done;
1832
diff --git source4/winbind/idmap.c source4/winbind/idmap.c
1833
index c4039be473a..c6375f8357a 100644
1834
--- source4/winbind/idmap.c
1835
+++ source4/winbind/idmap.c
1836
@@ -672,14 +672,8 @@ static NTSTATUS idmap_sid_to_xid(struct idmap_context *idmap_ctx,
1837
 		vals[1].data = (uint8_t *)hwm_string;
1838
 		vals[1].length = strlen(hwm_string);
1839
 	} else {
1840
-		ret = ldb_msg_add_empty(hwm_msg, "xidNumber", LDB_FLAG_MOD_ADD,
1841
-					NULL);
1842
-		if (ret != LDB_SUCCESS) {
1843
-			status = NT_STATUS_NONE_MAPPED;
1844
-			goto failed;
1845
-		}
1846
-
1847
-		ret = ldb_msg_add_string(hwm_msg, "xidNumber", hwm_string);
1848
+		ret = ldb_msg_append_string(hwm_msg, "xidNumber", hwm_string,
1849
+					    LDB_FLAG_MOD_ADD);
1850
 		if (ret != LDB_SUCCESS)
1851
 		{
1852
 			status = NT_STATUS_NONE_MAPPED;
1853
-- 
1854
2.25.1
1855
1856
1857
From 7270b68386692829f97d5c51c50108db395b263e Mon Sep 17 00:00:00 2001
1858
From: Andrew Bartlett <abartlet@samba.org>
1859
Date: Tue, 14 Jun 2022 15:43:26 +1200
1860
Subject: [PATCH 14/99] CVE-2022-32746 ldb: Release LDB 2.3.4
1861
1862
* CVE-2022-32746 Use-after-free occurring in database audit logging module (bug 15009)
1863
1864
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15009
1865
1866
Signed-off-by: Andrew Bartlett <abartlet@samba.org>
1867
---
1868
 lib/ldb/ABI/ldb-2.3.4.sigs        | 291 ++++++++++++++++++++++++++++++
1869
 lib/ldb/ABI/pyldb-util-2.3.4.sigs |   3 +
1870
 lib/ldb/wscript                   |   2 +-
1871
 3 files changed, 295 insertions(+), 1 deletion(-)
1872
 create mode 100644 lib/ldb/ABI/ldb-2.3.4.sigs
1873
 create mode 100644 lib/ldb/ABI/pyldb-util-2.3.4.sigs
1874
1875
diff --git lib/ldb/ABI/ldb-2.3.4.sigs lib/ldb/ABI/ldb-2.3.4.sigs
1876
new file mode 100644
1877
index 00000000000..40388d9e330
1878
--- /dev/null
1879
+++ lib/ldb/ABI/ldb-2.3.4.sigs
1880
@@ -0,0 +1,291 @@
1881
+ldb_add: int (struct ldb_context *, const struct ldb_message *)
1882
+ldb_any_comparison: int (struct ldb_context *, void *, ldb_attr_handler_t, const struct ldb_val *, const struct ldb_val *)
1883
+ldb_asprintf_errstring: void (struct ldb_context *, const char *, ...)
1884
+ldb_attr_casefold: char *(TALLOC_CTX *, const char *)
1885
+ldb_attr_dn: int (const char *)
1886
+ldb_attr_in_list: int (const char * const *, const char *)
1887
+ldb_attr_list_copy: const char **(TALLOC_CTX *, const char * const *)
1888
+ldb_attr_list_copy_add: const char **(TALLOC_CTX *, const char * const *, const char *)
1889
+ldb_base64_decode: int (char *)
1890
+ldb_base64_encode: char *(TALLOC_CTX *, const char *, int)
1891
+ldb_binary_decode: struct ldb_val (TALLOC_CTX *, const char *)
1892
+ldb_binary_encode: char *(TALLOC_CTX *, struct ldb_val)
1893
+ldb_binary_encode_string: char *(TALLOC_CTX *, const char *)
1894
+ldb_build_add_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1895
+ldb_build_del_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1896
+ldb_build_extended_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const char *, void *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1897
+ldb_build_mod_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1898
+ldb_build_rename_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, struct ldb_dn *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1899
+ldb_build_search_req: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, const char *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1900
+ldb_build_search_req_ex: int (struct ldb_request **, struct ldb_context *, TALLOC_CTX *, struct ldb_dn *, enum ldb_scope, struct ldb_parse_tree *, const char * const *, struct ldb_control **, void *, ldb_request_callback_t, struct ldb_request *)
1901
+ldb_casefold: char *(struct ldb_context *, TALLOC_CTX *, const char *, size_t)
1902
+ldb_casefold_default: char *(void *, TALLOC_CTX *, const char *, size_t)
1903
+ldb_check_critical_controls: int (struct ldb_control **)
1904
+ldb_comparison_binary: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
1905
+ldb_comparison_fold: int (struct ldb_context *, void *, const struct ldb_val *, const struct ldb_val *)
1906
+ldb_connect: int (struct ldb_context *, const char *, unsigned int, const char **)
1907
+ldb_control_to_string: char *(TALLOC_CTX *, const struct ldb_control *)
1908
+ldb_controls_except_specified: struct ldb_control **(struct ldb_control **, TALLOC_CTX *, struct ldb_control *)
1909
+ldb_debug: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
1910
+ldb_debug_add: void (struct ldb_context *, const char *, ...)
1911
+ldb_debug_end: void (struct ldb_context *, enum ldb_debug_level)
1912
+ldb_debug_set: void (struct ldb_context *, enum ldb_debug_level, const char *, ...)
1913
+ldb_delete: int (struct ldb_context *, struct ldb_dn *)
1914
+ldb_dn_add_base: bool (struct ldb_dn *, struct ldb_dn *)
1915
+ldb_dn_add_base_fmt: bool (struct ldb_dn *, const char *, ...)
1916
+ldb_dn_add_child: bool (struct ldb_dn *, struct ldb_dn *)
1917
+ldb_dn_add_child_fmt: bool (struct ldb_dn *, const char *, ...)
1918
+ldb_dn_add_child_val: bool (struct ldb_dn *, const char *, struct ldb_val)
1919
+ldb_dn_alloc_casefold: char *(TALLOC_CTX *, struct ldb_dn *)
1920
+ldb_dn_alloc_linearized: char *(TALLOC_CTX *, struct ldb_dn *)
1921
+ldb_dn_canonical_ex_string: char *(TALLOC_CTX *, struct ldb_dn *)
1922
+ldb_dn_canonical_string: char *(TALLOC_CTX *, struct ldb_dn *)
1923
+ldb_dn_check_local: bool (struct ldb_module *, struct ldb_dn *)
1924
+ldb_dn_check_special: bool (struct ldb_dn *, const char *)
1925
+ldb_dn_compare: int (struct ldb_dn *, struct ldb_dn *)
1926
+ldb_dn_compare_base: int (struct ldb_dn *, struct ldb_dn *)
1927
+ldb_dn_copy: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
1928
+ldb_dn_escape_value: char *(TALLOC_CTX *, struct ldb_val)
1929
+ldb_dn_extended_add_syntax: int (struct ldb_context *, unsigned int, const struct ldb_dn_extended_syntax *)
1930
+ldb_dn_extended_filter: void (struct ldb_dn *, const char * const *)
1931
+ldb_dn_extended_syntax_by_name: const struct ldb_dn_extended_syntax *(struct ldb_context *, const char *)
1932
+ldb_dn_from_ldb_val: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const struct ldb_val *)
1933
+ldb_dn_get_casefold: const char *(struct ldb_dn *)
1934
+ldb_dn_get_comp_num: int (struct ldb_dn *)
1935
+ldb_dn_get_component_name: const char *(struct ldb_dn *, unsigned int)
1936
+ldb_dn_get_component_val: const struct ldb_val *(struct ldb_dn *, unsigned int)
1937
+ldb_dn_get_extended_comp_num: int (struct ldb_dn *)
1938
+ldb_dn_get_extended_component: const struct ldb_val *(struct ldb_dn *, const char *)
1939
+ldb_dn_get_extended_linearized: char *(TALLOC_CTX *, struct ldb_dn *, int)
1940
+ldb_dn_get_ldb_context: struct ldb_context *(struct ldb_dn *)
1941
+ldb_dn_get_linearized: const char *(struct ldb_dn *)
1942
+ldb_dn_get_parent: struct ldb_dn *(TALLOC_CTX *, struct ldb_dn *)
1943
+ldb_dn_get_rdn_name: const char *(struct ldb_dn *)
1944
+ldb_dn_get_rdn_val: const struct ldb_val *(struct ldb_dn *)
1945
+ldb_dn_has_extended: bool (struct ldb_dn *)
1946
+ldb_dn_is_null: bool (struct ldb_dn *)
1947
+ldb_dn_is_special: bool (struct ldb_dn *)
1948
+ldb_dn_is_valid: bool (struct ldb_dn *)
1949
+ldb_dn_map_local: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
1950
+ldb_dn_map_rebase_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
1951
+ldb_dn_map_remote: struct ldb_dn *(struct ldb_module *, void *, struct ldb_dn *)
1952
+ldb_dn_minimise: bool (struct ldb_dn *)
1953
+ldb_dn_new: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *)
1954
+ldb_dn_new_fmt: struct ldb_dn *(TALLOC_CTX *, struct ldb_context *, const char *, ...)
1955
+ldb_dn_remove_base_components: bool (struct ldb_dn *, unsigned int)
1956
+ldb_dn_remove_child_components: bool (struct ldb_dn *, unsigned int)
1957
+ldb_dn_remove_extended_components: void (struct ldb_dn *)
1958
+ldb_dn_replace_components: bool (struct ldb_dn *, struct ldb_dn *)
1959
+ldb_dn_set_component: int (struct ldb_dn *, int, const char *, const struct ldb_val)
1960
+ldb_dn_set_extended_component: int (struct ldb_dn *, const char *, const struct ldb_val *)
1961
+ldb_dn_update_components: int (struct ldb_dn *, const struct ldb_dn *)
1962
+ldb_dn_validate: bool (struct ldb_dn *)
1963
+ldb_dump_results: void (struct ldb_context *, struct ldb_result *, FILE *)
1964
+ldb_error_at: int (struct ldb_context *, int, const char *, const char *, int)
1965
+ldb_errstring: const char *(struct ldb_context *)
1966
+ldb_extended: int (struct ldb_context *, const char *, void *, struct ldb_result **)
1967
+ldb_extended_default_callback: int (struct ldb_request *, struct ldb_reply *)
1968
+ldb_filter_attrs: int (struct ldb_context *, const struct ldb_message *, const char * const *, struct ldb_message *)
1969
+ldb_filter_from_tree: char *(TALLOC_CTX *, const struct ldb_parse_tree *)
1970
+ldb_get_config_basedn: struct ldb_dn *(struct ldb_context *)
1971
+ldb_get_create_perms: unsigned int (struct ldb_context *)
1972
+ldb_get_default_basedn: struct ldb_dn *(struct ldb_context *)
1973
+ldb_get_event_context: struct tevent_context *(struct ldb_context *)
1974
+ldb_get_flags: unsigned int (struct ldb_context *)
1975
+ldb_get_opaque: void *(struct ldb_context *, const char *)
1976
+ldb_get_root_basedn: struct ldb_dn *(struct ldb_context *)
1977
+ldb_get_schema_basedn: struct ldb_dn *(struct ldb_context *)
1978
+ldb_global_init: int (void)
1979
+ldb_handle_get_event_context: struct tevent_context *(struct ldb_handle *)
1980
+ldb_handle_new: struct ldb_handle *(TALLOC_CTX *, struct ldb_context *)
1981
+ldb_handle_use_global_event_context: void (struct ldb_handle *)
1982
+ldb_handler_copy: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
1983
+ldb_handler_fold: int (struct ldb_context *, void *, const struct ldb_val *, struct ldb_val *)
1984
+ldb_init: struct ldb_context *(TALLOC_CTX *, struct tevent_context *)
1985
+ldb_ldif_message_redacted_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
1986
+ldb_ldif_message_string: char *(struct ldb_context *, TALLOC_CTX *, enum ldb_changetype, const struct ldb_message *)
1987
+ldb_ldif_parse_modrdn: int (struct ldb_context *, const struct ldb_ldif *, TALLOC_CTX *, struct ldb_dn **, struct ldb_dn **, bool *, struct ldb_dn **, struct ldb_dn **)
1988
+ldb_ldif_read: struct ldb_ldif *(struct ldb_context *, int (*)(void *), void *)
1989
+ldb_ldif_read_file: struct ldb_ldif *(struct ldb_context *, FILE *)
1990
+ldb_ldif_read_file_state: struct ldb_ldif *(struct ldb_context *, struct ldif_read_file_state *)
1991
+ldb_ldif_read_free: void (struct ldb_context *, struct ldb_ldif *)
1992
+ldb_ldif_read_string: struct ldb_ldif *(struct ldb_context *, const char **)
1993
+ldb_ldif_write: int (struct ldb_context *, int (*)(void *, const char *, ...), void *, const struct ldb_ldif *)
1994
+ldb_ldif_write_file: int (struct ldb_context *, FILE *, const struct ldb_ldif *)
1995
+ldb_ldif_write_redacted_trace_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
1996
+ldb_ldif_write_string: char *(struct ldb_context *, TALLOC_CTX *, const struct ldb_ldif *)
1997
+ldb_load_modules: int (struct ldb_context *, const char **)
1998
+ldb_map_add: int (struct ldb_module *, struct ldb_request *)
1999
+ldb_map_delete: int (struct ldb_module *, struct ldb_request *)
2000
+ldb_map_init: int (struct ldb_module *, const struct ldb_map_attribute *, const struct ldb_map_objectclass *, const char * const *, const char *, const char *)
2001
+ldb_map_modify: int (struct ldb_module *, struct ldb_request *)
2002
+ldb_map_rename: int (struct ldb_module *, struct ldb_request *)
2003
+ldb_map_search: int (struct ldb_module *, struct ldb_request *)
2004
+ldb_match_message: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, enum ldb_scope, bool *)
2005
+ldb_match_msg: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope)
2006
+ldb_match_msg_error: int (struct ldb_context *, const struct ldb_message *, const struct ldb_parse_tree *, struct ldb_dn *, enum ldb_scope, bool *)
2007
+ldb_match_msg_objectclass: int (const struct ldb_message *, const char *)
2008
+ldb_mod_register_control: int (struct ldb_module *, const char *)
2009
+ldb_modify: int (struct ldb_context *, const struct ldb_message *)
2010
+ldb_modify_default_callback: int (struct ldb_request *, struct ldb_reply *)
2011
+ldb_module_call_chain: char *(struct ldb_request *, TALLOC_CTX *)
2012
+ldb_module_connect_backend: int (struct ldb_context *, const char *, const char **, struct ldb_module **)
2013
+ldb_module_done: int (struct ldb_request *, struct ldb_control **, struct ldb_extended *, int)
2014
+ldb_module_flags: uint32_t (struct ldb_context *)
2015
+ldb_module_get_ctx: struct ldb_context *(struct ldb_module *)
2016
+ldb_module_get_name: const char *(struct ldb_module *)
2017
+ldb_module_get_ops: const struct ldb_module_ops *(struct ldb_module *)
2018
+ldb_module_get_private: void *(struct ldb_module *)
2019
+ldb_module_init_chain: int (struct ldb_context *, struct ldb_module *)
2020
+ldb_module_load_list: int (struct ldb_context *, const char **, struct ldb_module *, struct ldb_module **)
2021
+ldb_module_new: struct ldb_module *(TALLOC_CTX *, struct ldb_context *, const char *, const struct ldb_module_ops *)
2022
+ldb_module_next: struct ldb_module *(struct ldb_module *)
2023
+ldb_module_popt_options: struct poptOption **(struct ldb_context *)
2024
+ldb_module_send_entry: int (struct ldb_request *, struct ldb_message *, struct ldb_control **)
2025
+ldb_module_send_referral: int (struct ldb_request *, char *)
2026
+ldb_module_set_next: void (struct ldb_module *, struct ldb_module *)
2027
+ldb_module_set_private: void (struct ldb_module *, void *)
2028
+ldb_modules_hook: int (struct ldb_context *, enum ldb_module_hook_type)
2029
+ldb_modules_list_from_string: const char **(struct ldb_context *, TALLOC_CTX *, const char *)
2030
+ldb_modules_load: int (const char *, const char *)
2031
+ldb_msg_add: int (struct ldb_message *, const struct ldb_message_element *, int)
2032
+ldb_msg_add_empty: int (struct ldb_message *, const char *, int, struct ldb_message_element **)
2033
+ldb_msg_add_fmt: int (struct ldb_message *, const char *, const char *, ...)
2034
+ldb_msg_add_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *)
2035
+ldb_msg_add_steal_string: int (struct ldb_message *, const char *, char *)
2036
+ldb_msg_add_steal_value: int (struct ldb_message *, const char *, struct ldb_val *)
2037
+ldb_msg_add_string: int (struct ldb_message *, const char *, const char *)
2038
+ldb_msg_add_string_flags: int (struct ldb_message *, const char *, const char *, int)
2039
+ldb_msg_add_value: int (struct ldb_message *, const char *, const struct ldb_val *, struct ldb_message_element **)
2040
+ldb_msg_append_fmt: int (struct ldb_message *, int, const char *, const char *, ...)
2041
+ldb_msg_append_linearized_dn: int (struct ldb_message *, const char *, struct ldb_dn *, int)
2042
+ldb_msg_append_steal_string: int (struct ldb_message *, const char *, char *, int)
2043
+ldb_msg_append_steal_value: int (struct ldb_message *, const char *, struct ldb_val *, int)
2044
+ldb_msg_append_string: int (struct ldb_message *, const char *, const char *, int)
2045
+ldb_msg_append_value: int (struct ldb_message *, const char *, const struct ldb_val *, int)
2046
+ldb_msg_canonicalize: struct ldb_message *(struct ldb_context *, const struct ldb_message *)
2047
+ldb_msg_check_string_attribute: int (const struct ldb_message *, const char *, const char *)
2048
+ldb_msg_copy: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
2049
+ldb_msg_copy_attr: int (struct ldb_message *, const char *, const char *)
2050
+ldb_msg_copy_shallow: struct ldb_message *(TALLOC_CTX *, const struct ldb_message *)
2051
+ldb_msg_diff: struct ldb_message *(struct ldb_context *, struct ldb_message *, struct ldb_message *)
2052
+ldb_msg_difference: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message *, struct ldb_message *, struct ldb_message **)
2053
+ldb_msg_element_add_value: int (TALLOC_CTX *, struct ldb_message_element *, const struct ldb_val *)
2054
+ldb_msg_element_compare: int (struct ldb_message_element *, struct ldb_message_element *)
2055
+ldb_msg_element_compare_name: int (struct ldb_message_element *, struct ldb_message_element *)
2056
+ldb_msg_element_equal_ordered: bool (const struct ldb_message_element *, const struct ldb_message_element *)
2057
+ldb_msg_find_attr_as_bool: int (const struct ldb_message *, const char *, int)
2058
+ldb_msg_find_attr_as_dn: struct ldb_dn *(struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, const char *)
2059
+ldb_msg_find_attr_as_double: double (const struct ldb_message *, const char *, double)
2060
+ldb_msg_find_attr_as_int: int (const struct ldb_message *, const char *, int)
2061
+ldb_msg_find_attr_as_int64: int64_t (const struct ldb_message *, const char *, int64_t)
2062
+ldb_msg_find_attr_as_string: const char *(const struct ldb_message *, const char *, const char *)
2063
+ldb_msg_find_attr_as_uint: unsigned int (const struct ldb_message *, const char *, unsigned int)
2064
+ldb_msg_find_attr_as_uint64: uint64_t (const struct ldb_message *, const char *, uint64_t)
2065
+ldb_msg_find_common_values: int (struct ldb_context *, TALLOC_CTX *, struct ldb_message_element *, struct ldb_message_element *, uint32_t)
2066
+ldb_msg_find_duplicate_val: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message_element *, struct ldb_val **, uint32_t)
2067
+ldb_msg_find_element: struct ldb_message_element *(const struct ldb_message *, const char *)
2068
+ldb_msg_find_ldb_val: const struct ldb_val *(const struct ldb_message *, const char *)
2069
+ldb_msg_find_val: struct ldb_val *(const struct ldb_message_element *, struct ldb_val *)
2070
+ldb_msg_new: struct ldb_message *(TALLOC_CTX *)
2071
+ldb_msg_normalize: int (struct ldb_context *, TALLOC_CTX *, const struct ldb_message *, struct ldb_message **)
2072
+ldb_msg_remove_attr: void (struct ldb_message *, const char *)
2073
+ldb_msg_remove_element: void (struct ldb_message *, struct ldb_message_element *)
2074
+ldb_msg_rename_attr: int (struct ldb_message *, const char *, const char *)
2075
+ldb_msg_sanity_check: int (struct ldb_context *, const struct ldb_message *)
2076
+ldb_msg_sort_elements: void (struct ldb_message *)
2077
+ldb_next_del_trans: int (struct ldb_module *)
2078
+ldb_next_end_trans: int (struct ldb_module *)
2079
+ldb_next_init: int (struct ldb_module *)
2080
+ldb_next_prepare_commit: int (struct ldb_module *)
2081
+ldb_next_read_lock: int (struct ldb_module *)
2082
+ldb_next_read_unlock: int (struct ldb_module *)
2083
+ldb_next_remote_request: int (struct ldb_module *, struct ldb_request *)
2084
+ldb_next_request: int (struct ldb_module *, struct ldb_request *)
2085
+ldb_next_start_trans: int (struct ldb_module *)
2086
+ldb_op_default_callback: int (struct ldb_request *, struct ldb_reply *)
2087
+ldb_options_copy: const char **(TALLOC_CTX *, const char **)
2088
+ldb_options_find: const char *(struct ldb_context *, const char **, const char *)
2089
+ldb_options_get: const char **(struct ldb_context *)
2090
+ldb_pack_data: int (struct ldb_context *, const struct ldb_message *, struct ldb_val *, uint32_t)
2091
+ldb_parse_control_from_string: struct ldb_control *(struct ldb_context *, TALLOC_CTX *, const char *)
2092
+ldb_parse_control_strings: struct ldb_control **(struct ldb_context *, TALLOC_CTX *, const char **)
2093
+ldb_parse_tree: struct ldb_parse_tree *(TALLOC_CTX *, const char *)
2094
+ldb_parse_tree_attr_replace: void (struct ldb_parse_tree *, const char *, const char *)
2095
+ldb_parse_tree_copy_shallow: struct ldb_parse_tree *(TALLOC_CTX *, const struct ldb_parse_tree *)
2096
+ldb_parse_tree_walk: int (struct ldb_parse_tree *, int (*)(struct ldb_parse_tree *, void *), void *)
2097
+ldb_qsort: void (void * const, size_t, size_t, void *, ldb_qsort_cmp_fn_t)
2098
+ldb_register_backend: int (const char *, ldb_connect_fn, bool)
2099
+ldb_register_extended_match_rule: int (struct ldb_context *, const struct ldb_extended_match_rule *)
2100
+ldb_register_hook: int (ldb_hook_fn)
2101
+ldb_register_module: int (const struct ldb_module_ops *)
2102
+ldb_rename: int (struct ldb_context *, struct ldb_dn *, struct ldb_dn *)
2103
+ldb_reply_add_control: int (struct ldb_reply *, const char *, bool, void *)
2104
+ldb_reply_get_control: struct ldb_control *(struct ldb_reply *, const char *)
2105
+ldb_req_get_custom_flags: uint32_t (struct ldb_request *)
2106
+ldb_req_is_untrusted: bool (struct ldb_request *)
2107
+ldb_req_location: const char *(struct ldb_request *)
2108
+ldb_req_mark_trusted: void (struct ldb_request *)
2109
+ldb_req_mark_untrusted: void (struct ldb_request *)
2110
+ldb_req_set_custom_flags: void (struct ldb_request *, uint32_t)
2111
+ldb_req_set_location: void (struct ldb_request *, const char *)
2112
+ldb_request: int (struct ldb_context *, struct ldb_request *)
2113
+ldb_request_add_control: int (struct ldb_request *, const char *, bool, void *)
2114
+ldb_request_done: int (struct ldb_request *, int)
2115
+ldb_request_get_control: struct ldb_control *(struct ldb_request *, const char *)
2116
+ldb_request_get_status: int (struct ldb_request *)
2117
+ldb_request_replace_control: int (struct ldb_request *, const char *, bool, void *)
2118
+ldb_request_set_state: void (struct ldb_request *, int)
2119
+ldb_reset_err_string: void (struct ldb_context *)
2120
+ldb_save_controls: int (struct ldb_control *, struct ldb_request *, struct ldb_control ***)
2121
+ldb_schema_attribute_add: int (struct ldb_context *, const char *, unsigned int, const char *)
2122
+ldb_schema_attribute_add_with_syntax: int (struct ldb_context *, const char *, unsigned int, const struct ldb_schema_syntax *)
2123
+ldb_schema_attribute_by_name: const struct ldb_schema_attribute *(struct ldb_context *, const char *)
2124
+ldb_schema_attribute_fill_with_syntax: int (struct ldb_context *, TALLOC_CTX *, const char *, unsigned int, const struct ldb_schema_syntax *, struct ldb_schema_attribute *)
2125
+ldb_schema_attribute_remove: void (struct ldb_context *, const char *)
2126
+ldb_schema_attribute_remove_flagged: void (struct ldb_context *, unsigned int)
2127
+ldb_schema_attribute_set_override_handler: void (struct ldb_context *, ldb_attribute_handler_override_fn_t, void *)
2128
+ldb_schema_set_override_GUID_index: void (struct ldb_context *, const char *, const char *)
2129
+ldb_schema_set_override_indexlist: void (struct ldb_context *, bool)
2130
+ldb_search: int (struct ldb_context *, TALLOC_CTX *, struct ldb_result **, struct ldb_dn *, enum ldb_scope, const char * const *, const char *, ...)
2131
+ldb_search_default_callback: int (struct ldb_request *, struct ldb_reply *)
2132
+ldb_sequence_number: int (struct ldb_context *, enum ldb_sequence_type, uint64_t *)
2133
+ldb_set_create_perms: void (struct ldb_context *, unsigned int)
2134
+ldb_set_debug: int (struct ldb_context *, void (*)(void *, enum ldb_debug_level, const char *, va_list), void *)
2135
+ldb_set_debug_stderr: int (struct ldb_context *)
2136
+ldb_set_default_dns: void (struct ldb_context *)
2137
+ldb_set_errstring: void (struct ldb_context *, const char *)
2138
+ldb_set_event_context: void (struct ldb_context *, struct tevent_context *)
2139
+ldb_set_flags: void (struct ldb_context *, unsigned int)
2140
+ldb_set_modules_dir: void (struct ldb_context *, const char *)
2141
+ldb_set_opaque: int (struct ldb_context *, const char *, void *)
2142
+ldb_set_require_private_event_context: void (struct ldb_context *)
2143
+ldb_set_timeout: int (struct ldb_context *, struct ldb_request *, int)
2144
+ldb_set_timeout_from_prev_req: int (struct ldb_context *, struct ldb_request *, struct ldb_request *)
2145
+ldb_set_utf8_default: void (struct ldb_context *)
2146
+ldb_set_utf8_fns: void (struct ldb_context *, void *, char *(*)(void *, void *, const char *, size_t))
2147
+ldb_setup_wellknown_attributes: int (struct ldb_context *)
2148
+ldb_should_b64_encode: int (struct ldb_context *, const struct ldb_val *)
2149
+ldb_standard_syntax_by_name: const struct ldb_schema_syntax *(struct ldb_context *, const char *)
2150
+ldb_strerror: const char *(int)
2151
+ldb_string_to_time: time_t (const char *)
2152
+ldb_string_utc_to_time: time_t (const char *)
2153
+ldb_timestring: char *(TALLOC_CTX *, time_t)
2154
+ldb_timestring_utc: char *(TALLOC_CTX *, time_t)
2155
+ldb_transaction_cancel: int (struct ldb_context *)
2156
+ldb_transaction_cancel_noerr: int (struct ldb_context *)
2157
+ldb_transaction_commit: int (struct ldb_context *)
2158
+ldb_transaction_prepare_commit: int (struct ldb_context *)
2159
+ldb_transaction_start: int (struct ldb_context *)
2160
+ldb_unpack_data: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *)
2161
+ldb_unpack_data_flags: int (struct ldb_context *, const struct ldb_val *, struct ldb_message *, unsigned int)
2162
+ldb_unpack_get_format: int (const struct ldb_val *, uint32_t *)
2163
+ldb_val_dup: struct ldb_val (TALLOC_CTX *, const struct ldb_val *)
2164
+ldb_val_equal_exact: int (const struct ldb_val *, const struct ldb_val *)
2165
+ldb_val_map_local: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
2166
+ldb_val_map_remote: struct ldb_val (struct ldb_module *, void *, const struct ldb_map_attribute *, const struct ldb_val *)
2167
+ldb_val_string_cmp: int (const struct ldb_val *, const char *)
2168
+ldb_val_to_time: int (const struct ldb_val *, time_t *)
2169
+ldb_valid_attr_name: int (const char *)
2170
+ldb_vdebug: void (struct ldb_context *, enum ldb_debug_level, const char *, va_list)
2171
+ldb_wait: int (struct ldb_handle *, enum ldb_wait_type)
2172
diff --git lib/ldb/ABI/pyldb-util-2.3.4.sigs lib/ldb/ABI/pyldb-util-2.3.4.sigs
2173
new file mode 100644
2174
index 00000000000..164a806b2ff
2175
--- /dev/null
2176
+++ lib/ldb/ABI/pyldb-util-2.3.4.sigs
2177
@@ -0,0 +1,3 @@
2178
+pyldb_Dn_FromDn: PyObject *(struct ldb_dn *)
2179
+pyldb_Object_AsDn: bool (TALLOC_CTX *, PyObject *, struct ldb_context *, struct ldb_dn **)
2180
+pyldb_check_type: bool (PyObject *, const char *)
2181
2182
-- 
2183
2.25.1
2184
2185
2186
From 6237c85565332e0be1890dd57cc7e25fb76571d7 Mon Sep 17 00:00:00 2001
2187
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2188
Date: Wed, 16 Feb 2022 17:03:10 +1300
2189
Subject: [PATCH 15/99] CVE-2022-32745 s4/dsdb/samldb: Check for empty values
2190
 array
2191
2192
This avoids potentially trying to access the first element of an empty
2193
array.
2194
2195
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008
2196
2197
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2198
---
2199
 source4/dsdb/samdb/ldb_modules/samldb.c | 4 ++--
2200
 1 file changed, 2 insertions(+), 2 deletions(-)
2201
2202
diff --git source4/dsdb/samdb/ldb_modules/samldb.c source4/dsdb/samdb/ldb_modules/samldb.c
2203
index 107e643e492..3625bb42e58 100644
2204
--- source4/dsdb/samdb/ldb_modules/samldb.c
2205
+++ source4/dsdb/samdb/ldb_modules/samldb.c
2206
@@ -751,7 +751,7 @@ static int samldb_schema_add_handle_linkid(struct samldb_ctx *ac)
2207
 		return ret;
2208
 	}
2209
 
2210
-	if (el == NULL) {
2211
+	if (el == NULL || el->num_values == 0) {
2212
 		return LDB_SUCCESS;
2213
 	}
2214
 
2215
@@ -919,7 +919,7 @@ static int samldb_schema_add_handle_mapiid(struct samldb_ctx *ac)
2216
 		return ret;
2217
 	}
2218
 
2219
-	if (el == NULL) {
2220
+	if (el == NULL || el->num_values == 0) {
2221
 		return LDB_SUCCESS;
2222
 	}
2223
 
2224
-- 
2225
2.25.1
2226
2227
2228
From 7c8427e5d2f247921ab44996829acfed1f5f2360 Mon Sep 17 00:00:00 2001
2229
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2230
Date: Thu, 17 Feb 2022 11:11:53 +1300
2231
Subject: [PATCH 16/99] CVE-2022-32745 s4/dsdb/util: Use correct value for loop
2232
 count limit
2233
2234
Currently, we can crash the server by sending a large number of values
2235
of a specific attribute (such as sAMAccountName) spread across a few
2236
message elements. If val_count is larger than the total number of
2237
elements, we get an access beyond the elements array.
2238
2239
Similarly, we can include unrelated message elements prior to the
2240
message elements of the attribute in question, so that not all of the
2241
attribute's values are copied into the returned elements values array.
2242
This can cause the server to access uninitialised data, likely resulting
2243
in a crash or unexpected behaviour.
2244
2245
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008
2246
2247
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2248
---
2249
 source4/dsdb/samdb/ldb_modules/util.c | 2 +-
2250
 1 file changed, 1 insertion(+), 1 deletion(-)
2251
2252
diff --git source4/dsdb/samdb/ldb_modules/util.c source4/dsdb/samdb/ldb_modules/util.c
2253
index 405febf0b3d..14947746837 100644
2254
--- source4/dsdb/samdb/ldb_modules/util.c
2255
+++ source4/dsdb/samdb/ldb_modules/util.c
2256
@@ -1546,7 +1546,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
2257
 
2258
 	v = _el->values;
2259
 
2260
-	for (i = 0; i < val_count; i++) {
2261
+	for (i = 0; i < msg->num_elements; i++) {
2262
 		if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
2263
 			if ((operation == LDB_MODIFY) &&
2264
 			    (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
2265
-- 
2266
2.25.1
2267
2268
2269
From 4d2d30c21b16a53d5547cb803efe49cb6304ce37 Mon Sep 17 00:00:00 2001
2270
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2271
Date: Thu, 17 Feb 2022 11:13:38 +1300
2272
Subject: [PATCH 17/99] CVE-2022-32745 s4/dsdb/util: Don't call memcpy() with a
2273
 NULL pointer
2274
2275
Doing so is undefined behaviour.
2276
2277
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008
2278
2279
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2280
---
2281
 source4/dsdb/samdb/ldb_modules/util.c | 12 ++++++++----
2282
 1 file changed, 8 insertions(+), 4 deletions(-)
2283
2284
diff --git source4/dsdb/samdb/ldb_modules/util.c source4/dsdb/samdb/ldb_modules/util.c
2285
index 14947746837..35ae110b5ef 100644
2286
--- source4/dsdb/samdb/ldb_modules/util.c
2287
+++ source4/dsdb/samdb/ldb_modules/util.c
2288
@@ -1548,15 +1548,19 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
2289
 
2290
 	for (i = 0; i < msg->num_elements; i++) {
2291
 		if (ldb_attr_cmp(msg->elements[i].name, attr_name) == 0) {
2292
+			const struct ldb_message_element *tmp_el = &msg->elements[i];
2293
 			if ((operation == LDB_MODIFY) &&
2294
-			    (LDB_FLAG_MOD_TYPE(msg->elements[i].flags)
2295
+			    (LDB_FLAG_MOD_TYPE(tmp_el->flags)
2296
 						== LDB_FLAG_MOD_DELETE)) {
2297
 				continue;
2298
 			}
2299
+			if (tmp_el->values == NULL || tmp_el->num_values == 0) {
2300
+				continue;
2301
+			}
2302
 			memcpy(v,
2303
-			       msg->elements[i].values,
2304
-			       msg->elements[i].num_values);
2305
-			v += msg->elements[i].num_values;
2306
+			       tmp_el->values,
2307
+			       tmp_el->num_values);
2308
+			v += tmp_el->num_values;
2309
 		}
2310
 	}
2311
 
2312
-- 
2313
2.25.1
2314
2315
2316
From 65d96369fa4f915f01e203cfc8b15e48c5b4b440 Mon Sep 17 00:00:00 2001
2317
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2318
Date: Fri, 3 Jun 2022 16:16:31 +1200
2319
Subject: [PATCH 18/99] CVE-2022-32745 s4/dsdb/util: Correctly copy values into
2320
 message element
2321
2322
To use memcpy(), we need to specify the number of bytes to copy, rather
2323
than the number of ldb_val structures.
2324
2325
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15008
2326
2327
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2328
---
2329
 source4/dsdb/samdb/ldb_modules/util.c | 2 +-
2330
 1 file changed, 1 insertion(+), 1 deletion(-)
2331
2332
diff --git source4/dsdb/samdb/ldb_modules/util.c source4/dsdb/samdb/ldb_modules/util.c
2333
index 35ae110b5ef..e7fe8f855df 100644
2334
--- source4/dsdb/samdb/ldb_modules/util.c
2335
+++ source4/dsdb/samdb/ldb_modules/util.c
2336
@@ -1559,7 +1559,7 @@ int dsdb_get_expected_new_values(TALLOC_CTX *mem_ctx,
2337
 			}
2338
 			memcpy(v,
2339
 			       tmp_el->values,
2340
-			       tmp_el->num_values);
2341
+			       tmp_el->num_values * sizeof(*v));
2342
 			v += tmp_el->num_values;
2343
 		}
2344
 	}
2345
-- 
2346
2.25.1
2347
2348
2349
From 34eb92a2066cc403aac5a3708257b04a40ba19ee Mon Sep 17 00:00:00 2001
2350
From: Isaac Boukris <iboukris@gmail.com>
2351
Date: Sat, 19 Sep 2020 14:16:20 +0200
2352
Subject: [PATCH 19/99] s4:mit-kdb: Force canonicalization for looking up
2353
 principals
2354
2355
See also
2356
https://github.com/krb5/krb5/commit/ac8865a22138ab0c657208c41be8fd6bc7968148
2357
2358
Pair-Programmed-With: Andreas Schneider <asn@samba.org>
2359
Signed-off-by: Isaac Boukris <iboukris@gmail.com>
2360
Signed-off-by: Andreas Schneider <asn@samba.org>
2361
Reviewed-by: Alexander Bokovoy <ab@samba.org>
2362
2363
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
2364
Autobuild-Date(master): Mon Nov 29 09:32:26 UTC 2021 on sn-devel-184
2365
2366
(cherry picked from commit 90febd2a33b88af49af595fe0e995d6ba0f33a1b)
2367
2368
[jsutton@samba.org Removed MIT knownfail changes]
2369
---
2370
 source4/heimdal/lib/hdb/hdb.h | 1 +
2371
 source4/kdc/db-glue.c         | 7 ++++++-
2372
 source4/kdc/mit_samba.c       | 8 ++++++++
2373
 source4/kdc/sdb.h             | 1 +
2374
 4 files changed, 16 insertions(+), 1 deletion(-)
2375
2376
diff --git source4/heimdal/lib/hdb/hdb.h source4/heimdal/lib/hdb/hdb.h
2377
index 5ef9d9565f3..dafaffc6c2d 100644
2378
--- source4/heimdal/lib/hdb/hdb.h
2379
+++ source4/heimdal/lib/hdb/hdb.h
2380
@@ -63,6 +63,7 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
2381
 #define HDB_F_ALL_KVNOS		2048	/* we want all the keys, live or not */
2382
 #define HDB_F_FOR_AS_REQ	4096	/* fetch is for a AS REQ */
2383
 #define HDB_F_FOR_TGS_REQ	8192	/* fetch is for a TGS REQ */
2384
+#define HDB_F_FORCE_CANON	16384	/* force canonicalition */
2385
 
2386
 /* hdb_capability_flags */
2387
 #define HDB_CAP_F_HANDLE_ENTERPRISE_PRINCIPAL 1
2388
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
2389
index 3a7e2176653..ac47fe78373 100644
2390
--- source4/kdc/db-glue.c
2391
+++ source4/kdc/db-glue.c
2392
@@ -957,11 +957,16 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
2393
 			krb5_clear_error_message(context);
2394
 			goto out;
2395
 		}
2396
-	} else if ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ)) {
2397
+	} else if ((flags & SDB_F_FORCE_CANON) ||
2398
+		   ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) {
2399
 		/*
2400
 		 * SDB_F_CANON maps from the canonicalize flag in the
2401
 		 * packet, and has a different meaning between AS-REQ
2402
 		 * and TGS-REQ.  We only change the principal in the AS-REQ case
2403
+		 *
2404
+		 * The SDB_F_FORCE_CANON if for new MIT KDC code that wants
2405
+		 * the canonical name in all lookups, and takes care to
2406
+		 * canonicalize only when appropriate.
2407
 		 */
2408
 		ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
2409
 		if (ret) {
2410
diff --git source4/kdc/mit_samba.c source4/kdc/mit_samba.c
2411
index e015c5a52db..c2a604045d9 100644
2412
--- source4/kdc/mit_samba.c
2413
+++ source4/kdc/mit_samba.c
2414
@@ -195,6 +195,14 @@ int mit_samba_get_principal(struct mit_samba_context *ctx,
2415
 		return ENOMEM;
2416
 	}
2417
 
2418
+#if KRB5_KDB_API_VERSION >= 10
2419
+	/*
2420
+	 * The MIT KDC code that wants the canonical name in all lookups, and
2421
+	 * takes care to canonicalize only when appropriate.
2422
+	 */
2423
+	sflags |= SDB_F_FORCE_CANON;
2424
+#endif
2425
+
2426
 	if (kflags & KRB5_KDB_FLAG_CANONICALIZE) {
2427
 		sflags |= SDB_F_CANON;
2428
 	}
2429
diff --git source4/kdc/sdb.h source4/kdc/sdb.h
2430
index c929acccce6..a9115ec23d7 100644
2431
--- source4/kdc/sdb.h
2432
+++ source4/kdc/sdb.h
2433
@@ -116,6 +116,7 @@ struct sdb_entry_ex {
2434
 #define SDB_F_KVNO_SPECIFIED	128	/* we want a particular KVNO */
2435
 #define SDB_F_FOR_AS_REQ	4096	/* fetch is for a AS REQ */
2436
 #define SDB_F_FOR_TGS_REQ	8192	/* fetch is for a TGS REQ */
2437
+#define SDB_F_FORCE_CANON	16384	/* force canonicalition */
2438
 
2439
 void sdb_free_entry(struct sdb_entry_ex *e);
2440
 void free_sdb_entry(struct sdb_entry *s);
2441
-- 
2442
2.25.1
2443
2444
2445
From 06a0a75b16bace9c29568653d9e4bde4050c5ee5 Mon Sep 17 00:00:00 2001
2446
From: Andreas Schneider <asn@samba.org>
2447
Date: Tue, 21 Dec 2021 12:17:11 +0100
2448
Subject: [PATCH 20/99] s4:kdc: Also cannoicalize krbtgt principals when
2449
 enforcing canonicalization
2450
2451
Signed-off-by: Andreas Schneider <asn@samba.org>
2452
Reviewed-by: Stefan Metzmacher <metze@samba.org>
2453
(cherry picked from commit f1ec950aeb47283a504018bafa21f54c3282e70c)
2454
---
2455
 source4/kdc/db-glue.c | 2 +-
2456
 1 file changed, 1 insertion(+), 1 deletion(-)
2457
2458
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
2459
index ac47fe78373..d017741e30a 100644
2460
--- source4/kdc/db-glue.c
2461
+++ source4/kdc/db-glue.c
2462
@@ -920,7 +920,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
2463
 	if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
2464
 		p->is_krbtgt = true;
2465
 
2466
-		if (flags & (SDB_F_CANON)) {
2467
+		if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) {
2468
 			/*
2469
 			 * When requested to do so, ensure that the
2470
 			 * both realm values in the principal are set
2471
-- 
2472
2.25.1
2473
2474
2475
From b4005403032b0b33ca88d3abcbf085621b32bd5b Mon Sep 17 00:00:00 2001
2476
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2477
Date: Wed, 24 Nov 2021 11:30:38 +1300
2478
Subject: [PATCH 21/99] selftest: Check received LDB error code when
2479
 STRICT_CHECKING=0
2480
2481
We were instead only checking the expected error.
2482
2483
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2484
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2485
(cherry picked from commit ad4d6fb01fd8083e68f07c427af8932574810cdc)
2486
---
2487
 source4/dsdb/tests/python/priv_attrs.py | 2 +-
2488
 1 file changed, 1 insertion(+), 1 deletion(-)
2489
2490
diff --git source4/dsdb/tests/python/priv_attrs.py source4/dsdb/tests/python/priv_attrs.py
2491
index aa35dcc1317..4dfdfb9cbb8 100644
2492
--- source4/dsdb/tests/python/priv_attrs.py
2493
+++ source4/dsdb/tests/python/priv_attrs.py
2494
@@ -167,7 +167,7 @@ class PrivAttrsTests(samba.tests.TestCase):
2495
         creds_tmp.set_kerberos_state(DONT_USE_KERBEROS)  # kinit is too expensive to use in a tight loop
2496
         return creds_tmp
2497
 
2498
-    def assertGotLdbError(self, got, wanted):
2499
+    def assertGotLdbError(self, wanted, got):
2500
         if not self.strict_checking:
2501
             self.assertNotEqual(got, ldb.SUCCESS)
2502
         else:
2503
-- 
2504
2.25.1
2505
2506
2507
From 6a4ed078902dcc57ab14f701c88e76ec0ac375e7 Mon Sep 17 00:00:00 2001
2508
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2509
Date: Wed, 24 Nov 2021 11:53:18 +1300
2510
Subject: [PATCH 22/99] tests/krb5: Remove unused variable
2511
2512
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2513
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2514
(cherry picked from commit 57b1b76154d699b9d70ad04fa5e94c4b30f0e4bf)
2515
---
2516
 python/samba/tests/krb5/raw_testcase.py | 2 --
2517
 1 file changed, 2 deletions(-)
2518
2519
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
2520
index 42f2e94f5aa..36a6134e6c9 100644
2521
--- python/samba/tests/krb5/raw_testcase.py
2522
+++ python/samba/tests/krb5/raw_testcase.py
2523
@@ -2855,7 +2855,6 @@ class RawKerberosTest(TestCaseInTempDir):
2524
 
2525
         expect_etype_info2 = ()
2526
         expect_etype_info = False
2527
-        unexpect_etype_info = True
2528
         expected_aes_type = 0
2529
         expected_rc4_type = 0
2530
         if kcrypto.Enctype.RC4 in proposed_etypes:
2531
@@ -2868,7 +2867,6 @@ class RawKerberosTest(TestCaseInTempDir):
2532
                 if etype > expected_aes_type:
2533
                     expected_aes_type = etype
2534
             if etype in (kcrypto.Enctype.RC4,) and error_code != 0:
2535
-                unexpect_etype_info = False
2536
                 if etype > expected_rc4_type:
2537
                     expected_rc4_type = etype
2538
 
2539
-- 
2540
2.25.1
2541
2542
2543
From 837453d34799f44653d0d6d690d3e3d5eb074993 Mon Sep 17 00:00:00 2001
2544
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2545
Date: Wed, 24 Nov 2021 11:34:11 +1300
2546
Subject: [PATCH 23/99] tests/krb5: Deduplicate AS-REQ tests
2547
2548
salt_tests was running the tests defined in the base class as well as
2549
its own tests.
2550
2551
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2552
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2553
(cherry picked from commit f0b222e3ecf72c8562bc97bedd9f3a92980b60d5)
2554
---
2555
 python/samba/tests/krb5/as_req_tests.py | 163 ++++++++++++------------
2556
 python/samba/tests/krb5/salt_tests.py   |   4 +-
2557
 2 files changed, 85 insertions(+), 82 deletions(-)
2558
2559
diff --git python/samba/tests/krb5/as_req_tests.py python/samba/tests/krb5/as_req_tests.py
2560
index 08081928363..315720f85d6 100755
2561
--- python/samba/tests/krb5/as_req_tests.py
2562
+++ python/samba/tests/krb5/as_req_tests.py
2563
@@ -38,87 +38,8 @@ from samba.tests.krb5.rfc4120_constants import (
2564
 global_asn1_print = False
2565
 global_hexdump = False
2566
 
2567
-@DynamicTestCase
2568
-class AsReqKerberosTests(KDCBaseTest):
2569
-
2570
-    @classmethod
2571
-    def setUpDynamicTestCases(cls):
2572
-        for (name, idx) in cls.etype_test_permutation_name_idx():
2573
-            for pac in [None, True, False]:
2574
-                tname = "%s_pac_%s" % (name, pac)
2575
-                targs = (idx, pac)
2576
-                cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs)
2577
-
2578
-    def setUp(self):
2579
-        super(AsReqKerberosTests, self).setUp()
2580
-        self.do_asn1_print = global_asn1_print
2581
-        self.do_hexdump = global_hexdump
2582
-
2583
-    def _test_as_req_nopreauth(self,
2584
-                               initial_etypes,
2585
-                               pac=None,
2586
-                               initial_kdc_options=None):
2587
-        client_creds = self.get_client_creds()
2588
-        client_account = client_creds.get_username()
2589
-        client_as_etypes = self.get_default_enctypes()
2590
-        krbtgt_creds = self.get_krbtgt_creds(require_keys=False)
2591
-        krbtgt_account = krbtgt_creds.get_username()
2592
-        realm = krbtgt_creds.get_realm()
2593
-
2594
-        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
2595
-                                          names=[client_account])
2596
-        sname = self.PrincipalName_create(name_type=NT_SRV_INST,
2597
-                                          names=[krbtgt_account, realm])
2598
-
2599
-        expected_crealm = realm
2600
-        expected_cname = cname
2601
-        expected_srealm = realm
2602
-        expected_sname = sname
2603
-        expected_salt = client_creds.get_salt()
2604
-
2605
-        if any(etype in client_as_etypes and etype in initial_etypes
2606
-               for etype in (kcrypto.Enctype.AES256,
2607
-                             kcrypto.Enctype.AES128,
2608
-                             kcrypto.Enctype.RC4)):
2609
-            expected_error_mode = KDC_ERR_PREAUTH_REQUIRED
2610
-        else:
2611
-            expected_error_mode = KDC_ERR_ETYPE_NOSUPP
2612
-
2613
-        kdc_exchange_dict = self.as_exchange_dict(
2614
-            expected_crealm=expected_crealm,
2615
-            expected_cname=expected_cname,
2616
-            expected_srealm=expected_srealm,
2617
-            expected_sname=expected_sname,
2618
-            generate_padata_fn=None,
2619
-            check_error_fn=self.generic_check_kdc_error,
2620
-            check_rep_fn=None,
2621
-            expected_error_mode=expected_error_mode,
2622
-            client_as_etypes=client_as_etypes,
2623
-            expected_salt=expected_salt,
2624
-            kdc_options=str(initial_kdc_options),
2625
-            pac_request=pac)
2626
-
2627
-        self._generic_kdc_exchange(kdc_exchange_dict,
2628
-                                   cname=cname,
2629
-                                   realm=realm,
2630
-                                   sname=sname,
2631
-                                   etypes=initial_etypes)
2632
-
2633
-    def _test_as_req_no_preauth_with_args(self, etype_idx, pac):
2634
-        name, etypes = self.etype_test_permutation_by_idx(etype_idx)
2635
-        self._test_as_req_nopreauth(
2636
-                     pac=pac,
2637
-                     initial_etypes=etypes,
2638
-                     initial_kdc_options=krb5_asn1.KDCOptions('forwardable'))
2639
-
2640
-    def test_as_req_enc_timestamp(self):
2641
-        client_creds = self.get_client_creds()
2642
-        self._run_as_req_enc_timestamp(client_creds)
2643
-
2644
-    def test_as_req_enc_timestamp_mac(self):
2645
-        client_creds = self.get_mach_creds()
2646
-        self._run_as_req_enc_timestamp(client_creds)
2647
 
2648
+class AsReqBaseTest(KDCBaseTest):
2649
     def _run_as_req_enc_timestamp(self, client_creds):
2650
         client_account = client_creds.get_username()
2651
         client_as_etypes = self.get_default_enctypes()
2652
@@ -207,6 +128,88 @@ class AsReqKerberosTests(KDCBaseTest):
2653
         return etype_info2
2654
 
2655
 
2656
+@DynamicTestCase
2657
+class AsReqKerberosTests(AsReqBaseTest):
2658
+
2659
+    @classmethod
2660
+    def setUpDynamicTestCases(cls):
2661
+        for (name, idx) in cls.etype_test_permutation_name_idx():
2662
+            for pac in [None, True, False]:
2663
+                tname = "%s_pac_%s" % (name, pac)
2664
+                targs = (idx, pac)
2665
+                cls.generate_dynamic_test("test_as_req_no_preauth", tname, *targs)
2666
+
2667
+    def setUp(self):
2668
+        super(AsReqKerberosTests, self).setUp()
2669
+        self.do_asn1_print = global_asn1_print
2670
+        self.do_hexdump = global_hexdump
2671
+
2672
+    def _test_as_req_nopreauth(self,
2673
+                               initial_etypes,
2674
+                               pac=None,
2675
+                               initial_kdc_options=None):
2676
+        client_creds = self.get_client_creds()
2677
+        client_account = client_creds.get_username()
2678
+        client_as_etypes = self.get_default_enctypes()
2679
+        krbtgt_creds = self.get_krbtgt_creds(require_keys=False)
2680
+        krbtgt_account = krbtgt_creds.get_username()
2681
+        realm = krbtgt_creds.get_realm()
2682
+
2683
+        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
2684
+                                          names=[client_account])
2685
+        sname = self.PrincipalName_create(name_type=NT_SRV_INST,
2686
+                                          names=[krbtgt_account, realm])
2687
+
2688
+        expected_crealm = realm
2689
+        expected_cname = cname
2690
+        expected_srealm = realm
2691
+        expected_sname = sname
2692
+        expected_salt = client_creds.get_salt()
2693
+
2694
+        if any(etype in client_as_etypes and etype in initial_etypes
2695
+               for etype in (kcrypto.Enctype.AES256,
2696
+                             kcrypto.Enctype.AES128,
2697
+                             kcrypto.Enctype.RC4)):
2698
+            expected_error_mode = KDC_ERR_PREAUTH_REQUIRED
2699
+        else:
2700
+            expected_error_mode = KDC_ERR_ETYPE_NOSUPP
2701
+
2702
+        kdc_exchange_dict = self.as_exchange_dict(
2703
+            expected_crealm=expected_crealm,
2704
+            expected_cname=expected_cname,
2705
+            expected_srealm=expected_srealm,
2706
+            expected_sname=expected_sname,
2707
+            generate_padata_fn=None,
2708
+            check_error_fn=self.generic_check_kdc_error,
2709
+            check_rep_fn=None,
2710
+            expected_error_mode=expected_error_mode,
2711
+            client_as_etypes=client_as_etypes,
2712
+            expected_salt=expected_salt,
2713
+            kdc_options=str(initial_kdc_options),
2714
+            pac_request=pac)
2715
+
2716
+        self._generic_kdc_exchange(kdc_exchange_dict,
2717
+                                   cname=cname,
2718
+                                   realm=realm,
2719
+                                   sname=sname,
2720
+                                   etypes=initial_etypes)
2721
+
2722
+    def _test_as_req_no_preauth_with_args(self, etype_idx, pac):
2723
+        name, etypes = self.etype_test_permutation_by_idx(etype_idx)
2724
+        self._test_as_req_nopreauth(
2725
+                     pac=pac,
2726
+                     initial_etypes=etypes,
2727
+                     initial_kdc_options=krb5_asn1.KDCOptions('forwardable'))
2728
+
2729
+    def test_as_req_enc_timestamp(self):
2730
+        client_creds = self.get_client_creds()
2731
+        self._run_as_req_enc_timestamp(client_creds)
2732
+
2733
+    def test_as_req_enc_timestamp_mac(self):
2734
+        client_creds = self.get_mach_creds()
2735
+        self._run_as_req_enc_timestamp(client_creds)
2736
+
2737
+
2738
 if __name__ == "__main__":
2739
     global_asn1_print = False
2740
     global_hexdump = False
2741
diff --git python/samba/tests/krb5/salt_tests.py python/samba/tests/krb5/salt_tests.py
2742
index ecbf618e40e..db777f8b7bc 100755
2743
--- python/samba/tests/krb5/salt_tests.py
2744
+++ python/samba/tests/krb5/salt_tests.py
2745
@@ -21,7 +21,7 @@ import os
2746
 
2747
 import ldb
2748
 
2749
-from samba.tests.krb5.as_req_tests import AsReqKerberosTests
2750
+from samba.tests.krb5.as_req_tests import AsReqBaseTest
2751
 import samba.tests.krb5.kcrypto as kcrypto
2752
 
2753
 sys.path.insert(0, "bin/python")
2754
@@ -31,7 +31,7 @@ global_asn1_print = False
2755
 global_hexdump = False
2756
 
2757
 
2758
-class SaltTests(AsReqKerberosTests):
2759
+class SaltTests(AsReqBaseTest):
2760
 
2761
     def setUp(self):
2762
         super().setUp()
2763
-- 
2764
2.25.1
2765
2766
2767
From 3d48ade670bb5b026d7bc0a26a4fa6775b21653b Mon Sep 17 00:00:00 2001
2768
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2769
Date: Wed, 24 Nov 2021 16:02:00 +1300
2770
Subject: [PATCH 24/99] tests/krb5: Run test_rpc against member server
2771
2772
We were instead always running against the DC.
2773
2774
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2775
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2776
(cherry picked from commit 167bd2070483004cd0b9a96ffb40ea73c6ddf579)
2777
---
2778
 python/samba/tests/krb5/test_rpc.py | 9 ++++-----
2779
 1 file changed, 4 insertions(+), 5 deletions(-)
2780
2781
diff --git python/samba/tests/krb5/test_rpc.py python/samba/tests/krb5/test_rpc.py
2782
index 03c125f518a..2d483986e83 100755
2783
--- python/samba/tests/krb5/test_rpc.py
2784
+++ python/samba/tests/krb5/test_rpc.py
2785
@@ -58,7 +58,7 @@ class RpcTests(KDCBaseTest):
2786
 
2787
         samdb = self.get_samdb()
2788
 
2789
-        mach_name = samdb.host_dns_name()
2790
+        mach_name = self.host
2791
         service = "cifs"
2792
 
2793
         # Create the user account.
2794
@@ -67,7 +67,7 @@ class RpcTests(KDCBaseTest):
2795
             use_cache=False)
2796
         user_name = user_credentials.get_username()
2797
 
2798
-        mach_credentials = self.get_dc_creds()
2799
+        mach_credentials = self.get_server_creds()
2800
 
2801
         # Talk to the KDC to obtain the service ticket, which gets placed into
2802
         # the cache. The machine account name has to match the name in the
2803
@@ -114,8 +114,7 @@ class RpcTests(KDCBaseTest):
2804
             self.assertEqual(user_name, account_name.string)
2805
 
2806
     def test_rpc_anonymous(self):
2807
-        samdb = self.get_samdb()
2808
-        mach_name = samdb.host_dns_name()
2809
+        mach_name = self.host
2810
 
2811
         anon_creds = credentials.Credentials()
2812
         anon_creds.set_anonymous()
2813
@@ -125,7 +124,7 @@ class RpcTests(KDCBaseTest):
2814
 
2815
         (account_name, _) = conn.GetUserName(None, None, None)
2816
 
2817
-        self.assertEqual('ANONYMOUS LOGON', account_name.string)
2818
+        self.assertEqual('ANONYMOUS LOGON', account_name.string.upper())
2819
 
2820
 
2821
 if __name__ == "__main__":
2822
-- 
2823
2.25.1
2824
2825
2826
From bf1aa0927895b1007ecea738681235b5be2e6208 Mon Sep 17 00:00:00 2001
2827
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2828
Date: Wed, 24 Nov 2021 11:37:35 +1300
2829
Subject: [PATCH 25/99] tests/krb5: Allow PasswordKey_create() to use s2kparams
2830
2831
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2832
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2833
(cherry picked from commit a560c2e9ad8abb824d1805c86c656943745f81eb)
2834
---
2835
 python/samba/tests/krb5/raw_testcase.py | 9 ++++++---
2836
 1 file changed, 6 insertions(+), 3 deletions(-)
2837
2838
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
2839
index 36a6134e6c9..da3f69c79c6 100644
2840
--- python/samba/tests/krb5/raw_testcase.py
2841
+++ python/samba/tests/krb5/raw_testcase.py
2842
@@ -1167,10 +1167,11 @@ class RawKerberosTest(TestCaseInTempDir):
2843
         key = kcrypto.Key(etype, contents)
2844
         return RodcPacEncryptionKey(key, kvno)
2845
 
2846
-    def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None):
2847
+    def PasswordKey_create(self, etype=None, pwd=None, salt=None, kvno=None,
2848
+                           params=None):
2849
         self.assertIsNotNone(pwd)
2850
         self.assertIsNotNone(salt)
2851
-        key = kcrypto.string_to_key(etype, pwd, salt)
2852
+        key = kcrypto.string_to_key(etype, pwd, salt, params=params)
2853
         return RodcPacEncryptionKey(key, kvno)
2854
 
2855
     def PasswordKey_from_etype_info2(self, creds, etype_info2, kvno=None):
2856
@@ -1182,9 +1183,11 @@ class RawKerberosTest(TestCaseInTempDir):
2857
             nthash = creds.get_nt_hash()
2858
             return self.SessionKey_create(etype=e, contents=nthash, kvno=kvno)
2859
 
2860
+        params = etype_info2.get('s2kparams')
2861
+
2862
         password = creds.get_password()
2863
         return self.PasswordKey_create(
2864
-            etype=e, pwd=password, salt=salt, kvno=kvno)
2865
+            etype=e, pwd=password, salt=salt, kvno=kvno, params=params)
2866
 
2867
     def TicketDecryptionKey_from_creds(self, creds, etype=None):
2868
 
2869
-- 
2870
2.25.1
2871
2872
2873
From 651db77b1c19c036cf229c44b764b0155e1dc399 Mon Sep 17 00:00:00 2001
2874
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2875
Date: Wed, 24 Nov 2021 11:40:35 +1300
2876
Subject: [PATCH 26/99] tests/krb5: Split out methods to create renewable or
2877
 invalid tickets
2878
2879
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2880
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2881
(cherry picked from commit e930274aa43810d6485c3c8a7c82958ecb409630)
2882
---
2883
 python/samba/tests/krb5/kdc_tgs_tests.py | 68 +++++++++++++-----------
2884
 1 file changed, 36 insertions(+), 32 deletions(-)
2885
2886
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
2887
index abac5a47a56..0578969ba69 100755
2888
--- python/samba/tests/krb5/kdc_tgs_tests.py
2889
+++ python/samba/tests/krb5/kdc_tgs_tests.py
2890
@@ -1786,6 +1786,40 @@ class KdcTgsTests(KDCBaseTest):
2891
 
2892
         self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN)
2893
 
2894
+    def _modify_renewable(self, enc_part):
2895
+        # Set the renewable flag.
2896
+        renewable_flag = krb5_asn1.TicketFlags('renewable')
2897
+        pos = len(tuple(renewable_flag)) - 1
2898
+
2899
+        flags = enc_part['flags']
2900
+        self.assertLessEqual(pos, len(flags))
2901
+
2902
+        new_flags = flags[:pos] + '1' + flags[pos + 1:]
2903
+        enc_part['flags'] = new_flags
2904
+
2905
+        # Set the renew-till time to be in the future.
2906
+        renew_till = self.get_KerberosTime(offset=100 * 60 * 60)
2907
+        enc_part['renew-till'] = renew_till
2908
+
2909
+        return enc_part
2910
+
2911
+    def _modify_invalid(self, enc_part):
2912
+        # Set the invalid flag.
2913
+        invalid_flag = krb5_asn1.TicketFlags('invalid')
2914
+        pos = len(tuple(invalid_flag)) - 1
2915
+
2916
+        flags = enc_part['flags']
2917
+        self.assertLessEqual(pos, len(flags))
2918
+
2919
+        new_flags = flags[:pos] + '1' + flags[pos + 1:]
2920
+        enc_part['flags'] = new_flags
2921
+
2922
+        # Set the ticket start time to be in the past.
2923
+        past_time = self.get_KerberosTime(offset=-100 * 60 * 60)
2924
+        enc_part['starttime'] = past_time
2925
+
2926
+        return enc_part
2927
+
2928
     def _get_tgt(self,
2929
                  client_creds,
2930
                  renewable=False,
2931
@@ -1880,39 +1914,9 @@ class KdcTgsTests(KDCBaseTest):
2932
             }
2933
 
2934
         if renewable:
2935
-            def flags_modify_fn(enc_part):
2936
-                # Set the renewable flag.
2937
-                renewable_flag = krb5_asn1.TicketFlags('renewable')
2938
-                pos = len(tuple(renewable_flag)) - 1
2939
-
2940
-                flags = enc_part['flags']
2941
-                self.assertLessEqual(pos, len(flags))
2942
-
2943
-                new_flags = flags[:pos] + '1' + flags[pos + 1:]
2944
-                enc_part['flags'] = new_flags
2945
-
2946
-                # Set the renew-till time to be in the future.
2947
-                renew_till = self.get_KerberosTime(offset=100 * 60 * 60)
2948
-                enc_part['renew-till'] = renew_till
2949
-
2950
-                return enc_part
2951
+            flags_modify_fn = self._modify_renewable
2952
         elif invalid:
2953
-            def flags_modify_fn(enc_part):
2954
-                # Set the invalid flag.
2955
-                invalid_flag = krb5_asn1.TicketFlags('invalid')
2956
-                pos = len(tuple(invalid_flag)) - 1
2957
-
2958
-                flags = enc_part['flags']
2959
-                self.assertLessEqual(pos, len(flags))
2960
-
2961
-                new_flags = flags[:pos] + '1' + flags[pos + 1:]
2962
-                enc_part['flags'] = new_flags
2963
-
2964
-                # Set the ticket start time to be in the past.
2965
-                past_time = self.get_KerberosTime(offset=-100 * 60 * 60)
2966
-                enc_part['starttime'] = past_time
2967
-
2968
-                return enc_part
2969
+            flags_modify_fn = self._modify_invalid
2970
         else:
2971
             flags_modify_fn = None
2972
 
2973
-- 
2974
2.25.1
2975
2976
2977
From 1e9ad4246ce7fe7a212da4357e6e11c5ac22a8b2 Mon Sep 17 00:00:00 2001
2978
From: Joseph Sutton <josephsutton@catalyst.net.nz>
2979
Date: Wed, 24 Nov 2021 11:52:31 +1300
2980
Subject: [PATCH 27/99] tests/krb5: Adjust error codes to better match Windows
2981
 with PacRequestorEnforcement=2
2982
2983
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
2984
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
2985
(cherry picked from commit d95705172bcf6fe24817800a4c0009e9cc8be595)
2986
2987
[jsutton@samba.org Fixed MIT knownfail conflict]
2988
---
2989
 python/samba/tests/krb5/alias_tests.py        |   7 +-
2990
 python/samba/tests/krb5/kdc_tgs_tests.py      | 130 ++++++++----------
2991
 .../ms_kile_client_principal_lookup_tests.py  |  39 ++----
2992
 python/samba/tests/krb5/s4u_tests.py          |  57 ++++----
2993
 python/samba/tests/krb5/test_rpc.py           |   8 +-
2994
 selftest/knownfail_heimdal_kdc                |  64 +++++++++
2995
 selftest/knownfail_mit_kdc                    |   9 ++
2996
 7 files changed, 181 insertions(+), 133 deletions(-)
2997
2998
diff --git python/samba/tests/krb5/alias_tests.py python/samba/tests/krb5/alias_tests.py
2999
index 60213845a44..1f63775c189 100755
3000
--- python/samba/tests/krb5/alias_tests.py
3001
+++ python/samba/tests/krb5/alias_tests.py
3002
@@ -28,7 +28,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest
3003
 from samba.tests.krb5.rfc4120_constants import (
3004
     AES256_CTS_HMAC_SHA1_96,
3005
     ARCFOUR_HMAC_MD5,
3006
-    KDC_ERR_CLIENT_NAME_MISMATCH,
3007
+    KDC_ERR_TGT_REVOKED,
3008
     NT_PRINCIPAL,
3009
 )
3010
 
3011
@@ -168,7 +168,7 @@ class AliasTests(KDCBaseTest):
3012
                                              ctype=None)
3013
             return [padata], req_body
3014
 
3015
-        expected_error_mode = KDC_ERR_CLIENT_NAME_MISMATCH
3016
+        expected_error_mode = KDC_ERR_TGT_REVOKED
3017
 
3018
         # Make a request using S4U2Self. The request should fail.
3019
         kdc_exchange_dict = self.tgs_exchange_dict(
3020
@@ -184,7 +184,8 @@ class AliasTests(KDCBaseTest):
3021
             tgt=tgt,
3022
             authenticator_subkey=authenticator_subkey,
3023
             kdc_options='0',
3024
-            expect_pac=True)
3025
+            expect_pac=True,
3026
+            expect_edata=False)
3027
 
3028
         rep = self._generic_kdc_exchange(kdc_exchange_dict,
3029
                                          cname=None,
3030
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
3031
index 0578969ba69..7ea15f0fbab 100755
3032
--- python/samba/tests/krb5/kdc_tgs_tests.py
3033
+++ python/samba/tests/krb5/kdc_tgs_tests.py
3034
@@ -23,7 +23,7 @@ import os
3035
 import ldb
3036
 
3037
 
3038
-from samba import dsdb, ntstatus
3039
+from samba import dsdb
3040
 
3041
 from samba.dcerpc import krb5pac, security
3042
 
3043
@@ -38,8 +38,6 @@ from samba.tests.krb5.rfc4120_constants import (
3044
     KRB_ERROR,
3045
     KRB_TGS_REP,
3046
     KDC_ERR_BADMATCH,
3047
-    KDC_ERR_BADOPTION,
3048
-    KDC_ERR_CLIENT_NAME_MISMATCH,
3049
     KDC_ERR_GENERIC,
3050
     KDC_ERR_MODIFIED,
3051
     KDC_ERR_POLICY,
3052
@@ -262,7 +260,7 @@ class KdcTgsTests(KDCBaseTest):
3053
         authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
3054
 
3055
         if expect_error:
3056
-            expected_error_mode = KDC_ERR_BADOPTION
3057
+            expected_error_mode = KDC_ERR_TGT_REVOKED
3058
             check_error_fn = self.generic_check_kdc_error
3059
             check_rep_fn = None
3060
         else:
3061
@@ -288,7 +286,8 @@ class KdcTgsTests(KDCBaseTest):
3062
             authenticator_subkey=authenticator_subkey,
3063
             kdc_options=kdc_options,
3064
             pac_request=pac_request,
3065
-            expect_pac=expect_pac)
3066
+            expect_pac=expect_pac,
3067
+            expect_edata=False)
3068
 
3069
         rep = self._generic_kdc_exchange(kdc_exchange_dict,
3070
                                          cname=cname,
3071
@@ -516,8 +515,7 @@ class KdcTgsTests(KDCBaseTest):
3072
         creds = self._get_creds()
3073
         tgt = self._get_tgt(creds, remove_requester_sid=True)
3074
 
3075
-        self._run_tgs(tgt, expected_error=0, expect_pac=True,
3076
-                      expect_requester_sid=False)  # Note: not expected
3077
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3078
 
3079
     def test_tgs_req_no_pac_attrs(self):
3080
         creds = self._get_creds()
3081
@@ -531,11 +529,7 @@ class KdcTgsTests(KDCBaseTest):
3082
                                 revealed_to_rodc=True)
3083
         tgt = self._get_tgt(creds, from_rodc=True, remove_requester_sid=True)
3084
 
3085
-        samdb = self.get_samdb()
3086
-        sid = self.get_objectSid(samdb, creds.get_dn())
3087
-
3088
-        self._run_tgs(tgt, expected_error=0, expect_pac=True,
3089
-                      expect_requester_sid=True, expected_sid=sid)
3090
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3091
 
3092
     def test_tgs_req_from_rodc_no_pac_attrs(self):
3093
         creds = self._get_creds(replication_allowed=True,
3094
@@ -548,101 +542,99 @@ class KdcTgsTests(KDCBaseTest):
3095
     def test_tgs_no_pac(self):
3096
         creds = self._get_creds()
3097
         tgt = self._get_tgt(creds, remove_pac=True)
3098
-        self._run_tgs(tgt, expected_error=KDC_ERR_BADOPTION)
3099
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3100
 
3101
     def test_renew_no_pac(self):
3102
         creds = self._get_creds()
3103
         tgt = self._get_tgt(creds, renewable=True, remove_pac=True)
3104
-        self._renew_tgt(tgt, expected_error=KDC_ERR_BADOPTION)
3105
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3106
 
3107
     def test_validate_no_pac(self):
3108
         creds = self._get_creds()
3109
         tgt = self._get_tgt(creds, invalid=True, remove_pac=True)
3110
-        self._validate_tgt(tgt, expected_error=KDC_ERR_BADOPTION)
3111
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3112
 
3113
     def test_s4u2self_no_pac(self):
3114
         creds = self._get_creds()
3115
         tgt = self._get_tgt(creds, remove_pac=True)
3116
         self._s4u2self(tgt, creds,
3117
-                       expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION),
3118
-                       expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER,
3119
-                       expect_edata=True)
3120
+                       expected_error=KDC_ERR_TGT_REVOKED,
3121
+                       expect_edata=False)
3122
 
3123
     def test_user2user_no_pac(self):
3124
         creds = self._get_creds()
3125
         tgt = self._get_tgt(creds, remove_pac=True)
3126
-        self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION)
3127
+        self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
3128
 
3129
     # Test making a request with authdata and without a PAC.
3130
     def test_tgs_authdata_no_pac(self):
3131
         creds = self._get_creds()
3132
         tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True)
3133
-        self._run_tgs(tgt, expected_error=KDC_ERR_BADOPTION)
3134
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3135
 
3136
     def test_renew_authdata_no_pac(self):
3137
         creds = self._get_creds()
3138
         tgt = self._get_tgt(creds, renewable=True, remove_pac=True,
3139
                             allow_empty_authdata=True)
3140
-        self._renew_tgt(tgt, expected_error=KDC_ERR_BADOPTION)
3141
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3142
 
3143
     def test_validate_authdata_no_pac(self):
3144
         creds = self._get_creds()
3145
         tgt = self._get_tgt(creds, invalid=True, remove_pac=True,
3146
                             allow_empty_authdata=True)
3147
-        self._validate_tgt(tgt, expected_error=KDC_ERR_BADOPTION)
3148
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3149
 
3150
     def test_s4u2self_authdata_no_pac(self):
3151
         creds = self._get_creds()
3152
         tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True)
3153
         self._s4u2self(tgt, creds,
3154
-                       expected_error=(KDC_ERR_GENERIC, KDC_ERR_BADOPTION),
3155
-                       expected_status=ntstatus.NT_STATUS_INVALID_PARAMETER,
3156
-                       expect_edata=True)
3157
+                       expected_error=KDC_ERR_TGT_REVOKED,
3158
+                       expect_edata=False)
3159
 
3160
     def test_user2user_authdata_no_pac(self):
3161
         creds = self._get_creds()
3162
         tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True)
3163
-        self._user2user(tgt, creds, expected_error=KDC_ERR_BADOPTION)
3164
+        self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
3165
 
3166
     # Test changing the SID in the PAC to that of another account.
3167
     def test_tgs_sid_mismatch_existing(self):
3168
         creds = self._get_creds()
3169
         existing_rid = self._get_existing_rid()
3170
         tgt = self._get_tgt(creds, new_rid=existing_rid)
3171
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3172
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3173
 
3174
     def test_renew_sid_mismatch_existing(self):
3175
         creds = self._get_creds()
3176
         existing_rid = self._get_existing_rid()
3177
         tgt = self._get_tgt(creds, renewable=True, new_rid=existing_rid)
3178
-        self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3179
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3180
 
3181
     def test_validate_sid_mismatch_existing(self):
3182
         creds = self._get_creds()
3183
         existing_rid = self._get_existing_rid()
3184
         tgt = self._get_tgt(creds, invalid=True, new_rid=existing_rid)
3185
-        self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3186
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3187
 
3188
     def test_s4u2self_sid_mismatch_existing(self):
3189
         creds = self._get_creds()
3190
         existing_rid = self._get_existing_rid()
3191
         tgt = self._get_tgt(creds, new_rid=existing_rid)
3192
         self._s4u2self(tgt, creds,
3193
-                       expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3194
+                       expected_error=KDC_ERR_TGT_REVOKED)
3195
 
3196
     def test_user2user_sid_mismatch_existing(self):
3197
         creds = self._get_creds()
3198
         existing_rid = self._get_existing_rid()
3199
         tgt = self._get_tgt(creds, new_rid=existing_rid)
3200
         self._user2user(tgt, creds,
3201
-                        expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3202
+                        expected_error=KDC_ERR_TGT_REVOKED)
3203
 
3204
     def test_requester_sid_mismatch_existing(self):
3205
         creds = self._get_creds()
3206
         existing_rid = self._get_existing_rid()
3207
         tgt = self._get_tgt(creds, new_rid=existing_rid,
3208
                             can_modify_logon_info=False)
3209
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3210
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3211
 
3212
     def test_logon_info_sid_mismatch_existing(self):
3213
         creds = self._get_creds()
3214
@@ -656,49 +648,49 @@ class KdcTgsTests(KDCBaseTest):
3215
         existing_rid = self._get_existing_rid()
3216
         tgt = self._get_tgt(creds, new_rid=existing_rid,
3217
                             remove_requester_sid=True)
3218
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3219
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3220
 
3221
     # Test changing the SID in the PAC to a non-existent one.
3222
     def test_tgs_sid_mismatch_nonexisting(self):
3223
         creds = self._get_creds()
3224
         nonexistent_rid = self._get_non_existent_rid()
3225
         tgt = self._get_tgt(creds, new_rid=nonexistent_rid)
3226
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3227
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3228
 
3229
     def test_renew_sid_mismatch_nonexisting(self):
3230
         creds = self._get_creds()
3231
         nonexistent_rid = self._get_non_existent_rid()
3232
         tgt = self._get_tgt(creds, renewable=True,
3233
                             new_rid=nonexistent_rid)
3234
-        self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3235
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3236
 
3237
     def test_validate_sid_mismatch_nonexisting(self):
3238
         creds = self._get_creds()
3239
         nonexistent_rid = self._get_non_existent_rid()
3240
         tgt = self._get_tgt(creds, invalid=True,
3241
                             new_rid=nonexistent_rid)
3242
-        self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3243
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3244
 
3245
     def test_s4u2self_sid_mismatch_nonexisting(self):
3246
         creds = self._get_creds()
3247
         nonexistent_rid = self._get_non_existent_rid()
3248
         tgt = self._get_tgt(creds, new_rid=nonexistent_rid)
3249
         self._s4u2self(tgt, creds,
3250
-                       expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3251
+                       expected_error=KDC_ERR_TGT_REVOKED)
3252
 
3253
     def test_user2user_sid_mismatch_nonexisting(self):
3254
         creds = self._get_creds()
3255
         nonexistent_rid = self._get_non_existent_rid()
3256
         tgt = self._get_tgt(creds, new_rid=nonexistent_rid)
3257
         self._user2user(tgt, creds,
3258
-                        expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3259
+                        expected_error=KDC_ERR_TGT_REVOKED)
3260
 
3261
     def test_requester_sid_mismatch_nonexisting(self):
3262
         creds = self._get_creds()
3263
         nonexistent_rid = self._get_non_existent_rid()
3264
         tgt = self._get_tgt(creds, new_rid=nonexistent_rid,
3265
                             can_modify_logon_info=False)
3266
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3267
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3268
 
3269
     def test_logon_info_sid_mismatch_nonexisting(self):
3270
         creds = self._get_creds()
3271
@@ -712,7 +704,7 @@ class KdcTgsTests(KDCBaseTest):
3272
         nonexistent_rid = self._get_non_existent_rid()
3273
         tgt = self._get_tgt(creds, new_rid=nonexistent_rid,
3274
                             remove_requester_sid=True)
3275
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3276
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3277
 
3278
     # Test with an RODC-issued ticket where the client is revealed to the RODC.
3279
     def test_tgs_rodc_revealed(self):
3280
@@ -753,7 +745,7 @@ class KdcTgsTests(KDCBaseTest):
3281
         existing_rid = self._get_existing_rid(replication_allowed=True,
3282
                                               revealed_to_rodc=True)
3283
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid)
3284
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3285
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3286
 
3287
     def test_renew_rodc_sid_mismatch_existing(self):
3288
         creds = self._get_creds(replication_allowed=True,
3289
@@ -762,7 +754,7 @@ class KdcTgsTests(KDCBaseTest):
3290
                                               revealed_to_rodc=True)
3291
         tgt = self._get_tgt(creds, renewable=True, from_rodc=True,
3292
                             new_rid=existing_rid)
3293
-        self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3294
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3295
 
3296
     def test_validate_rodc_sid_mismatch_existing(self):
3297
         creds = self._get_creds(replication_allowed=True,
3298
@@ -771,7 +763,7 @@ class KdcTgsTests(KDCBaseTest):
3299
                                        revealed_to_rodc=True)
3300
         tgt = self._get_tgt(creds, invalid=True, from_rodc=True,
3301
                             new_rid=existing_rid)
3302
-        self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3303
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3304
 
3305
     def test_s4u2self_rodc_sid_mismatch_existing(self):
3306
         creds = self._get_creds(replication_allowed=True,
3307
@@ -779,7 +771,7 @@ class KdcTgsTests(KDCBaseTest):
3308
         existing_rid = self._get_existing_rid(replication_allowed=True,
3309
                                               revealed_to_rodc=True)
3310
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid)
3311
-        self._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3312
+        self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
3313
 
3314
     def test_user2user_rodc_sid_mismatch_existing(self):
3315
         creds = self._get_creds(replication_allowed=True,
3316
@@ -788,7 +780,7 @@ class KdcTgsTests(KDCBaseTest):
3317
                                               revealed_to_rodc=True)
3318
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid)
3319
         self._user2user(tgt, creds,
3320
-                        expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3321
+                        expected_error=KDC_ERR_TGT_REVOKED)
3322
 
3323
     def test_tgs_rodc_requester_sid_mismatch_existing(self):
3324
         creds = self._get_creds(replication_allowed=True,
3325
@@ -797,7 +789,7 @@ class KdcTgsTests(KDCBaseTest):
3326
                                               revealed_to_rodc=True)
3327
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid,
3328
                             can_modify_logon_info=False)
3329
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3330
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3331
 
3332
     def test_tgs_rodc_logon_info_sid_mismatch_existing(self):
3333
         creds = self._get_creds(replication_allowed=True,
3334
@@ -815,7 +807,7 @@ class KdcTgsTests(KDCBaseTest):
3335
                                               revealed_to_rodc=True)
3336
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid,
3337
                             remove_requester_sid=True)
3338
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3339
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3340
 
3341
     # Test with an RODC-issued ticket where the SID in the PAC is changed to a
3342
     # non-existent one.
3343
@@ -824,7 +816,7 @@ class KdcTgsTests(KDCBaseTest):
3344
                                 revealed_to_rodc=True)
3345
         nonexistent_rid = self._get_non_existent_rid()
3346
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid)
3347
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3348
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3349
 
3350
     def test_renew_rodc_sid_mismatch_nonexisting(self):
3351
         creds = self._get_creds(replication_allowed=True,
3352
@@ -832,7 +824,7 @@ class KdcTgsTests(KDCBaseTest):
3353
         nonexistent_rid = self._get_non_existent_rid()
3354
         tgt = self._get_tgt(creds, renewable=True, from_rodc=True,
3355
                             new_rid=nonexistent_rid)
3356
-        self._renew_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3357
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3358
 
3359
     def test_validate_rodc_sid_mismatch_nonexisting(self):
3360
         creds = self._get_creds(replication_allowed=True,
3361
@@ -840,14 +832,14 @@ class KdcTgsTests(KDCBaseTest):
3362
         nonexistent_rid = self._get_non_existent_rid()
3363
         tgt = self._get_tgt(creds, invalid=True, from_rodc=True,
3364
                             new_rid=nonexistent_rid)
3365
-        self._validate_tgt(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3366
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3367
 
3368
     def test_s4u2self_rodc_sid_mismatch_nonexisting(self):
3369
         creds = self._get_creds(replication_allowed=True,
3370
                                 revealed_to_rodc=True)
3371
         nonexistent_rid = self._get_non_existent_rid()
3372
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid)
3373
-        self._s4u2self(tgt, creds, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3374
+        self._s4u2self(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
3375
 
3376
     def test_user2user_rodc_sid_mismatch_nonexisting(self):
3377
         creds = self._get_creds(replication_allowed=True,
3378
@@ -855,7 +847,7 @@ class KdcTgsTests(KDCBaseTest):
3379
         nonexistent_rid = self._get_non_existent_rid()
3380
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid)
3381
         self._user2user(tgt, creds,
3382
-                        expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3383
+                        expected_error=KDC_ERR_TGT_REVOKED)
3384
 
3385
     def test_tgs_rodc_requester_sid_mismatch_nonexisting(self):
3386
         creds = self._get_creds(replication_allowed=True,
3387
@@ -863,7 +855,7 @@ class KdcTgsTests(KDCBaseTest):
3388
         nonexistent_rid = self._get_non_existent_rid()
3389
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid,
3390
                             can_modify_logon_info=False)
3391
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3392
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3393
 
3394
     def test_tgs_rodc_logon_info_sid_mismatch_nonexisting(self):
3395
         creds = self._get_creds(replication_allowed=True,
3396
@@ -879,7 +871,7 @@ class KdcTgsTests(KDCBaseTest):
3397
         nonexistent_rid = self._get_non_existent_rid()
3398
         tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid,
3399
                             remove_requester_sid=True)
3400
-        self._run_tgs(tgt, expected_error=KDC_ERR_CLIENT_NAME_MISMATCH)
3401
+        self._run_tgs(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3402
 
3403
     # Test with an RODC-issued ticket where the client is not revealed to the
3404
     # RODC.
3405
@@ -1111,8 +1103,7 @@ class KdcTgsTests(KDCBaseTest):
3406
                                           names=[user_name])
3407
 
3408
         self._user2user(tgt, creds, sname=sname,
3409
-                        expected_error=(KDC_ERR_BADMATCH,
3410
-                                        KDC_ERR_BADOPTION))
3411
+                        expected_error=KDC_ERR_BADMATCH)
3412
 
3413
     def test_user2user_other_sname(self):
3414
         other_name = self.get_new_username()
3415
@@ -1134,8 +1125,7 @@ class KdcTgsTests(KDCBaseTest):
3416
         sname = self.get_krbtgt_sname()
3417
 
3418
         self._user2user(tgt, creds, sname=sname,
3419
-                        expected_error=(KDC_ERR_BADMATCH,
3420
-                                        KDC_ERR_BADOPTION))
3421
+                        expected_error=KDC_ERR_BADMATCH)
3422
 
3423
     def test_user2user_wrong_srealm(self):
3424
         creds = self._get_creds()
3425
@@ -1206,7 +1196,9 @@ class KdcTgsTests(KDCBaseTest):
3426
 
3427
         tgt = self._modify_tgt(tgt, cname=cname)
3428
 
3429
-        self._user2user(tgt, creds, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN)
3430
+        self._user2user(tgt, creds,
3431
+                        expected_error=(KDC_ERR_TGT_REVOKED,
3432
+                                        KDC_ERR_C_PRINCIPAL_UNKNOWN))
3433
 
3434
     def test_user2user_non_existent_sname(self):
3435
         creds = self._get_creds()
3436
@@ -1522,8 +1514,7 @@ class KdcTgsTests(KDCBaseTest):
3437
         tgt = self._modify_tgt(tgt, renewable=True,
3438
                                remove_requester_sid=True)
3439
 
3440
-        self._renew_tgt(tgt, expected_error=0, expect_pac=True,
3441
-                        expect_requester_sid=False)  # Note: not expected
3442
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3443
 
3444
     def test_tgs_requester_sid_missing_rodc_renew(self):
3445
         creds = self._get_creds(replication_allowed=True,
3446
@@ -1539,9 +1530,7 @@ class KdcTgsTests(KDCBaseTest):
3447
         tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True,
3448
                                remove_requester_sid=True)
3449
 
3450
-        self._renew_tgt(tgt, expected_error=0, expect_pac=True,
3451
-                        expected_sid=sid,
3452
-                        expect_requester_sid=True)
3453
+        self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
3454
 
3455
     def test_tgs_pac_request_none(self):
3456
         creds = self._get_creds()
3457
@@ -1655,10 +1644,10 @@ class KdcTgsTests(KDCBaseTest):
3458
         creds = self._get_creds()
3459
         tgt = self.get_tgt(creds, pac_request=False, expect_pac=None)
3460
 
3461
-        ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=False)
3462
+        ticket = self._s4u2self(tgt, creds, expected_error=0, expect_pac=True)
3463
 
3464
-        pac = self.get_ticket_pac(ticket, expect_pac=False)
3465
-        self.assertIsNone(pac)
3466
+        pac = self.get_ticket_pac(ticket)
3467
+        self.assertIsNotNone(pac)
3468
 
3469
     def test_s4u2self_pac_request_true(self):
3470
         creds = self._get_creds()
3471
@@ -1753,10 +1742,10 @@ class KdcTgsTests(KDCBaseTest):
3472
         tgt = self.get_tgt(creds, pac_request=False, expect_pac=None)
3473
         tgt = self._modify_tgt(tgt, from_rodc=True)
3474
 
3475
-        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False)
3476
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
3477
 
3478
         pac = self.get_ticket_pac(ticket, expect_pac=False)
3479
-        self.assertIsNone(pac)
3480
+        self.assertIsNotNone(pac)
3481
 
3482
     def test_tgs_rodc_pac_request_true(self):
3483
         creds = self._get_creds(replication_allowed=True,
3484
@@ -1784,7 +1773,8 @@ class KdcTgsTests(KDCBaseTest):
3485
                                                    'sAMAccountName')
3486
         samdb.modify(msg)
3487
 
3488
-        self._run_tgs(tgt, expected_error=KDC_ERR_C_PRINCIPAL_UNKNOWN)
3489
+        self._run_tgs(tgt, expected_error=(KDC_ERR_TGT_REVOKED,
3490
+                                           KDC_ERR_C_PRINCIPAL_UNKNOWN))
3491
 
3492
     def _modify_renewable(self, enc_part):
3493
         # Set the renewable flag.
3494
diff --git python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py
3495
index 0aa3309b814..e6b90d3e16a 100755
3496
--- python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py
3497
+++ python/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py
3498
@@ -32,6 +32,7 @@ from samba.tests.krb5.rfc4120_constants import (
3499
     NT_PRINCIPAL,
3500
     NT_SRV_INST,
3501
     KDC_ERR_C_PRINCIPAL_UNKNOWN,
3502
+    KDC_ERR_TGT_REVOKED,
3503
 )
3504
 
3505
 global_asn1_print = False
3506
@@ -322,21 +323,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest):
3507
 
3508
         (rep, enc_part) = self.tgs_req(
3509
             cname, sname, uc.get_realm(), ticket, key, etype,
3510
-            service_creds=mc, expect_pac=False)
3511
-        self.check_tgs_reply(rep)
3512
-
3513
-        # Check the contents of the service ticket
3514
-        ticket = rep['ticket']
3515
-        enc_part = self.decode_service_ticket(mc, ticket)
3516
-        #
3517
-        # We get an empty authorization-data element in the ticket.
3518
-        # i.e. no PAC
3519
-        self.assertEqual([], enc_part['authorization-data'])
3520
-        # check the crealm and cname
3521
-        cname = enc_part['cname']
3522
-        self.assertEqual(NT_PRINCIPAL, cname['name-type'])
3523
-        self.assertEqual(alt_name.encode('UTF8'), cname['name-string'][0])
3524
-        self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm'])
3525
+            service_creds=mc, expect_pac=False,
3526
+            expect_edata=False,
3527
+            expected_error_mode=KDC_ERR_TGT_REVOKED)
3528
+        self.check_error_rep(rep, KDC_ERR_TGT_REVOKED)
3529
 
3530
     def test_nt_principal_step_4_b(self):
3531
         ''' Step 4, pre-authentication
3532
@@ -703,21 +693,10 @@ class MS_Kile_Client_Principal_Lookup_Tests(KDCBaseTest):
3533
 
3534
         (rep, enc_part) = self.tgs_req(
3535
             cname, sname, uc.get_realm(), ticket, key, etype,
3536
-            service_creds=mc, expect_pac=False)
3537
-        self.check_tgs_reply(rep)
3538
-
3539
-        # Check the contents of the service ticket
3540
-        ticket = rep['ticket']
3541
-        enc_part = self.decode_service_ticket(mc, ticket)
3542
-        #
3543
-        # We get an empty authorization-data element in the ticket.
3544
-        # i.e. no PAC
3545
-        self.assertEqual([], enc_part['authorization-data'])
3546
-        # check the crealm and cname
3547
-        cname = enc_part['cname']
3548
-        self.assertEqual(NT_ENTERPRISE_PRINCIPAL, cname['name-type'])
3549
-        self.assertEqual(ename.encode('UTF8'), cname['name-string'][0])
3550
-        self.assertEqual(realm.upper().encode('UTF8'), enc_part['crealm'])
3551
+            service_creds=mc, expect_pac=False,
3552
+            expect_edata=False,
3553
+            expected_error_mode=KDC_ERR_TGT_REVOKED)
3554
+        self.check_error_rep(rep, KDC_ERR_TGT_REVOKED)
3555
 
3556
     def test_nt_enterprise_principal_step_6_b(self):
3557
         ''' Step 4, pre-authentication
3558
diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py
3559
index a80a7b3427e..5f37525f393 100755
3560
--- python/samba/tests/krb5/s4u_tests.py
3561
+++ python/samba/tests/krb5/s4u_tests.py
3562
@@ -42,6 +42,7 @@ from samba.tests.krb5.rfc4120_constants import (
3563
     KDC_ERR_INAPP_CKSUM,
3564
     KDC_ERR_MODIFIED,
3565
     KDC_ERR_SUMTYPE_NOSUPP,
3566
+    KDC_ERR_TGT_REVOKED,
3567
     KU_PA_ENC_TIMESTAMP,
3568
     KU_AS_REP_ENC_PART,
3569
     KU_TGS_REP_ENC_PART_SUB_KEY,
3570
@@ -278,6 +279,8 @@ class S4UKerberosTests(KDCBaseTest):
3571
         etypes = kdc_dict.pop('etypes', (AES256_CTS_HMAC_SHA1_96,
3572
                                          ARCFOUR_HMAC_MD5))
3573
 
3574
+        expect_edata = kdc_dict.pop('expect_edata', None)
3575
+
3576
         def generate_s4u2self_padata(_kdc_exchange_dict,
3577
                                      _callback_dict,
3578
                                      req_body):
3579
@@ -309,7 +312,8 @@ class S4UKerberosTests(KDCBaseTest):
3580
             tgt=service_tgt,
3581
             authenticator_subkey=authenticator_subkey,
3582
             kdc_options=str(kdc_options),
3583
-            expect_claims=False)
3584
+            expect_claims=False,
3585
+            expect_edata=expect_edata)
3586
 
3587
         self._generic_kdc_exchange(kdc_exchange_dict,
3588
                                    cname=None,
3589
@@ -343,15 +347,14 @@ class S4UKerberosTests(KDCBaseTest):
3590
 
3591
         self._run_s4u2self_test(
3592
             {
3593
-                'expected_error_mode': (KDC_ERR_GENERIC,
3594
-                                        KDC_ERR_BADOPTION),
3595
-                'expected_status': ntstatus.NT_STATUS_INVALID_PARAMETER,
3596
+                'expected_error_mode': KDC_ERR_TGT_REVOKED,
3597
                 'client_opts': {
3598
                     'not_delegated': False
3599
                 },
3600
                 'kdc_options': 'forwardable',
3601
                 'modify_service_tgt_fn': forwardable_no_pac,
3602
-                'expected_flags': 'forwardable'
3603
+                'expected_flags': 'forwardable',
3604
+                'expect_edata': False
3605
             })
3606
 
3607
     # Test performing an S4U2Self operation without requesting a forwardable
3608
@@ -674,8 +677,8 @@ class S4UKerberosTests(KDCBaseTest):
3609
         # contain a PAC.
3610
         self._run_delegation_test(
3611
             {
3612
-                'expected_error_mode': (KDC_ERR_BADOPTION,
3613
-                                        KDC_ERR_MODIFIED),
3614
+                'expected_error_mode': (KDC_ERR_MODIFIED,
3615
+                                        KDC_ERR_TGT_REVOKED),
3616
                 'allow_delegation': True,
3617
                 'modify_client_tkt_fn': self.remove_ticket_pac,
3618
                 'expect_edata': False
3619
@@ -686,9 +689,10 @@ class S4UKerberosTests(KDCBaseTest):
3620
         # PAC.
3621
         self._run_delegation_test(
3622
             {
3623
-                'expected_error_mode': 0,
3624
+                'expected_error_mode': KDC_ERR_TGT_REVOKED,
3625
                 'allow_delegation': True,
3626
-                'modify_service_tgt_fn': self.remove_ticket_pac
3627
+                'modify_service_tgt_fn': self.remove_ticket_pac,
3628
+                'expect_edata': False
3629
             })
3630
 
3631
     def test_constrained_delegation_no_client_pac_no_auth_data_required(self):
3632
@@ -696,8 +700,8 @@ class S4UKerberosTests(KDCBaseTest):
3633
         # contain a PAC.
3634
         self._run_delegation_test(
3635
             {
3636
-                'expected_error_mode': (KDC_ERR_BADOPTION,
3637
-                                        KDC_ERR_MODIFIED),
3638
+                'expected_error_mode': (KDC_ERR_MODIFIED,
3639
+                                        KDC_ERR_BADOPTION),
3640
                 'allow_delegation': True,
3641
                 'modify_client_tkt_fn': self.remove_ticket_pac,
3642
                 'expect_edata': False,
3643
@@ -711,13 +715,14 @@ class S4UKerberosTests(KDCBaseTest):
3644
         # PAC.
3645
         self._run_delegation_test(
3646
             {
3647
-                'expected_error_mode': (KDC_ERR_BADOPTION,
3648
-                                        KDC_ERR_MODIFIED),
3649
+                'expected_error_mode': KDC_ERR_TGT_REVOKED,
3650
                 'allow_delegation': True,
3651
                 'modify_service_tgt_fn': self.remove_ticket_pac,
3652
                 'service2_opts': {
3653
                     'no_auth_data_required': True
3654
-                }
3655
+                },
3656
+                'expect_pac': False,
3657
+                'expect_edata': False
3658
             })
3659
 
3660
     def test_constrained_delegation_non_forwardable(self):
3661
@@ -812,12 +817,11 @@ class S4UKerberosTests(KDCBaseTest):
3662
         # PAC.
3663
         self._run_delegation_test(
3664
             {
3665
-                'expected_error_mode': KDC_ERR_BADOPTION,
3666
-                'expected_status':
3667
-                    ntstatus.NT_STATUS_NOT_FOUND,
3668
+                'expected_error_mode': KDC_ERR_TGT_REVOKED,
3669
                 'allow_rbcd': True,
3670
                 'pac_options': '0001',  # supports RBCD
3671
-                'modify_service_tgt_fn': self.remove_ticket_pac
3672
+                'modify_service_tgt_fn': self.remove_ticket_pac,
3673
+                'expect_edata': False
3674
             })
3675
 
3676
     def test_rbcd_no_client_pac_no_auth_data_required_a(self):
3677
@@ -858,15 +862,14 @@ class S4UKerberosTests(KDCBaseTest):
3678
         # PAC.
3679
         self._run_delegation_test(
3680
             {
3681
-                'expected_error_mode': KDC_ERR_BADOPTION,
3682
-                'expected_status':
3683
-                    ntstatus.NT_STATUS_NOT_FOUND,
3684
+                'expected_error_mode': KDC_ERR_TGT_REVOKED,
3685
                 'allow_rbcd': True,
3686
                 'pac_options': '0001',  # supports RBCD
3687
                 'modify_service_tgt_fn': self.remove_ticket_pac,
3688
                 'service2_opts': {
3689
                     'no_auth_data_required': True
3690
-                }
3691
+                },
3692
+                'expect_edata': False
3693
             })
3694
 
3695
     def test_rbcd_non_forwardable(self):
3696
@@ -941,8 +944,8 @@ class S4UKerberosTests(KDCBaseTest):
3697
         for checksum in self.pac_checksum_types:
3698
             with self.subTest(checksum=checksum):
3699
                 if checksum == krb5pac.PAC_TYPE_TICKET_CHECKSUM:
3700
-                    expected_error_mode = (KDC_ERR_BADOPTION,
3701
-                                           KDC_ERR_MODIFIED)
3702
+                    expected_error_mode = (KDC_ERR_MODIFIED,
3703
+                                           KDC_ERR_BADOPTION)
3704
                 else:
3705
                     expected_error_mode = KDC_ERR_GENERIC
3706
 
3707
@@ -1061,8 +1064,7 @@ class S4UKerberosTests(KDCBaseTest):
3708
         for checksum in self.pac_checksum_types:
3709
             with self.subTest(checksum=checksum):
3710
                 if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM:
3711
-                    expected_error_mode = (KDC_ERR_MODIFIED,
3712
-                                           KDC_ERR_BAD_INTEGRITY)
3713
+                    expected_error_mode = KDC_ERR_MODIFIED
3714
                     expected_status = ntstatus.NT_STATUS_WRONG_PASSWORD
3715
                 else:
3716
                     expected_error_mode = 0
3717
@@ -1162,8 +1164,7 @@ class S4UKerberosTests(KDCBaseTest):
3718
                 with self.subTest(checksum=checksum, ctype=ctype):
3719
                     if checksum == krb5pac.PAC_TYPE_SRV_CHECKSUM:
3720
                         if ctype == Cksumtype.SHA1:
3721
-                            expected_error_mode = (KDC_ERR_SUMTYPE_NOSUPP,
3722
-                                                   KDC_ERR_BAD_INTEGRITY)
3723
+                            expected_error_mode = KDC_ERR_SUMTYPE_NOSUPP
3724
                             expected_status = ntstatus.NT_STATUS_LOGON_FAILURE
3725
                         else:
3726
                             expected_error_mode = KDC_ERR_GENERIC
3727
diff --git python/samba/tests/krb5/test_rpc.py python/samba/tests/krb5/test_rpc.py
3728
index 2d483986e83..5a3c7339cea 100755
3729
--- python/samba/tests/krb5/test_rpc.py
3730
+++ python/samba/tests/krb5/test_rpc.py
3731
@@ -24,7 +24,10 @@ import ldb
3732
 
3733
 from samba import NTSTATUSError, credentials
3734
 from samba.dcerpc import lsa
3735
-from samba.ntstatus import NT_STATUS_NO_IMPERSONATION_TOKEN
3736
+from samba.ntstatus import (
3737
+    NT_STATUS_ACCESS_DENIED,
3738
+    NT_STATUS_NO_IMPERSONATION_TOKEN
3739
+)
3740
 
3741
 from samba.tests.krb5.kdc_base_test import KDCBaseTest
3742
 
3743
@@ -103,7 +106,8 @@ class RpcTests(KDCBaseTest):
3744
                 self.fail()
3745
 
3746
             enum, _ = e.args
3747
-            self.assertEqual(NT_STATUS_NO_IMPERSONATION_TOKEN, enum)
3748
+            self.assertIn(enum, {NT_STATUS_ACCESS_DENIED,
3749
+                                 NT_STATUS_NO_IMPERSONATION_TOKEN})
3750
             return
3751
 
3752
         (account_name, _) = conn.GetUserName(None, None, None)
3753
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
3754
index 7eba899966e..1b7e159c381 100644
3755
--- selftest/knownfail_heimdal_kdc
3756
+++ selftest/knownfail_heimdal_kdc
3757
@@ -233,16 +233,21 @@
3758
 # S4U tests
3759
 #
3760
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_rbcd_old_checksum
3761
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac(?!_no_auth_data_required)
3762
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac\(.*\)$
3763
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac_no_auth_data_required
3764
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_existing_delegation_info
3765
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_missing_client_checksum
3766
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_a
3767
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_b
3768
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac
3769
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac_no_auth_data_required
3770
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_client_checksum
3771
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum
3772
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum
3773
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
3774
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
3775
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_pac
3776
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
3777
 #
3778
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
3779
@@ -259,3 +264,62 @@
3780
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_not_revealed
3781
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed
3782
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed
3783
+#
3784
+# Alias tests
3785
+#
3786
+^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete
3787
+^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_rename
3788
+^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_delete
3789
+^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_rename
3790
+#
3791
+# KDC TGS tests
3792
+#
3793
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
3794
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
3795
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac
3796
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required
3797
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required
3798
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
3799
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
3800
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
3801
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
3802
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing
3803
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting
3804
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing
3805
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting
3806
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac
3807
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac
3808
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
3809
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing
3810
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting
3811
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing
3812
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting
3813
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac
3814
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
3815
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
3816
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
3817
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
3818
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
3819
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
3820
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
3821
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false
3822
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing
3823
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting
3824
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing
3825
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting
3826
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing
3827
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting
3828
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac
3829
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac
3830
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing
3831
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting
3832
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing
3833
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting
3834
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname
3835
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt
3836
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
3837
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac
3838
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
3839
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
3840
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing
3841
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting
3842
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
3843
index 8cd36fe2d96..cc12499bb50 100644
3844
--- selftest/knownfail_mit_kdc
3845
+++ selftest/knownfail_mit_kdc
3846
@@ -390,6 +390,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
3847
 #
3848
 # KDC TGT tests
3849
 #
3850
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
3851
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
3852
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
3853
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
3854
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied
3855
@@ -401,6 +403,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
3856
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
3857
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
3858
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
3859
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing
3860
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting
3861
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac
3862
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac
3863
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req
3864
@@ -418,6 +422,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
3865
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac
3866
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
3867
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename
3868
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
3869
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied
3870
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied
3871
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link
3872
@@ -427,6 +432,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
3873
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_revealed
3874
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing
3875
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting
3876
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing
3877
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting
3878
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac
3879
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac
3880
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname
3881
@@ -462,6 +469,8 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
3882
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
3883
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
3884
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
3885
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing
3886
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting
3887
 #
3888
 # PAC attributes tests
3889
 #
3890
-- 
3891
2.25.1
3892
3893
3894
From ea82822a5c451df50feed15c5da3501df2b5c106 Mon Sep 17 00:00:00 2001
3895
From: Joseph Sutton <josephsutton@catalyst.net.nz>
3896
Date: Wed, 24 Nov 2021 12:04:36 +1300
3897
Subject: [PATCH 28/99] tests/krb5: Remove unnecessary expect_pac arguments
3898
3899
The value of expect_pac is not considered if we are expecting an error.
3900
3901
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
3902
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
3903
(cherry picked from commit 28d501875a98fa2817262eb8ec68bf91528428c2)
3904
---
3905
 python/samba/tests/krb5/kdc_tgs_tests.py | 6 +++---
3906
 1 file changed, 3 insertions(+), 3 deletions(-)
3907
3908
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
3909
index 7ea15f0fbab..6160ef649e8 100755
3910
--- python/samba/tests/krb5/kdc_tgs_tests.py
3911
+++ python/samba/tests/krb5/kdc_tgs_tests.py
3912
@@ -412,7 +412,7 @@ class KdcTgsTests(KDCBaseTest):
3913
         self.assertIsNone(pac)
3914
 
3915
         self._make_tgs_request(client_creds, service_creds, tgt,
3916
-                               expect_pac=False, expect_error=True)
3917
+                               expect_error=True)
3918
 
3919
     def test_remove_pac_client_no_auth_data_required(self):
3920
         client_creds = self.get_cached_creds(
3921
@@ -427,7 +427,7 @@ class KdcTgsTests(KDCBaseTest):
3922
         self.assertIsNone(pac)
3923
 
3924
         self._make_tgs_request(client_creds, service_creds, tgt,
3925
-                               expect_pac=False, expect_error=True)
3926
+                               expect_error=True)
3927
 
3928
     def test_remove_pac(self):
3929
         client_creds = self.get_client_creds()
3930
@@ -440,7 +440,7 @@ class KdcTgsTests(KDCBaseTest):
3931
         self.assertIsNone(pac)
3932
 
3933
         self._make_tgs_request(client_creds, service_creds, tgt,
3934
-                               expect_pac=False, expect_error=True)
3935
+                               expect_error=True)
3936
 
3937
     def test_upn_dns_info_ex_user(self):
3938
         client_creds = self.get_client_creds()
3939
-- 
3940
2.25.1
3941
3942
3943
From eb0ed5f4f6d725c49fda97bc8f7aae89f90bd913 Mon Sep 17 00:00:00 2001
3944
From: Joseph Sutton <josephsutton@catalyst.net.nz>
3945
Date: Tue, 30 Nov 2021 09:26:40 +1300
3946
Subject: [PATCH 29/99] tests/krb5: Add tests for invalid TGTs
3947
3948
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
3949
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
3950
(cherry picked from commit 7574ba9f580fca552b80532a49d00e657fbdf4fd)
3951
3952
[jsutton@samba.org Removed some MIT knownfail changes]
3953
---
3954
 python/samba/tests/krb5/kdc_tgs_tests.py     | 16 ++++++++++++++++
3955
 python/samba/tests/krb5/rfc4120_constants.py |  1 +
3956
 selftest/knownfail_mit_kdc                   |  1 +
3957
 3 files changed, 18 insertions(+)
3958
3959
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
3960
index 6160ef649e8..f5f091610ac 100755
3961
--- python/samba/tests/krb5/kdc_tgs_tests.py
3962
+++ python/samba/tests/krb5/kdc_tgs_tests.py
3963
@@ -44,6 +44,7 @@ from samba.tests.krb5.rfc4120_constants import (
3964
     KDC_ERR_C_PRINCIPAL_UNKNOWN,
3965
     KDC_ERR_S_PRINCIPAL_UNKNOWN,
3966
     KDC_ERR_TGT_REVOKED,
3967
+    KRB_ERR_TKT_NYV,
3968
     KDC_ERR_WRONG_REALM,
3969
     NT_PRINCIPAL,
3970
     NT_SRV_INST,
3971
@@ -511,6 +512,21 @@ class KdcTgsTests(KDCBaseTest):
3972
         tgt = self._get_tgt(creds)
3973
         self._user2user(tgt, creds, expected_error=0)
3974
 
3975
+    def test_tgs_req_invalid(self):
3976
+        creds = self._get_creds()
3977
+        tgt = self._get_tgt(creds, invalid=True)
3978
+        self._run_tgs(tgt, expected_error=KRB_ERR_TKT_NYV)
3979
+
3980
+    def test_s4u2self_req_invalid(self):
3981
+        creds = self._get_creds()
3982
+        tgt = self._get_tgt(creds, invalid=True)
3983
+        self._s4u2self(tgt, creds, expected_error=KRB_ERR_TKT_NYV)
3984
+
3985
+    def test_user2user_req_invalid(self):
3986
+        creds = self._get_creds()
3987
+        tgt = self._get_tgt(creds, invalid=True)
3988
+        self._user2user(tgt, creds, expected_error=KRB_ERR_TKT_NYV)
3989
+
3990
     def test_tgs_req_no_requester_sid(self):
3991
         creds = self._get_creds()
3992
         tgt = self._get_tgt(creds, remove_requester_sid=True)
3993
diff --git python/samba/tests/krb5/rfc4120_constants.py python/samba/tests/krb5/rfc4120_constants.py
3994
index 5251e291fde..a9fdc5735dd 100644
3995
--- python/samba/tests/krb5/rfc4120_constants.py
3996
+++ python/samba/tests/krb5/rfc4120_constants.py
3997
@@ -76,6 +76,7 @@ KDC_ERR_TGT_REVOKED = 20
3998
 KDC_ERR_PREAUTH_FAILED = 24
3999
 KDC_ERR_PREAUTH_REQUIRED = 25
4000
 KDC_ERR_BAD_INTEGRITY = 31
4001
+KRB_ERR_TKT_NYV = 33
4002
 KDC_ERR_NOT_US = 35
4003
 KDC_ERR_BADMATCH = 36
4004
 KDC_ERR_SKEW = 37
4005
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
4006
index cc12499bb50..3aacec00870 100644
4007
--- selftest/knownfail_mit_kdc
4008
+++ selftest/knownfail_mit_kdc
4009
@@ -422,6 +422,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
4010
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac
4011
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
4012
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename
4013
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_invalid
4014
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
4015
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied
4016
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied
4017
-- 
4018
2.25.1
4019
4020
4021
From 645d30ff371fdf3e16cb1fa69f2e93a848d20bdb Mon Sep 17 00:00:00 2001
4022
From: Joseph Sutton <josephsutton@catalyst.net.nz>
4023
Date: Wed, 24 Nov 2021 12:10:45 +1300
4024
Subject: [PATCH 30/99] tests/krb5: Add tests for TGS requests with a non-TGT
4025
4026
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
4027
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
4028
(cherry picked from commit 778029c1dc443b87f4ed4b9d2c613d0e6fc45b0d)
4029
---
4030
 python/samba/tests/krb5/kdc_tgs_tests.py | 51 ++++++++++++++++++++++++
4031
 selftest/knownfail_mit_kdc               |  2 +
4032
 2 files changed, 53 insertions(+)
4033
4034
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
4035
index f5f091610ac..52297c963e8 100755
4036
--- python/samba/tests/krb5/kdc_tgs_tests.py
4037
+++ python/samba/tests/krb5/kdc_tgs_tests.py
4038
@@ -40,6 +40,7 @@ from samba.tests.krb5.rfc4120_constants import (
4039
     KDC_ERR_BADMATCH,
4040
     KDC_ERR_GENERIC,
4041
     KDC_ERR_MODIFIED,
4042
+    KDC_ERR_NOT_US,
4043
     KDC_ERR_POLICY,
4044
     KDC_ERR_C_PRINCIPAL_UNKNOWN,
4045
     KDC_ERR_S_PRINCIPAL_UNKNOWN,
4046
@@ -1234,6 +1235,56 @@ class KdcTgsTests(KDCBaseTest):
4047
                         expected_error=(KDC_ERR_GENERIC,
4048
                                         KDC_ERR_S_PRINCIPAL_UNKNOWN))
4049
 
4050
+    def test_tgs_service_ticket(self):
4051
+        creds = self._get_creds()
4052
+        tgt = self._get_tgt(creds)
4053
+
4054
+        service_creds = self.get_service_creds()
4055
+        service_ticket = self.get_service_ticket(tgt, service_creds)
4056
+
4057
+        self._run_tgs(service_ticket,
4058
+                      expected_error=(KDC_ERR_NOT_US, KDC_ERR_POLICY))
4059
+
4060
+    def test_renew_service_ticket(self):
4061
+        creds = self._get_creds()
4062
+        tgt = self._get_tgt(creds)
4063
+
4064
+        service_creds = self.get_service_creds()
4065
+        service_ticket = self.get_service_ticket(tgt, service_creds)
4066
+
4067
+        service_ticket = self.modified_ticket(
4068
+            service_ticket,
4069
+            modify_fn=self._modify_renewable,
4070
+            checksum_keys=self.get_krbtgt_checksum_key())
4071
+
4072
+        self._renew_tgt(service_ticket,
4073
+                        expected_error=KDC_ERR_POLICY)
4074
+
4075
+    def test_validate_service_ticket(self):
4076
+        creds = self._get_creds()
4077
+        tgt = self._get_tgt(creds)
4078
+
4079
+        service_creds = self.get_service_creds()
4080
+        service_ticket = self.get_service_ticket(tgt, service_creds)
4081
+
4082
+        service_ticket = self.modified_ticket(
4083
+            service_ticket,
4084
+            modify_fn=self._modify_invalid,
4085
+            checksum_keys=self.get_krbtgt_checksum_key())
4086
+
4087
+        self._validate_tgt(service_ticket,
4088
+                           expected_error=KDC_ERR_POLICY)
4089
+
4090
+    def test_s4u2self_service_ticket(self):
4091
+        creds = self._get_creds()
4092
+        tgt = self._get_tgt(creds)
4093
+
4094
+        service_creds = self.get_service_creds()
4095
+        service_ticket = self.get_service_ticket(tgt, service_creds)
4096
+
4097
+        self._s4u2self(service_ticket, creds,
4098
+                       expected_error=(KDC_ERR_NOT_US, KDC_ERR_POLICY))
4099
+
4100
     def test_user2user_service_ticket(self):
4101
         creds = self._get_creds()
4102
         tgt = self._get_tgt(creds)
4103
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
4104
index 3aacec00870..98e8a34cd5f 100644
4105
--- selftest/knownfail_mit_kdc
4106
+++ selftest/knownfail_mit_kdc
4107
@@ -403,6 +403,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
4108
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
4109
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
4110
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
4111
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket
4112
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing
4113
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting
4114
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac
4115
@@ -470,6 +471,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
4116
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
4117
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
4118
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
4119
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_service_ticket
4120
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing
4121
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting
4122
 #
4123
-- 
4124
2.25.1
4125
4126
4127
From 1d616e8e9c0dceabebd1f079fc4d652d6bf2060d Mon Sep 17 00:00:00 2001
4128
From: Joseph Sutton <josephsutton@catalyst.net.nz>
4129
Date: Wed, 24 Nov 2021 12:09:18 +1300
4130
Subject: [PATCH 31/99] tests/krb5: Add TGS-REQ tests with FAST
4131
4132
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
4133
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
4134
(cherry picked from commit ec823c2a83c639f1d7c422153a53d366750e5f2a)
4135
---
4136
 python/samba/tests/krb5/kdc_tgs_tests.py | 184 ++++++++++++++++++++++-
4137
 selftest/knownfail_heimdal_kdc           |  13 ++
4138
 selftest/knownfail_mit_kdc               |  17 +++
4139
 3 files changed, 212 insertions(+), 2 deletions(-)
4140
4141
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
4142
index 52297c963e8..99a91528fa8 100755
4143
--- python/samba/tests/krb5/kdc_tgs_tests.py
4144
+++ python/samba/tests/krb5/kdc_tgs_tests.py
4145
@@ -32,6 +32,7 @@ os.environ["PYTHONUNBUFFERED"] = "1"
4146
 
4147
 import samba.tests.krb5.kcrypto as kcrypto
4148
 from samba.tests.krb5.kdc_base_test import KDCBaseTest
4149
+from samba.tests.krb5.raw_testcase import Krb5EncryptionKey
4150
 from samba.tests.krb5.rfc4120_constants import (
4151
     AES256_CTS_HMAC_SHA1_96,
4152
     ARCFOUR_HMAC_MD5,
4153
@@ -513,6 +514,11 @@ class KdcTgsTests(KDCBaseTest):
4154
         tgt = self._get_tgt(creds)
4155
         self._user2user(tgt, creds, expected_error=0)
4156
 
4157
+    def test_fast_req(self):
4158
+        creds = self._get_creds()
4159
+        tgt = self._get_tgt(creds)
4160
+        self._fast(tgt, creds, expected_error=0)
4161
+
4162
     def test_tgs_req_invalid(self):
4163
         creds = self._get_creds()
4164
         tgt = self._get_tgt(creds, invalid=True)
4165
@@ -528,6 +534,12 @@ class KdcTgsTests(KDCBaseTest):
4166
         tgt = self._get_tgt(creds, invalid=True)
4167
         self._user2user(tgt, creds, expected_error=KRB_ERR_TKT_NYV)
4168
 
4169
+    def test_fast_req_invalid(self):
4170
+        creds = self._get_creds()
4171
+        tgt = self._get_tgt(creds, invalid=True)
4172
+        self._fast(tgt, creds, expected_error=KRB_ERR_TKT_NYV,
4173
+                   expected_sname=self.get_krbtgt_sname())
4174
+
4175
     def test_tgs_req_no_requester_sid(self):
4176
         creds = self._get_creds()
4177
         tgt = self._get_tgt(creds, remove_requester_sid=True)
4178
@@ -583,6 +595,12 @@ class KdcTgsTests(KDCBaseTest):
4179
         tgt = self._get_tgt(creds, remove_pac=True)
4180
         self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
4181
 
4182
+    def test_fast_no_pac(self):
4183
+        creds = self._get_creds()
4184
+        tgt = self._get_tgt(creds, remove_pac=True)
4185
+        self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED,
4186
+                   expected_sname=self.get_krbtgt_sname())
4187
+
4188
     # Test making a request with authdata and without a PAC.
4189
     def test_tgs_authdata_no_pac(self):
4190
         creds = self._get_creds()
4191
@@ -613,6 +631,12 @@ class KdcTgsTests(KDCBaseTest):
4192
         tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True)
4193
         self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
4194
 
4195
+    def test_fast_authdata_no_pac(self):
4196
+        creds = self._get_creds()
4197
+        tgt = self._get_tgt(creds, remove_pac=True, allow_empty_authdata=True)
4198
+        self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED,
4199
+                   expected_sname=self.get_krbtgt_sname())
4200
+
4201
     # Test changing the SID in the PAC to that of another account.
4202
     def test_tgs_sid_mismatch_existing(self):
4203
         creds = self._get_creds()
4204
@@ -646,6 +670,14 @@ class KdcTgsTests(KDCBaseTest):
4205
         self._user2user(tgt, creds,
4206
                         expected_error=KDC_ERR_TGT_REVOKED)
4207
 
4208
+    def test_fast_sid_mismatch_existing(self):
4209
+        creds = self._get_creds()
4210
+        existing_rid = self._get_existing_rid()
4211
+        tgt = self._get_tgt(creds, new_rid=existing_rid)
4212
+        self._fast(tgt, creds,
4213
+                   expected_error=KDC_ERR_TGT_REVOKED,
4214
+                   expected_sname=self.get_krbtgt_sname())
4215
+
4216
     def test_requester_sid_mismatch_existing(self):
4217
         creds = self._get_creds()
4218
         existing_rid = self._get_existing_rid()
4219
@@ -702,6 +734,14 @@ class KdcTgsTests(KDCBaseTest):
4220
         self._user2user(tgt, creds,
4221
                         expected_error=KDC_ERR_TGT_REVOKED)
4222
 
4223
+    def test_fast_sid_mismatch_nonexisting(self):
4224
+        creds = self._get_creds()
4225
+        nonexistent_rid = self._get_non_existent_rid()
4226
+        tgt = self._get_tgt(creds, new_rid=nonexistent_rid)
4227
+        self._fast(tgt, creds,
4228
+                   expected_error=KDC_ERR_TGT_REVOKED,
4229
+                   expected_sname=self.get_krbtgt_sname())
4230
+
4231
     def test_requester_sid_mismatch_nonexisting(self):
4232
         creds = self._get_creds()
4233
         nonexistent_rid = self._get_non_existent_rid()
4234
@@ -799,6 +839,16 @@ class KdcTgsTests(KDCBaseTest):
4235
         self._user2user(tgt, creds,
4236
                         expected_error=KDC_ERR_TGT_REVOKED)
4237
 
4238
+    def test_fast_rodc_sid_mismatch_existing(self):
4239
+        creds = self._get_creds(replication_allowed=True,
4240
+                                revealed_to_rodc=True)
4241
+        existing_rid = self._get_existing_rid(replication_allowed=True,
4242
+                                              revealed_to_rodc=True)
4243
+        tgt = self._get_tgt(creds, from_rodc=True, new_rid=existing_rid)
4244
+        self._fast(tgt, creds,
4245
+                   expected_error=KDC_ERR_TGT_REVOKED,
4246
+                   expected_sname=self.get_krbtgt_sname())
4247
+
4248
     def test_tgs_rodc_requester_sid_mismatch_existing(self):
4249
         creds = self._get_creds(replication_allowed=True,
4250
                                 revealed_to_rodc=True)
4251
@@ -866,6 +916,15 @@ class KdcTgsTests(KDCBaseTest):
4252
         self._user2user(tgt, creds,
4253
                         expected_error=KDC_ERR_TGT_REVOKED)
4254
 
4255
+    def test_fast_rodc_sid_mismatch_nonexisting(self):
4256
+        creds = self._get_creds(replication_allowed=True,
4257
+                                revealed_to_rodc=True)
4258
+        nonexistent_rid = self._get_non_existent_rid()
4259
+        tgt = self._get_tgt(creds, from_rodc=True, new_rid=nonexistent_rid)
4260
+        self._fast(tgt, creds,
4261
+                   expected_error=KDC_ERR_TGT_REVOKED,
4262
+                   expected_sname=self.get_krbtgt_sname())
4263
+
4264
     def test_tgs_rodc_requester_sid_mismatch_nonexisting(self):
4265
         creds = self._get_creds(replication_allowed=True,
4266
                                 revealed_to_rodc=True)
4267
@@ -955,6 +1014,14 @@ class KdcTgsTests(KDCBaseTest):
4268
         self._remove_rodc_partial_secrets()
4269
         self._user2user(tgt, creds, expected_error=KDC_ERR_POLICY)
4270
 
4271
+    def test_fast_rodc_no_partial_secrets(self):
4272
+        creds = self._get_creds(replication_allowed=True,
4273
+                                revealed_to_rodc=True)
4274
+        tgt = self._get_tgt(creds, from_rodc=True)
4275
+        self._remove_rodc_partial_secrets()
4276
+        self._fast(tgt, creds, expected_error=KDC_ERR_POLICY,
4277
+                   expected_sname=self.get_krbtgt_sname())
4278
+
4279
     # Test with an RODC-issued ticket where the RODC account does not have an
4280
     # msDS-KrbTgtLink.
4281
     def test_tgs_rodc_no_krbtgt_link(self):
4282
@@ -992,6 +1059,14 @@ class KdcTgsTests(KDCBaseTest):
4283
         self._remove_rodc_krbtgt_link()
4284
         self._user2user(tgt, creds, expected_error=KDC_ERR_POLICY)
4285
 
4286
+    def test_fast_rodc_no_krbtgt_link(self):
4287
+        creds = self._get_creds(replication_allowed=True,
4288
+                                revealed_to_rodc=True)
4289
+        tgt = self._get_tgt(creds, from_rodc=True)
4290
+        self._remove_rodc_krbtgt_link()
4291
+        self._fast(tgt, creds, expected_error=KDC_ERR_POLICY,
4292
+                   expected_sname=self.get_krbtgt_sname())
4293
+
4294
     # Test with an RODC-issued ticket where the client is not allowed to
4295
     # replicate to the RODC.
4296
     def test_tgs_rodc_not_allowed(self):
4297
@@ -1019,6 +1094,12 @@ class KdcTgsTests(KDCBaseTest):
4298
         tgt = self._get_tgt(creds, from_rodc=True)
4299
         self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
4300
 
4301
+    def test_fast_rodc_not_allowed(self):
4302
+        creds = self._get_creds(revealed_to_rodc=True)
4303
+        tgt = self._get_tgt(creds, from_rodc=True)
4304
+        self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED,
4305
+                   expected_sname=self.get_krbtgt_sname())
4306
+
4307
     # Test with an RODC-issued ticket where the client is denied from
4308
     # replicating to the RODC.
4309
     def test_tgs_rodc_denied(self):
4310
@@ -1051,6 +1132,13 @@ class KdcTgsTests(KDCBaseTest):
4311
         tgt = self._get_tgt(creds, from_rodc=True)
4312
         self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
4313
 
4314
+    def test_fast_rodc_denied(self):
4315
+        creds = self._get_creds(replication_denied=True,
4316
+                                revealed_to_rodc=True)
4317
+        tgt = self._get_tgt(creds, from_rodc=True)
4318
+        self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED,
4319
+                   expected_sname=self.get_krbtgt_sname())
4320
+
4321
     # Test with an RODC-issued ticket where the client is both allowed and
4322
     # denied replicating to the RODC.
4323
     def test_tgs_rodc_allowed_denied(self):
4324
@@ -1088,6 +1176,14 @@ class KdcTgsTests(KDCBaseTest):
4325
         tgt = self._get_tgt(creds, from_rodc=True)
4326
         self._user2user(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED)
4327
 
4328
+    def test_fast_rodc_allowed_denied(self):
4329
+        creds = self._get_creds(replication_allowed=True,
4330
+                                replication_denied=True,
4331
+                                revealed_to_rodc=True)
4332
+        tgt = self._get_tgt(creds, from_rodc=True)
4333
+        self._fast(tgt, creds, expected_error=KDC_ERR_TGT_REVOKED,
4334
+                   expected_sname=self.get_krbtgt_sname())
4335
+
4336
     # Test user-to-user with incorrect service principal names.
4337
     def test_user2user_matching_sname_host(self):
4338
         creds = self._get_creds()
4339
@@ -1295,6 +1391,17 @@ class KdcTgsTests(KDCBaseTest):
4340
         self._user2user(service_ticket, creds,
4341
                         expected_error=(KDC_ERR_MODIFIED, KDC_ERR_POLICY))
4342
 
4343
+    # Expected to fail against Windows, which does not produce a policy error.
4344
+    def test_fast_service_ticket(self):
4345
+        creds = self._get_creds()
4346
+        tgt = self._get_tgt(creds)
4347
+
4348
+        service_creds = self.get_service_creds()
4349
+        service_ticket = self.get_service_ticket(tgt, service_creds)
4350
+
4351
+        self._fast(service_ticket, creds,
4352
+                   expected_error=KDC_ERR_POLICY)
4353
+
4354
     def test_pac_attrs_none(self):
4355
         creds = self._get_creds()
4356
         self.get_tgt(creds, pac_request=None,
4357
@@ -1792,6 +1899,34 @@ class KdcTgsTests(KDCBaseTest):
4358
         pac = self.get_ticket_pac(ticket)
4359
         self.assertIsNotNone(pac)
4360
 
4361
+    def test_fast_pac_request_none(self):
4362
+        creds = self._get_creds()
4363
+        tgt = self.get_tgt(creds, pac_request=None)
4364
+
4365
+        ticket = self._fast(tgt, creds, expected_error=0, expect_pac=True)
4366
+
4367
+        pac = self.get_ticket_pac(ticket)
4368
+        self.assertIsNotNone(pac)
4369
+
4370
+    def test_fast_pac_request_false(self):
4371
+        creds = self._get_creds()
4372
+        tgt = self.get_tgt(creds, pac_request=False)
4373
+
4374
+        ticket = self._fast(tgt, creds, expected_error=0,
4375
+                            expect_pac=True)
4376
+
4377
+        pac = self.get_ticket_pac(ticket, expect_pac=True)
4378
+        self.assertIsNotNone(pac)
4379
+
4380
+    def test_fast_pac_request_true(self):
4381
+        creds = self._get_creds()
4382
+        tgt = self.get_tgt(creds, pac_request=True)
4383
+
4384
+        ticket = self._fast(tgt, creds, expected_error=0, expect_pac=True)
4385
+
4386
+        pac = self.get_ticket_pac(ticket)
4387
+        self.assertIsNotNone(pac)
4388
+
4389
     def test_tgs_rodc_pac_request_none(self):
4390
         creds = self._get_creds(replication_allowed=True,
4391
                                 revealed_to_rodc=True)
4392
@@ -2192,13 +2327,28 @@ class KdcTgsTests(KDCBaseTest):
4393
                              srealm=srealm,
4394
                              expect_pac=expect_pac)
4395
 
4396
+    def _fast(self, armor_tgt, armor_tgt_creds, expected_error,
4397
+              expected_sname=None, expect_pac=True):
4398
+        user_creds = self._get_mach_creds()
4399
+        user_tgt = self.get_tgt(user_creds)
4400
+
4401
+        target_creds = self.get_service_creds()
4402
+
4403
+        return self._tgs_req(user_tgt, expected_error, target_creds,
4404
+                             armor_tgt=armor_tgt,
4405
+                             expected_sname=expected_sname,
4406
+                             expect_pac=expect_pac)
4407
+
4408
     def _tgs_req(self, tgt, expected_error, target_creds,
4409
+                 armor_tgt=None,
4410
                  kdc_options='0',
4411
                  expected_cname=None,
4412
+                 expected_sname=None,
4413
                  additional_ticket=None,
4414
                  generate_padata_fn=None,
4415
                  sname=None,
4416
                  srealm=None,
4417
+                 use_fast=False,
4418
                  expect_claims=True,
4419
                  expect_pac=True,
4420
                  expect_pac_attrs=None,
4421
@@ -2214,7 +2364,8 @@ class KdcTgsTests(KDCBaseTest):
4422
 
4423
         if sname is False:
4424
             sname = None
4425
-            expected_sname = self.get_krbtgt_sname()
4426
+            if expected_sname is None:
4427
+                expected_sname = self.get_krbtgt_sname()
4428
         else:
4429
             if sname is None:
4430
                 target_name = target_creds.get_username()
4431
@@ -2229,7 +2380,8 @@ class KdcTgsTests(KDCBaseTest):
4432
                         name_type=NT_PRINCIPAL,
4433
                         names=['host', target_name])
4434
 
4435
-            expected_sname = sname
4436
+            if expected_sname is None:
4437
+                expected_sname = sname
4438
 
4439
         if additional_ticket is not None:
4440
             additional_tickets = [additional_ticket.ticket]
4441
@@ -2241,6 +2393,28 @@ class KdcTgsTests(KDCBaseTest):
4442
 
4443
         subkey = self.RandomKey(tgt.session_key.etype)
4444
 
4445
+        if armor_tgt is not None:
4446
+            armor_subkey = self.RandomKey(subkey.etype)
4447
+            explicit_armor_key = self.generate_armor_key(armor_subkey,
4448
+                                                         armor_tgt.session_key)
4449
+            armor_key = kcrypto.cf2(explicit_armor_key.key,
4450
+                                    subkey.key,
4451
+                                    b'explicitarmor',
4452
+                                    b'tgsarmor')
4453
+            armor_key = Krb5EncryptionKey(armor_key, None)
4454
+
4455
+            generate_fast_fn = self.generate_simple_fast
4456
+            generate_fast_armor_fn = self.generate_ap_req
4457
+
4458
+            pac_options = '1'  # claims support
4459
+        else:
4460
+            armor_subkey = None
4461
+            armor_key = None
4462
+            generate_fast_fn = None
4463
+            generate_fast_armor_fn = None
4464
+
4465
+            pac_options = None
4466
+
4467
         etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
4468
 
4469
         if expected_error:
4470
@@ -2260,12 +2434,18 @@ class KdcTgsTests(KDCBaseTest):
4471
             expected_sname=expected_sname,
4472
             ticket_decryption_key=decryption_key,
4473
             generate_padata_fn=generate_padata_fn,
4474
+            generate_fast_fn=generate_fast_fn,
4475
+            generate_fast_armor_fn=generate_fast_armor_fn,
4476
             check_error_fn=check_error_fn,
4477
             check_rep_fn=check_rep_fn,
4478
             check_kdc_private_fn=self.generic_check_kdc_private,
4479
             expected_error_mode=expected_error,
4480
             expected_status=expected_status,
4481
             tgt=tgt,
4482
+            armor_key=armor_key,
4483
+            armor_tgt=armor_tgt,
4484
+            armor_subkey=armor_subkey,
4485
+            pac_options=pac_options,
4486
             authenticator_subkey=subkey,
4487
             kdc_options=kdc_options,
4488
             expect_edata=expect_edata,
4489
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
4490
index 1b7e159c381..61de06659be 100644
4491
--- selftest/knownfail_heimdal_kdc
4492
+++ selftest/knownfail_heimdal_kdc
4493
@@ -274,6 +274,19 @@
4494
 #
4495
 # KDC TGS tests
4496
 #
4497
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac
4498
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_no_pac
4499
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req_invalid
4500
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_allowed_denied
4501
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_denied
4502
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_krbtgt_link
4503
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_partial_secrets
4504
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_not_allowed
4505
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_existing
4506
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_nonexisting
4507
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
4508
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
4509
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
4510
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
4511
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
4512
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac
4513
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
4514
index 98e8a34cd5f..3e19ee6c8b9 100644
4515
--- selftest/knownfail_mit_kdc
4516
+++ selftest/knownfail_mit_kdc
4517
@@ -390,6 +390,23 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
4518
 #
4519
 # KDC TGT tests
4520
 #
4521
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac
4522
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_no_pac
4523
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_false
4524
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_none
4525
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_pac_request_true
4526
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req
4527
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_req_invalid
4528
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_allowed_denied
4529
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_denied
4530
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_krbtgt_link
4531
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_no_partial_secrets
4532
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_not_allowed
4533
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_existing
4534
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_rodc_sid_mismatch_nonexisting
4535
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
4536
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
4537
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
4538
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
4539
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
4540
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
4541
-- 
4542
2.25.1
4543
4544
4545
From 5375e2b99cd5fd9e40d6d5f94eb7d46f366f525e Mon Sep 17 00:00:00 2001
4546
From: Joseph Sutton <josephsutton@catalyst.net.nz>
4547
Date: Wed, 24 Nov 2021 12:37:08 +1300
4548
Subject: [PATCH 32/99] tests/krb5: Align PAC buffer checking to more closely
4549
 match Windows with PacRequestorEnforcement=2
4550
4551
We set EXPECT_EXTRA_PAC_BUFFERS to 0 for the moment. This signifies that
4552
these checks are currently not enforced, which avoids a lot of test
4553
failures.
4554
4555
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
4556
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
4557
(cherry picked from commit ebc9137cee94dee9dcf0e47d5bc0dc83de7aaaa1)
4558
4559
[jsutton@samba.org Fixed conflicts]
4560
---
4561
 python/samba/tests/krb5/kdc_tgs_tests.py | 121 ++++++++++++++++-------
4562
 python/samba/tests/krb5/raw_testcase.py  |  39 ++++++--
4563
 selftest/knownfail_heimdal_kdc           |   9 ++
4564
 selftest/knownfail_mit_kdc               |   6 ++
4565
 source4/selftest/tests.py                |  58 +++++++----
4566
 5 files changed, 168 insertions(+), 65 deletions(-)
4567
4568
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
4569
index 99a91528fa8..f14439a4ab5 100755
4570
--- python/samba/tests/krb5/kdc_tgs_tests.py
4571
+++ python/samba/tests/krb5/kdc_tgs_tests.py
4572
@@ -497,12 +497,18 @@ class KdcTgsTests(KDCBaseTest):
4573
     def test_renew_req(self):
4574
         creds = self._get_creds()
4575
         tgt = self._get_tgt(creds, renewable=True)
4576
-        self._renew_tgt(tgt, expected_error=0)
4577
+        self._renew_tgt(tgt, expected_error=0,
4578
+                        expect_pac_attrs=True,
4579
+                        expect_pac_attrs_pac_request=True,
4580
+                        expect_requester_sid=True)
4581
 
4582
     def test_validate_req(self):
4583
         creds = self._get_creds()
4584
         tgt = self._get_tgt(creds, invalid=True)
4585
-        self._validate_tgt(tgt, expected_error=0)
4586
+        self._validate_tgt(tgt, expected_error=0,
4587
+                           expect_pac_attrs=True,
4588
+                           expect_pac_attrs_pac_request=True,
4589
+                           expect_requester_sid=True)
4590
 
4591
     def test_s4u2self_req(self):
4592
         creds = self._get_creds()
4593
@@ -774,13 +780,17 @@ class KdcTgsTests(KDCBaseTest):
4594
         creds = self._get_creds(replication_allowed=True,
4595
                                 revealed_to_rodc=True)
4596
         tgt = self._get_tgt(creds, renewable=True, from_rodc=True)
4597
-        self._renew_tgt(tgt, expected_error=0)
4598
+        self._renew_tgt(tgt, expected_error=0,
4599
+                        expect_pac_attrs=False,
4600
+                        expect_requester_sid=True)
4601
 
4602
     def test_validate_rodc_revealed(self):
4603
         creds = self._get_creds(replication_allowed=True,
4604
                                 revealed_to_rodc=True)
4605
         tgt = self._get_tgt(creds, invalid=True, from_rodc=True)
4606
-        self._validate_tgt(tgt, expected_error=0)
4607
+        self._validate_tgt(tgt, expected_error=0,
4608
+                           expect_pac_attrs=False,
4609
+                           expect_requester_sid=True)
4610
 
4611
     def test_s4u2self_rodc_revealed(self):
4612
         creds = self._get_creds(replication_allowed=True,
4613
@@ -1434,7 +1444,8 @@ class KdcTgsTests(KDCBaseTest):
4614
         self._renew_tgt(tgt, expected_error=0,
4615
                         expect_pac=True,
4616
                         expect_pac_attrs=True,
4617
-                        expect_pac_attrs_pac_request=None)
4618
+                        expect_pac_attrs_pac_request=None,
4619
+                        expect_requester_sid=True)
4620
 
4621
     def test_pac_attrs_renew_false(self):
4622
         creds = self._get_creds()
4623
@@ -1447,7 +1458,8 @@ class KdcTgsTests(KDCBaseTest):
4624
         self._renew_tgt(tgt, expected_error=0,
4625
                         expect_pac=True,
4626
                         expect_pac_attrs=True,
4627
-                        expect_pac_attrs_pac_request=False)
4628
+                        expect_pac_attrs_pac_request=False,
4629
+                        expect_requester_sid=True)
4630
 
4631
     def test_pac_attrs_renew_true(self):
4632
         creds = self._get_creds()
4633
@@ -1460,7 +1472,8 @@ class KdcTgsTests(KDCBaseTest):
4634
         self._renew_tgt(tgt, expected_error=0,
4635
                         expect_pac=True,
4636
                         expect_pac_attrs=True,
4637
-                        expect_pac_attrs_pac_request=True)
4638
+                        expect_pac_attrs_pac_request=True,
4639
+                        expect_requester_sid=True)
4640
 
4641
     def test_pac_attrs_rodc_renew_none(self):
4642
         creds = self._get_creds(replication_allowed=True,
4643
@@ -1473,8 +1486,8 @@ class KdcTgsTests(KDCBaseTest):
4644
 
4645
         self._renew_tgt(tgt, expected_error=0,
4646
                         expect_pac=True,
4647
-                        expect_pac_attrs=True,
4648
-                        expect_pac_attrs_pac_request=None)
4649
+                        expect_pac_attrs=False,
4650
+                        expect_requester_sid=True)
4651
 
4652
     def test_pac_attrs_rodc_renew_false(self):
4653
         creds = self._get_creds(replication_allowed=True,
4654
@@ -1487,8 +1500,8 @@ class KdcTgsTests(KDCBaseTest):
4655
 
4656
         self._renew_tgt(tgt, expected_error=0,
4657
                         expect_pac=True,
4658
-                        expect_pac_attrs=True,
4659
-                        expect_pac_attrs_pac_request=False)
4660
+                        expect_pac_attrs=False,
4661
+                        expect_requester_sid=True)
4662
 
4663
     def test_pac_attrs_rodc_renew_true(self):
4664
         creds = self._get_creds(replication_allowed=True,
4665
@@ -1501,8 +1514,8 @@ class KdcTgsTests(KDCBaseTest):
4666
 
4667
         self._renew_tgt(tgt, expected_error=0,
4668
                         expect_pac=True,
4669
-                        expect_pac_attrs=True,
4670
-                        expect_pac_attrs_pac_request=True)
4671
+                        expect_pac_attrs=False,
4672
+                        expect_requester_sid=True)
4673
 
4674
     def test_pac_attrs_missing_renew_none(self):
4675
         creds = self._get_creds()
4676
@@ -1515,7 +1528,8 @@ class KdcTgsTests(KDCBaseTest):
4677
 
4678
         self._renew_tgt(tgt, expected_error=0,
4679
                         expect_pac=True,
4680
-                        expect_pac_attrs=False)
4681
+                        expect_pac_attrs=False,
4682
+                        expect_requester_sid=True)
4683
 
4684
     def test_pac_attrs_missing_renew_false(self):
4685
         creds = self._get_creds()
4686
@@ -1528,7 +1542,8 @@ class KdcTgsTests(KDCBaseTest):
4687
 
4688
         self._renew_tgt(tgt, expected_error=0,
4689
                         expect_pac=True,
4690
-                        expect_pac_attrs=False)
4691
+                        expect_pac_attrs=False,
4692
+                        expect_requester_sid=True)
4693
 
4694
     def test_pac_attrs_missing_renew_true(self):
4695
         creds = self._get_creds()
4696
@@ -1541,7 +1556,8 @@ class KdcTgsTests(KDCBaseTest):
4697
 
4698
         self._renew_tgt(tgt, expected_error=0,
4699
                         expect_pac=True,
4700
-                        expect_pac_attrs=False)
4701
+                        expect_pac_attrs=False,
4702
+                        expect_requester_sid=True)
4703
 
4704
     def test_pac_attrs_missing_rodc_renew_none(self):
4705
         creds = self._get_creds(replication_allowed=True,
4706
@@ -1555,7 +1571,8 @@ class KdcTgsTests(KDCBaseTest):
4707
 
4708
         self._renew_tgt(tgt, expected_error=0,
4709
                         expect_pac=True,
4710
-                        expect_pac_attrs=False)
4711
+                        expect_pac_attrs=False,
4712
+                        expect_requester_sid=True)
4713
 
4714
     def test_pac_attrs_missing_rodc_renew_false(self):
4715
         creds = self._get_creds(replication_allowed=True,
4716
@@ -1569,7 +1586,8 @@ class KdcTgsTests(KDCBaseTest):
4717
 
4718
         self._renew_tgt(tgt, expected_error=0,
4719
                         expect_pac=True,
4720
-                        expect_pac_attrs=False)
4721
+                        expect_pac_attrs=False,
4722
+                        expect_requester_sid=True)
4723
 
4724
     def test_pac_attrs_missing_rodc_renew_true(self):
4725
         creds = self._get_creds(replication_allowed=True,
4726
@@ -1583,7 +1601,8 @@ class KdcTgsTests(KDCBaseTest):
4727
 
4728
         self._renew_tgt(tgt, expected_error=0,
4729
                         expect_pac=True,
4730
-                        expect_pac_attrs=False)
4731
+                        expect_pac_attrs=False,
4732
+                        expect_requester_sid=True)
4733
 
4734
     def test_tgs_pac_attrs_none(self):
4735
         creds = self._get_creds()
4736
@@ -1593,8 +1612,7 @@ class KdcTgsTests(KDCBaseTest):
4737
                            expect_pac_attrs_pac_request=None)
4738
 
4739
         self._run_tgs(tgt, expected_error=0, expect_pac=True,
4740
-                      expect_pac_attrs=True,
4741
-                      expect_pac_attrs_pac_request=None)
4742
+                      expect_pac_attrs=False)
4743
 
4744
     def test_tgs_pac_attrs_false(self):
4745
         creds = self._get_creds()
4746
@@ -1603,7 +1621,8 @@ class KdcTgsTests(KDCBaseTest):
4747
                            expect_pac_attrs=True,
4748
                            expect_pac_attrs_pac_request=False)
4749
 
4750
-        self._run_tgs(tgt, expected_error=0, expect_pac=False)
4751
+        self._run_tgs(tgt, expected_error=0, expect_pac=False,
4752
+                      expect_pac_attrs=False)
4753
 
4754
     def test_tgs_pac_attrs_true(self):
4755
         creds = self._get_creds()
4756
@@ -1613,8 +1632,7 @@ class KdcTgsTests(KDCBaseTest):
4757
                            expect_pac_attrs_pac_request=True)
4758
 
4759
         self._run_tgs(tgt, expected_error=0, expect_pac=True,
4760
-                      expect_pac_attrs=True,
4761
-                      expect_pac_attrs_pac_request=True)
4762
+                      expect_pac_attrs=False)
4763
 
4764
     def test_as_requester_sid(self):
4765
         creds = self._get_creds()
4766
@@ -1639,8 +1657,7 @@ class KdcTgsTests(KDCBaseTest):
4767
                            expect_requester_sid=True)
4768
 
4769
         self._run_tgs(tgt, expected_error=0, expect_pac=True,
4770
-                      expected_sid=sid,
4771
-                      expect_requester_sid=True)
4772
+                      expect_requester_sid=False)
4773
 
4774
     def test_tgs_requester_sid_renew(self):
4775
         creds = self._get_creds()
4776
@@ -1655,6 +1672,8 @@ class KdcTgsTests(KDCBaseTest):
4777
         tgt = self._modify_tgt(tgt, renewable=True)
4778
 
4779
         self._renew_tgt(tgt, expected_error=0, expect_pac=True,
4780
+                        expect_pac_attrs=True,
4781
+                        expect_pac_attrs_pac_request=None,
4782
                         expected_sid=sid,
4783
                         expect_requester_sid=True)
4784
 
4785
@@ -1672,6 +1691,7 @@ class KdcTgsTests(KDCBaseTest):
4786
         tgt = self._modify_tgt(tgt, from_rodc=True, renewable=True)
4787
 
4788
         self._renew_tgt(tgt, expected_error=0, expect_pac=True,
4789
+                        expect_pac_attrs=False,
4790
                         expected_sid=sid,
4791
                         expect_requester_sid=True)
4792
 
4793
@@ -1738,7 +1758,10 @@ class KdcTgsTests(KDCBaseTest):
4794
         tgt = self.get_tgt(creds, pac_request=None)
4795
         tgt = self._modify_tgt(tgt, renewable=True)
4796
 
4797
-        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None)
4798
+        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None,
4799
+                              expect_pac_attrs=True,
4800
+                              expect_pac_attrs_pac_request=None,
4801
+                              expect_requester_sid=True)
4802
 
4803
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
4804
 
4805
@@ -1750,7 +1773,10 @@ class KdcTgsTests(KDCBaseTest):
4806
         tgt = self.get_tgt(creds, pac_request=False, expect_pac=None)
4807
         tgt = self._modify_tgt(tgt, renewable=True)
4808
 
4809
-        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None)
4810
+        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None,
4811
+                              expect_pac_attrs=True,
4812
+                              expect_pac_attrs_pac_request=False,
4813
+                              expect_requester_sid=True)
4814
 
4815
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False)
4816
 
4817
@@ -1762,7 +1788,10 @@ class KdcTgsTests(KDCBaseTest):
4818
         tgt = self.get_tgt(creds, pac_request=True)
4819
         tgt = self._modify_tgt(tgt, renewable=True)
4820
 
4821
-        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None)
4822
+        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None,
4823
+                              expect_pac_attrs=True,
4824
+                              expect_pac_attrs_pac_request=True,
4825
+                              expect_requester_sid=True)
4826
 
4827
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
4828
 
4829
@@ -1774,7 +1803,10 @@ class KdcTgsTests(KDCBaseTest):
4830
         tgt = self.get_tgt(creds, pac_request=None)
4831
         tgt = self._modify_tgt(tgt, invalid=True)
4832
 
4833
-        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None)
4834
+        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None,
4835
+                                 expect_pac_attrs=True,
4836
+                                 expect_pac_attrs_pac_request=None,
4837
+                                 expect_requester_sid=True)
4838
 
4839
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
4840
 
4841
@@ -1786,7 +1818,10 @@ class KdcTgsTests(KDCBaseTest):
4842
         tgt = self.get_tgt(creds, pac_request=False, expect_pac=None)
4843
         tgt = self._modify_tgt(tgt, invalid=True)
4844
 
4845
-        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None)
4846
+        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None,
4847
+                                 expect_pac_attrs=True,
4848
+                                 expect_pac_attrs_pac_request=False,
4849
+                                 expect_requester_sid=True)
4850
 
4851
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=False)
4852
 
4853
@@ -1798,7 +1833,10 @@ class KdcTgsTests(KDCBaseTest):
4854
         tgt = self.get_tgt(creds, pac_request=True)
4855
         tgt = self._modify_tgt(tgt, invalid=True)
4856
 
4857
-        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None)
4858
+        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None,
4859
+                                 expect_pac_attrs=True,
4860
+                                 expect_pac_attrs_pac_request=True,
4861
+                                 expect_requester_sid=True)
4862
 
4863
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
4864
 
4865
@@ -1946,7 +1984,7 @@ class KdcTgsTests(KDCBaseTest):
4866
 
4867
         ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
4868
 
4869
-        pac = self.get_ticket_pac(ticket, expect_pac=False)
4870
+        pac = self.get_ticket_pac(ticket)
4871
         self.assertIsNotNone(pac)
4872
 
4873
     def test_tgs_rodc_pac_request_true(self):
4874
@@ -2279,12 +2317,21 @@ class KdcTgsTests(KDCBaseTest):
4875
             expect_requester_sid=expect_requester_sid,
4876
             expected_sid=expected_sid)
4877
 
4878
-    def _validate_tgt(self, tgt, expected_error, expect_pac=True):
4879
+    def _validate_tgt(self, tgt, expected_error, expect_pac=True,
4880
+                      expect_pac_attrs=None,
4881
+                      expect_pac_attrs_pac_request=None,
4882
+                      expect_requester_sid=None,
4883
+                      expected_sid=None):
4884
         krbtgt_creds = self.get_krbtgt_creds()
4885
         kdc_options = str(krb5_asn1.KDCOptions('validate'))
4886
-        return self._tgs_req(tgt, expected_error, krbtgt_creds,
4887
-                             kdc_options=kdc_options,
4888
-                             expect_pac=expect_pac)
4889
+        return self._tgs_req(
4890
+            tgt, expected_error, krbtgt_creds,
4891
+            kdc_options=kdc_options,
4892
+            expect_pac=expect_pac,
4893
+            expect_pac_attrs=expect_pac_attrs,
4894
+            expect_pac_attrs_pac_request=expect_pac_attrs_pac_request,
4895
+            expect_requester_sid=expect_requester_sid,
4896
+            expected_sid=expected_sid)
4897
 
4898
     def _s4u2self(self, tgt, tgt_creds, expected_error, expect_pac=True,
4899
                   expect_edata=False, expected_status=None):
4900
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
4901
index da3f69c79c6..14e655313fc 100644
4902
--- python/samba/tests/krb5/raw_testcase.py
4903
+++ python/samba/tests/krb5/raw_testcase.py
4904
@@ -602,6 +602,13 @@ class RawKerberosTest(TestCaseInTempDir):
4905
             expect_pac = '1'
4906
         cls.expect_pac = bool(int(expect_pac))
4907
 
4908
+        expect_extra_pac_buffers = samba.tests.env_get_var_value(
4909
+            'EXPECT_EXTRA_PAC_BUFFERS',
4910
+            allow_missing=True)
4911
+        if expect_extra_pac_buffers is None:
4912
+            expect_extra_pac_buffers = '1'
4913
+        cls.expect_extra_pac_buffers = bool(int(expect_extra_pac_buffers))
4914
+
4915
     def setUp(self):
4916
         super().setUp()
4917
         self.do_asn1_print = False
4918
@@ -2624,17 +2631,34 @@ class RawKerberosTest(TestCaseInTempDir):
4919
         if not self.tkt_sig_support:
4920
             require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM)
4921
 
4922
+        expect_extra_pac_buffers = rep_msg_type == KRB_AS_REP
4923
+
4924
         expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs']
4925
+
4926
+        if expect_pac_attrs:
4927
+            expect_pac_attrs_pac_request = kdc_exchange_dict[
4928
+                'expect_pac_attrs_pac_request']
4929
+        else:
4930
+            expect_pac_attrs_pac_request = kdc_exchange_dict[
4931
+                'pac_request']
4932
+
4933
+        if expect_pac_attrs is None:
4934
+            if self.expect_extra_pac_buffers:
4935
+                expect_pac_attrs = expect_extra_pac_buffers
4936
+            else:
4937
+                require_strict.add(krb5pac.PAC_TYPE_ATTRIBUTES_INFO)
4938
         if expect_pac_attrs:
4939
             expected_types.append(krb5pac.PAC_TYPE_ATTRIBUTES_INFO)
4940
-        elif expect_pac_attrs is None:
4941
-            require_strict.add(krb5pac.PAC_TYPE_ATTRIBUTES_INFO)
4942
 
4943
         expect_requester_sid = kdc_exchange_dict['expect_requester_sid']
4944
+
4945
+        if expect_requester_sid is None:
4946
+            if self.expect_extra_pac_buffers:
4947
+                expect_requester_sid = expect_extra_pac_buffers
4948
+            else:
4949
+                require_strict.add(krb5pac.PAC_TYPE_REQUESTER_SID)
4950
         if expect_requester_sid:
4951
             expected_types.append(krb5pac.PAC_TYPE_REQUESTER_SID)
4952
-        elif expect_requester_sid is None:
4953
-            require_strict.add(krb5pac.PAC_TYPE_REQUESTER_SID)
4954
 
4955
         buffer_types = [pac_buffer.type
4956
                         for pac_buffer in pac.buffers]
4957
@@ -2722,9 +2746,6 @@ class RawKerberosTest(TestCaseInTempDir):
4958
                 requested_pac = bool(flags & 1)
4959
                 given_pac = bool(flags & 2)
4960
 
4961
-                expect_pac_attrs_pac_request = kdc_exchange_dict[
4962
-                    'expect_pac_attrs_pac_request']
4963
-
4964
                 self.assertEqual(expect_pac_attrs_pac_request is True,
4965
                                  requested_pac)
4966
                 self.assertEqual(expect_pac_attrs_pac_request is None,
4967
@@ -2734,8 +2755,8 @@ class RawKerberosTest(TestCaseInTempDir):
4968
                       and expect_requester_sid):
4969
                 requester_sid = pac_buffer.info.sid
4970
 
4971
-                self.assertIsNotNone(expected_sid)
4972
-                self.assertEqual(expected_sid, str(requester_sid))
4973
+                if expected_sid is not None:
4974
+                    self.assertEqual(expected_sid, str(requester_sid))
4975
 
4976
     def generic_check_kdc_error(self,
4977
                                 kdc_exchange_dict,
4978
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
4979
index 61de06659be..294e06027b1 100644
4980
--- selftest/knownfail_heimdal_kdc
4981
+++ selftest/knownfail_heimdal_kdc
4982
@@ -289,11 +289,15 @@
4983
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
4984
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
4985
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
4986
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
4987
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
4988
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
4989
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac
4990
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required
4991
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required
4992
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
4993
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
4994
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
4995
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
4996
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
4997
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing
4998
@@ -309,10 +313,14 @@
4999
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting
5000
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac
5001
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
5002
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
5003
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
5004
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
5005
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
5006
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_)
5007
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
5008
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
5009
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5010
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
5011
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
5012
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false
5013
@@ -332,6 +340,7 @@
5014
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt
5015
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
5016
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac
5017
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
5018
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
5019
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
5020
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing
5021
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
5022
index 3e19ee6c8b9..6c74657e87d 100644
5023
--- selftest/knownfail_mit_kdc
5024
+++ selftest/knownfail_mit_kdc
5025
@@ -411,6 +411,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5026
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
5027
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
5028
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
5029
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none
5030
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true
5031
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req
5032
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied
5033
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_denied
5034
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_no_krbtgt_link
5035
@@ -479,6 +482,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5036
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm
5037
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
5038
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac
5039
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none
5040
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true
5041
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req
5042
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied
5043
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_denied
5044
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_no_krbtgt_link
5045
5046
From 3fdfbd08b9460fb486f100d7091984f41ebd9429 Mon Sep 17 00:00:00 2001
5047
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5048
Date: Wed, 24 Nov 2021 13:10:52 +1300
5049
Subject: [PATCH 33/99] tests/krb5: Add tests for validation with requester SID
5050
 PAC buffer
5051
5052
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5053
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5054
(cherry picked from commit ca80c47406e0f2b6fac2c55229306e21ccef9745)
5055
---
5056
 python/samba/tests/krb5/kdc_tgs_tests.py | 67 ++++++++++++++++++++++++
5057
 selftest/knownfail_heimdal_kdc           |  3 ++
5058
 selftest/knownfail_mit_kdc               |  4 ++
5059
 3 files changed, 74 insertions(+)
5060
5061
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
5062
index f14439a4ab5..50079a1710c 100755
5063
--- python/samba/tests/krb5/kdc_tgs_tests.py
5064
+++ python/samba/tests/krb5/kdc_tgs_tests.py
5065
@@ -1726,6 +1726,73 @@ class KdcTgsTests(KDCBaseTest):
5066
 
5067
         self._renew_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
5068
 
5069
+    def test_tgs_requester_sid_validate(self):
5070
+        creds = self._get_creds()
5071
+
5072
+        samdb = self.get_samdb()
5073
+        sid = self.get_objectSid(samdb, creds.get_dn())
5074
+
5075
+        tgt = self.get_tgt(creds, pac_request=None,
5076
+                           expect_pac=True,
5077
+                           expected_sid=sid,
5078
+                           expect_requester_sid=True)
5079
+        tgt = self._modify_tgt(tgt, invalid=True)
5080
+
5081
+        self._validate_tgt(tgt, expected_error=0, expect_pac=True,
5082
+                           expect_pac_attrs=True,
5083
+                           expect_pac_attrs_pac_request=None,
5084
+                           expected_sid=sid,
5085
+                           expect_requester_sid=True)
5086
+
5087
+    def test_tgs_requester_sid_rodc_validate(self):
5088
+        creds = self._get_creds(replication_allowed=True,
5089
+                                revealed_to_rodc=True)
5090
+
5091
+        samdb = self.get_samdb()
5092
+        sid = self.get_objectSid(samdb, creds.get_dn())
5093
+
5094
+        tgt = self.get_tgt(creds, pac_request=None,
5095
+                           expect_pac=True,
5096
+                           expected_sid=sid,
5097
+                           expect_requester_sid=True)
5098
+        tgt = self._modify_tgt(tgt, from_rodc=True, invalid=True)
5099
+
5100
+        self._validate_tgt(tgt, expected_error=0, expect_pac=True,
5101
+                           expect_pac_attrs=False,
5102
+                           expected_sid=sid,
5103
+                           expect_requester_sid=True)
5104
+
5105
+    def test_tgs_requester_sid_missing_validate(self):
5106
+        creds = self._get_creds()
5107
+
5108
+        samdb = self.get_samdb()
5109
+        sid = self.get_objectSid(samdb, creds.get_dn())
5110
+
5111
+        tgt = self.get_tgt(creds, pac_request=None,
5112
+                           expect_pac=True,
5113
+                           expected_sid=sid,
5114
+                           expect_requester_sid=True)
5115
+        tgt = self._modify_tgt(tgt, invalid=True,
5116
+                               remove_requester_sid=True)
5117
+
5118
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
5119
+
5120
+    def test_tgs_requester_sid_missing_rodc_validate(self):
5121
+        creds = self._get_creds(replication_allowed=True,
5122
+                                revealed_to_rodc=True)
5123
+
5124
+        samdb = self.get_samdb()
5125
+        sid = self.get_objectSid(samdb, creds.get_dn())
5126
+
5127
+        tgt = self.get_tgt(creds, pac_request=None,
5128
+                           expect_pac=True,
5129
+                           expected_sid=sid,
5130
+                           expect_requester_sid=True)
5131
+        tgt = self._modify_tgt(tgt, from_rodc=True, invalid=True,
5132
+                               remove_requester_sid=True)
5133
+
5134
+        self._validate_tgt(tgt, expected_error=KDC_ERR_TGT_REVOKED)
5135
+
5136
     def test_tgs_pac_request_none(self):
5137
         creds = self._get_creds()
5138
         tgt = self.get_tgt(creds, pac_request=None)
5139
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5140
index 294e06027b1..f7c5feda872 100644
5141
--- selftest/knownfail_heimdal_kdc
5142
+++ selftest/knownfail_heimdal_kdc
5143
@@ -320,7 +320,10 @@
5144
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_)
5145
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
5146
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
5147
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
5148
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
5149
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5150
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
5151
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
5152
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
5153
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false
5154
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
5155
index 6c74657e87d..ff287e6cd9d 100644
5156
--- selftest/knownfail_mit_kdc
5157
+++ selftest/knownfail_mit_kdc
5158
@@ -546,8 +546,12 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5159
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid
5160
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
5161
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
5162
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
5163
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
5164
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew
5165
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5166
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
5167
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate
5168
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
5169
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
5170
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing
5171
-- 
5172
2.25.1
5173
5174
5175
From 69233dd323b1ce715387e6015542ed234d909295 Mon Sep 17 00:00:00 2001
5176
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5177
Date: Wed, 24 Nov 2021 15:32:32 +1300
5178
Subject: [PATCH 34/99] tests/krb5: Add comments for tests that fail against
5179
 Windows
5180
5181
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5182
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5183
(cherry picked from commit 749349efab9b401d33a4fc286473a924364a41c9)
5184
---
5185
 python/samba/tests/krb5/kdc_tgs_tests.py | 6 ++++++
5186
 1 file changed, 6 insertions(+)
5187
5188
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
5189
index 50079a1710c..ecc38538e61 100755
5190
--- python/samba/tests/krb5/kdc_tgs_tests.py
5191
+++ python/samba/tests/krb5/kdc_tgs_tests.py
5192
@@ -792,6 +792,8 @@ class KdcTgsTests(KDCBaseTest):
5193
                            expect_pac_attrs=False,
5194
                            expect_requester_sid=True)
5195
 
5196
+    # This test fails on Windows, which gives KDC_ERR_C_PRINCIPAL_UNKNOWN when
5197
+    # attempting to use S4U2Self with a TGT from an RODC.
5198
     def test_s4u2self_rodc_revealed(self):
5199
         creds = self._get_creds(replication_allowed=True,
5200
                                 revealed_to_rodc=True)
5201
@@ -2370,6 +2372,8 @@ class KdcTgsTests(KDCBaseTest):
5202
             expect_requester_sid=expect_requester_sid,
5203
             expected_sid=expected_sid)
5204
 
5205
+    # These tests fail against Windows, which does not implement ticket
5206
+    # renewal.
5207
     def _renew_tgt(self, tgt, expected_error, expect_pac=True,
5208
                    expect_pac_attrs=None, expect_pac_attrs_pac_request=None,
5209
                    expect_requester_sid=None, expected_sid=None):
5210
@@ -2384,6 +2388,8 @@ class KdcTgsTests(KDCBaseTest):
5211
             expect_requester_sid=expect_requester_sid,
5212
             expected_sid=expected_sid)
5213
 
5214
+    # These tests fail against Windows, which does not implement ticket
5215
+    # validation.
5216
     def _validate_tgt(self, tgt, expected_error, expect_pac=True,
5217
                       expect_pac_attrs=None,
5218
                       expect_pac_attrs_pac_request=None,
5219
-- 
5220
2.25.1
5221
5222
5223
From 6dbed53756f6bac8f63847644b3e9cbb7b6181b0 Mon Sep 17 00:00:00 2001
5224
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5225
Date: Thu, 18 Nov 2021 13:14:51 +1300
5226
Subject: [PATCH 35/99] heimdal:kdc: Fix error message for user-to-user
5227
5228
We were checking the wrong variable to see whether a PAC was found or not.
5229
5230
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5231
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5232
(cherry picked from commit 11fb9476ad3c09415d12b3cdf7934c293cbefcb2)
5233
---
5234
 source4/heimdal/kdc/krb5tgs.c | 2 +-
5235
 1 file changed, 1 insertion(+), 1 deletion(-)
5236
5237
diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c
5238
index fb2ef8230c9..cde68b41714 100644
5239
--- source4/heimdal/kdc/krb5tgs.c
5240
+++ source4/heimdal/kdc/krb5tgs.c
5241
@@ -1629,7 +1629,7 @@ server_lookup:
5242
 		ret = KRB5KDC_ERR_BADOPTION;
5243
 		kdc_log(context, config, 0,
5244
 			"Ticket not signed with PAC; user-to-user failed (%s).",
5245
-			mspac ? "Ticket unsigned" : "No PAC");
5246
+			user2user_pac ? "Ticket unsigned" : "No PAC");
5247
 		goto out;
5248
 	    }
5249
 
5250
-- 
5251
2.25.1
5252
5253
5254
From 33d5e5ad3a06ca6a1a62e64d323580ca60f068b8 Mon Sep 17 00:00:00 2001
5255
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5256
Date: Thu, 18 Nov 2021 16:22:34 +1300
5257
Subject: [PATCH 36/99] s4:torture: Fix typo
5258
5259
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5260
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5261
(cherry picked from commit 9cfb88ba04818b5e9cec3c96422e8e4a3080d490)
5262
---
5263
 source4/torture/krb5/kdc-canon-heimdal.c | 2 +-
5264
 1 file changed, 1 insertion(+), 1 deletion(-)
5265
5266
diff --git source4/torture/krb5/kdc-canon-heimdal.c source4/torture/krb5/kdc-canon-heimdal.c
5267
index cd47182c0ef..059078a4ffb 100644
5268
--- source4/torture/krb5/kdc-canon-heimdal.c
5269
+++ source4/torture/krb5/kdc-canon-heimdal.c
5270
@@ -262,7 +262,7 @@ static bool torture_krb5_pre_send_as_req_test(struct torture_krb5_context *test_
5271
 						 KRB5_NT_PRINCIPAL,
5272
 						 "krb5 libs unexpectedly "
5273
 						 "did not set principal "
5274
-						 "as NT_SRV_HST!");
5275
+						 "as NT_PRINCIPAL!");
5276
 		} else {
5277
 			torture_assert_int_equal(test_context->tctx,
5278
 						 test_context->as_req.req_body.cname->name_type,
5279
-- 
5280
2.25.1
5281
5282
5283
From 02ceb9be33dca0e3a885fd7d85b1199f76e04670 Mon Sep 17 00:00:00 2001
5284
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5285
Date: Wed, 24 Nov 2021 20:41:34 +1300
5286
Subject: [PATCH 37/99] heimdal:kdc: Adjust no-PAC error code to match Windows
5287
5288
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5289
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5290
(cherry picked from commit f7a2fef8f49a86f63c3dc2f6a2d7d979fb53238a)
5291
---
5292
 selftest/knownfail_heimdal_kdc | 19 -------------------
5293
 source4/heimdal/kdc/krb5tgs.c  |  2 +-
5294
 2 files changed, 1 insertion(+), 20 deletions(-)
5295
5296
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5297
index f7c5feda872..9ff85fe18fc 100644
5298
--- selftest/knownfail_heimdal_kdc
5299
+++ selftest/knownfail_heimdal_kdc
5300
@@ -233,21 +233,15 @@
5301
 # S4U tests
5302
 #
5303
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_bronze_bit_rbcd_old_checksum
5304
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_client_pac(?!_no_auth_data_required)
5305
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac\(.*\)$
5306
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_service_pac_no_auth_data_required
5307
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_existing_delegation_info
5308
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_missing_client_checksum
5309
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_a
5310
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_client_pac_b
5311
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac
5312
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_service_pac_no_auth_data_required
5313
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_client_checksum
5314
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum
5315
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum
5316
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
5317
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
5318
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_pac
5319
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
5320
 #
5321
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
5322
@@ -292,11 +286,6 @@
5323
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
5324
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
5325
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
5326
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac
5327
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_client_no_auth_data_required
5328
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_remove_pac_service_no_auth_data_required
5329
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
5330
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
5331
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
5332
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
5333
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
5334
@@ -304,15 +293,11 @@
5335
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting
5336
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing
5337
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting
5338
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac
5339
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac
5340
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
5341
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing
5342
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting
5343
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing
5344
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting
5345
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_authdata_no_pac
5346
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
5347
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
5348
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
5349
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
5350
@@ -333,16 +318,12 @@
5351
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting
5352
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing
5353
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting
5354
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac
5355
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac
5356
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing
5357
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting
5358
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing
5359
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting
5360
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname
5361
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt
5362
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
5363
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac
5364
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
5365
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
5366
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
5367
diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c
5368
index cde68b41714..6c5c51aa448 100644
5369
--- source4/heimdal/kdc/krb5tgs.c
5370
+++ source4/heimdal/kdc/krb5tgs.c
5371
@@ -78,7 +78,7 @@ check_PAC(krb5_context context,
5372
 	return ret;
5373
 
5374
     if (pac == NULL)
5375
-	return KRB5KDC_ERR_BADOPTION;
5376
+	return KRB5KDC_ERR_TGT_REVOKED;
5377
 
5378
     /* Verify the server signature. */
5379
     ret = krb5_pac_verify(context, pac, tkt->authtime, client_principal,
5380
-- 
5381
2.25.1
5382
5383
5384
From 5556f97c782c9be9af47c76f2432bb8480bc0622 Mon Sep 17 00:00:00 2001
5385
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5386
Date: Wed, 24 Nov 2021 20:41:45 +1300
5387
Subject: [PATCH 38/99] kdc: Adjust SID mismatch error code to match Windows
5388
5389
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5390
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5391
(cherry picked from commit d5d22bf84a71492342287e54b555c9f024e7e71c)
5392
---
5393
 selftest/knownfail_heimdal_kdc | 35 ----------------------------------
5394
 selftest/knownfail_mit_kdc     |  8 --------
5395
 source4/kdc/pac-glue.c         |  6 +-----
5396
 3 files changed, 1 insertion(+), 48 deletions(-)
5397
5398
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5399
index 9ff85fe18fc..bc644587319 100644
5400
--- selftest/knownfail_heimdal_kdc
5401
+++ selftest/knownfail_heimdal_kdc
5402
@@ -259,13 +259,6 @@
5403
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_not_revealed
5404
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_not_revealed
5405
 #
5406
-# Alias tests
5407
-#
5408
-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_delete
5409
-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_create_alias_rename
5410
-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_delete
5411
-^samba.tests.krb5.alias_tests.samba.tests.krb5.alias_tests.AliasTests.test_dc_alias_rename
5412
-#
5413
 # KDC TGS tests
5414
 #
5415
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_authdata_no_pac
5416
@@ -281,23 +274,11 @@
5417
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
5418
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
5419
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
5420
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
5421
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
5422
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
5423
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
5424
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
5425
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
5426
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
5427
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
5428
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing
5429
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting
5430
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing
5431
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting
5432
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
5433
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_existing
5434
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_sid_mismatch_nonexisting
5435
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_existing
5436
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_sid_mismatch_nonexisting
5437
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
5438
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
5439
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
5440
@@ -309,23 +290,7 @@
5441
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
5442
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5443
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
5444
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
5445
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
5446
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false
5447
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing
5448
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting
5449
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing
5450
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting
5451
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing
5452
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting
5453
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_existing
5454
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_rodc_sid_mismatch_nonexisting
5455
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_existing
5456
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_sid_mismatch_nonexisting
5457
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname
5458
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt
5459
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
5460
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
5461
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
5462
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing
5463
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting
5464
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
5465
index ff287e6cd9d..c6dc1285837 100644
5466
--- selftest/knownfail_mit_kdc
5467
+++ selftest/knownfail_mit_kdc
5468
@@ -407,8 +407,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5469
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
5470
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
5471
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
5472
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_existing
5473
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_only_sid_mismatch_nonexisting
5474
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
5475
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
5476
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none
5477
@@ -424,8 +422,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5478
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
5479
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
5480
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket
5481
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_existing
5482
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_sid_mismatch_nonexisting
5483
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac
5484
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac
5485
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req
5486
@@ -454,8 +450,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5487
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_revealed
5488
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_existing
5489
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_sid_mismatch_nonexisting
5490
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_existing
5491
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_sid_mismatch_nonexisting
5492
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_authdata_no_pac
5493
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_pac
5494
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_no_sname
5495
@@ -495,8 +489,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5496
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_existing
5497
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_sid_mismatch_nonexisting
5498
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_service_ticket
5499
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_existing
5500
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_sid_mismatch_nonexisting
5501
 #
5502
 # PAC attributes tests
5503
 #
5504
diff --git source4/kdc/pac-glue.c source4/kdc/pac-glue.c
5505
index e0e483662c0..2a96a683cd9 100644
5506
--- source4/kdc/pac-glue.c
5507
+++ source4/kdc/pac-glue.c
5508
@@ -1237,11 +1237,7 @@ krb5_error_code samba_kdc_validate_pac_blob(
5509
 			"PAC[%s] != CLI[%s]\n",
5510
 			dom_sid_str_buf(&pac_sid, &buf1),
5511
 			dom_sid_str_buf(client_sid, &buf2));
5512
-#if defined(KRB5KDC_ERR_CLIENT_NAME_MISMATCH) /* MIT */
5513
-			code = KRB5KDC_ERR_CLIENT_NAME_MISMATCH;
5514
-#else /* Heimdal (where this is an enum) */
5515
-			code = KRB5_KDC_ERR_CLIENT_NAME_MISMATCH;
5516
-#endif
5517
+			code = KRB5KDC_ERR_TGT_REVOKED;
5518
 		goto out;
5519
 	}
5520
 
5521
-- 
5522
2.25.1
5523
5524
5525
From c62a2b7a218e2c4bdbd476a055049e78b8c0f4ce Mon Sep 17 00:00:00 2001
5526
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5527
Date: Thu, 25 Nov 2021 10:05:17 +1300
5528
Subject: [PATCH 39/99] tests/krb5: Add test for S4U2Self with wrong sname
5529
5530
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5531
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5532
(cherry picked from commit bac5f75059450898937be891e863826e1350b62c)
5533
---
5534
 python/samba/tests/krb5/s4u_tests.py | 32 +++++++++++++++++++++++++++-
5535
 selftest/knownfail_heimdal_kdc       |  1 +
5536
 2 files changed, 32 insertions(+), 1 deletion(-)
5537
5538
diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py
5539
index 5f37525f393..2953766ef21 100755
5540
--- python/samba/tests/krb5/s4u_tests.py
5541
+++ python/samba/tests/krb5/s4u_tests.py
5542
@@ -36,6 +36,7 @@ from samba.tests.krb5.raw_testcase import (
5543
 from samba.tests.krb5.rfc4120_constants import (
5544
     AES256_CTS_HMAC_SHA1_96,
5545
     ARCFOUR_HMAC_MD5,
5546
+    KDC_ERR_BADMATCH,
5547
     KDC_ERR_BADOPTION,
5548
     KDC_ERR_BAD_INTEGRITY,
5549
     KDC_ERR_GENERIC,
5550
@@ -243,7 +244,9 @@ class S4UKerberosTests(KDCBaseTest):
5551
         client_dn = client_creds.get_dn()
5552
         sid = self.get_objectSid(samdb, client_dn)
5553
 
5554
-        service_name = service_creds.get_username()[:-1]
5555
+        service_name = kdc_dict.pop('service_name', None)
5556
+        if service_name is None:
5557
+            service_name = service_creds.get_username()[:-1]
5558
         service_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
5559
                                                   names=['host', service_name])
5560
 
5561
@@ -474,6 +477,33 @@ class S4UKerberosTests(KDCBaseTest):
5562
                 'expected_flags': 'forwardable'
5563
             })
5564
 
5565
+    # Do an S4U2Self with the sname in the request different to that of the
5566
+    # service. We expect an error.
5567
+    def test_s4u2self_wrong_sname(self):
5568
+        other_creds = self.get_cached_creds(
5569
+            account_type=self.AccountType.COMPUTER,
5570
+            opts={
5571
+                'trusted_to_auth_for_delegation': True,
5572
+                'id': 0
5573
+            })
5574
+        other_sname = other_creds.get_username()[:-1]
5575
+
5576
+        self._run_s4u2self_test(
5577
+            {
5578
+                'expected_error_mode': KDC_ERR_BADMATCH,
5579
+                'expect_edata': False,
5580
+                'client_opts': {
5581
+                    'not_delegated': False
5582
+                },
5583
+                'service_opts': {
5584
+                    'trusted_to_auth_for_delegation': True
5585
+                },
5586
+                'service_name': other_sname,
5587
+                'kdc_options': 'forwardable',
5588
+                'modify_service_tgt_fn': functools.partial(
5589
+                    self.set_ticket_forwardable, flag=True)
5590
+            })
5591
+
5592
     def _run_delegation_test(self, kdc_dict):
5593
         client_opts = kdc_dict.pop('client_opts', None)
5594
         client_creds = self.get_cached_creds(
5595
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5596
index bc644587319..483145f1473 100644
5597
--- selftest/knownfail_heimdal_kdc
5598
+++ selftest/knownfail_heimdal_kdc
5599
@@ -243,6 +243,7 @@
5600
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
5601
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
5602
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
5603
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_wrong_sname
5604
 #
5605
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
5606
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required
5607
-- 
5608
2.25.1
5609
5610
5611
From 46b05cbf803c54cf56dca228fe95a3454027d0cc Mon Sep 17 00:00:00 2001
5612
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5613
Date: Tue, 23 Nov 2021 20:00:07 +1300
5614
Subject: [PATCH 40/99] kdc: Match Windows error code for mismatching sname
5615
5616
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5617
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5618
(cherry picked from commit b6a25f5f016aef39c3b1d7be8b3ecfe021c03c83)
5619
---
5620
 selftest/knownfail_heimdal_kdc | 3 ---
5621
 source4/kdc/db-glue.c          | 2 +-
5622
 2 files changed, 1 insertion(+), 4 deletions(-)
5623
5624
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5625
index 483145f1473..981d7894158 100644
5626
--- selftest/knownfail_heimdal_kdc
5627
+++ selftest/knownfail_heimdal_kdc
5628
@@ -243,7 +243,6 @@
5629
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
5630
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
5631
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
5632
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_wrong_sname
5633
 #
5634
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
5635
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required
5636
@@ -292,6 +291,4 @@
5637
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5638
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
5639
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false
5640
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname
5641
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_sname_krbtgt
5642
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
5643
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
5644
index d017741e30a..bed0ff773f9 100644
5645
--- source4/kdc/db-glue.c
5646
+++ source4/kdc/db-glue.c
5647
@@ -2599,7 +2599,7 @@ samba_kdc_check_s4u2self(krb5_context context,
5648
 	 */
5649
 	if (!(orig_sid && target_sid && dom_sid_equal(orig_sid, target_sid))) {
5650
 		talloc_free(frame);
5651
-		return KRB5KDC_ERR_BADOPTION;
5652
+		return KRB5KRB_AP_ERR_BADMATCH;
5653
 	}
5654
 
5655
 	talloc_free(frame);
5656
-- 
5657
2.25.1
5658
5659
5660
From 93a5264dd68da57e172af50020f670631eeef263 Mon Sep 17 00:00:00 2001
5661
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5662
Date: Tue, 23 Nov 2021 20:15:41 +1300
5663
Subject: [PATCH 41/99] kdc: Always add the PAC if the header TGT is from an
5664
 RODC
5665
5666
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5667
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5668
(cherry picked from commit 690a00a40c0a3f77da6e4dca42b630f2793a98b8)
5669
---
5670
 selftest/knownfail_heimdal_kdc | 1 -
5671
 source4/kdc/wdc-samba4.c       | 2 +-
5672
 2 files changed, 1 insertion(+), 2 deletions(-)
5673
5674
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5675
index 981d7894158..94a4509f45a 100644
5676
--- selftest/knownfail_heimdal_kdc
5677
+++ selftest/knownfail_heimdal_kdc
5678
@@ -290,5 +290,4 @@
5679
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
5680
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5681
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
5682
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_pac_request_false
5683
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
5684
diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c
5685
index ecd182702c3..8c3ce71529c 100644
5686
--- source4/kdc/wdc-samba4.c
5687
+++ source4/kdc/wdc-samba4.c
5688
@@ -471,7 +471,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
5689
 		goto out;
5690
 	}
5691
 
5692
-	if (!server_skdc_entry->is_krbtgt) {
5693
+	if (!is_untrusted && !server_skdc_entry->is_krbtgt) {
5694
 		/*
5695
 		 * The client may have requested no PAC when obtaining the
5696
 		 * TGT.
5697
-- 
5698
2.25.1
5699
5700
5701
From 4cd44326ce38187965c46c71322caedb7a2fbf6c Mon Sep 17 00:00:00 2001
5702
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5703
Date: Thu, 25 Nov 2021 10:32:44 +1300
5704
Subject: [PATCH 42/99] tests/krb5: Add tests for renewal and validation of
5705
 RODC TGTs with PAC requests
5706
5707
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5708
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5709
(cherry picked from commit 73a48063469205099f02efdf3b8f0f1040dc7a3d)
5710
---
5711
 python/samba/tests/krb5/kdc_tgs_tests.py | 90 ++++++++++++++++++++++++
5712
 selftest/knownfail_heimdal_kdc           |  6 ++
5713
 selftest/knownfail_mit_kdc               |  6 ++
5714
 3 files changed, 102 insertions(+)
5715
5716
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
5717
index ecc38538e61..2923d53772a 100755
5718
--- python/samba/tests/krb5/kdc_tgs_tests.py
5719
+++ python/samba/tests/krb5/kdc_tgs_tests.py
5720
@@ -1867,6 +1867,51 @@ class KdcTgsTests(KDCBaseTest):
5721
         pac = self.get_ticket_pac(ticket)
5722
         self.assertIsNotNone(pac)
5723
 
5724
+    def test_rodc_renew_pac_request_none(self):
5725
+        creds = self._get_creds(replication_allowed=True,
5726
+                                revealed_to_rodc=True)
5727
+        tgt = self.get_tgt(creds, pac_request=None)
5728
+        tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True)
5729
+
5730
+        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None,
5731
+                              expect_pac_attrs=False,
5732
+                              expect_requester_sid=True)
5733
+
5734
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
5735
+
5736
+        pac = self.get_ticket_pac(ticket)
5737
+        self.assertIsNotNone(pac)
5738
+
5739
+    def test_rodc_renew_pac_request_false(self):
5740
+        creds = self._get_creds(replication_allowed=True,
5741
+                                revealed_to_rodc=True)
5742
+        tgt = self.get_tgt(creds, pac_request=False, expect_pac=None)
5743
+        tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True)
5744
+
5745
+        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None,
5746
+                              expect_pac_attrs=False,
5747
+                              expect_requester_sid=True)
5748
+
5749
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
5750
+
5751
+        pac = self.get_ticket_pac(ticket)
5752
+        self.assertIsNotNone(pac)
5753
+
5754
+    def test_rodc_renew_pac_request_true(self):
5755
+        creds = self._get_creds(replication_allowed=True,
5756
+                                revealed_to_rodc=True)
5757
+        tgt = self.get_tgt(creds, pac_request=True)
5758
+        tgt = self._modify_tgt(tgt, renewable=True, from_rodc=True)
5759
+
5760
+        tgt = self._renew_tgt(tgt, expected_error=0, expect_pac=None,
5761
+                              expect_pac_attrs=False,
5762
+                              expect_requester_sid=True)
5763
+
5764
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
5765
+
5766
+        pac = self.get_ticket_pac(ticket)
5767
+        self.assertIsNotNone(pac)
5768
+
5769
     def test_validate_pac_request_none(self):
5770
         creds = self._get_creds()
5771
         tgt = self.get_tgt(creds, pac_request=None)
5772
@@ -1912,6 +1957,51 @@ class KdcTgsTests(KDCBaseTest):
5773
         pac = self.get_ticket_pac(ticket)
5774
         self.assertIsNotNone(pac)
5775
 
5776
+    def test_rodc_validate_pac_request_none(self):
5777
+        creds = self._get_creds(replication_allowed=True,
5778
+                                revealed_to_rodc=True)
5779
+        tgt = self.get_tgt(creds, pac_request=None)
5780
+        tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True)
5781
+
5782
+        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None,
5783
+                                 expect_pac_attrs=False,
5784
+                                 expect_requester_sid=True)
5785
+
5786
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
5787
+
5788
+        pac = self.get_ticket_pac(ticket)
5789
+        self.assertIsNotNone(pac)
5790
+
5791
+    def test_rodc_validate_pac_request_false(self):
5792
+        creds = self._get_creds(replication_allowed=True,
5793
+                                revealed_to_rodc=True)
5794
+        tgt = self.get_tgt(creds, pac_request=False, expect_pac=None)
5795
+        tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True)
5796
+
5797
+        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None,
5798
+                                 expect_pac_attrs=False,
5799
+                                 expect_requester_sid=True)
5800
+
5801
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
5802
+
5803
+        pac = self.get_ticket_pac(ticket)
5804
+        self.assertIsNotNone(pac)
5805
+
5806
+    def test_rodc_validate_pac_request_true(self):
5807
+        creds = self._get_creds(replication_allowed=True,
5808
+                                revealed_to_rodc=True)
5809
+        tgt = self.get_tgt(creds, pac_request=True)
5810
+        tgt = self._modify_tgt(tgt, invalid=True, from_rodc=True)
5811
+
5812
+        tgt = self._validate_tgt(tgt, expected_error=0, expect_pac=None,
5813
+                                 expect_pac_attrs=False,
5814
+                                 expect_requester_sid=True)
5815
+
5816
+        ticket = self._run_tgs(tgt, expected_error=0, expect_pac=True)
5817
+
5818
+        pac = self.get_ticket_pac(ticket)
5819
+        self.assertIsNotNone(pac)
5820
+
5821
     def test_s4u2self_pac_request_none(self):
5822
         creds = self._get_creds()
5823
         tgt = self.get_tgt(creds, pac_request=None)
5824
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5825
index 94a4509f45a..2de898e73c2 100644
5826
--- selftest/knownfail_heimdal_kdc
5827
+++ selftest/knownfail_heimdal_kdc
5828
@@ -278,6 +278,12 @@
5829
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
5830
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
5831
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
5832
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false
5833
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none
5834
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true
5835
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false
5836
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none
5837
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true
5838
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
5839
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
5840
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
5841
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
5842
index c6dc1285837..73e64145e42 100644
5843
--- selftest/knownfail_mit_kdc
5844
+++ selftest/knownfail_mit_kdc
5845
@@ -422,6 +422,12 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
5846
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_existing
5847
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_sid_mismatch_nonexisting
5848
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_service_ticket
5849
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false
5850
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none
5851
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true
5852
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false
5853
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none
5854
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true
5855
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_authdata_no_pac
5856
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_no_pac
5857
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req
5858
-- 
5859
2.25.1
5860
5861
5862
From 925f63f3e464c0fdb91aaa5ed523a6ddb481bfff Mon Sep 17 00:00:00 2001
5863
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5864
Date: Thu, 25 Nov 2021 13:24:57 +1300
5865
Subject: [PATCH 43/99] Revert "CVE-2020-25719 s4/torture: Expect additional
5866
 PAC buffers"
5867
5868
This reverts commit fa4c9bcefdeed0a7106aab84df20b02435febc1f.
5869
5870
We should not be generating these additional PAC buffers for service
5871
tickets, only for TGTs.
5872
5873
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5874
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5875
(cherry picked from commit e61983c7f2c4daade83b237efb990d0c0645b3a3)
5876
---
5877
 selftest/knownfail_heimdal_kdc   | 39 ++++++++++++++++++++++++++++++++
5878
 source4/torture/rpc/remote_pac.c | 24 ++------------------
5879
 2 files changed, 41 insertions(+), 22 deletions(-)
5880
5881
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
5882
index 2de898e73c2..65e4fee9510 100644
5883
--- selftest/knownfail_heimdal_kdc
5884
+++ selftest/knownfail_heimdal_kdc
5885
@@ -297,3 +297,42 @@
5886
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
5887
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
5888
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
5889
+#
5890
+# PAC tests
5891
+#
5892
+^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc:local
5893
+^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc_ntvfs:local
5894
+^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc:local
5895
+^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc_ntvfs:local
5896
+^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc:local
5897
+^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc_ntvfs:local
5898
+^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc:local
5899
+^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc_ntvfs:local
5900
+^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc:local
5901
+^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc_ntvfs:local
5902
+^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc:local
5903
+^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc_ntvfs:local
5904
+^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2000dc
5905
+^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2003dc
5906
+^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008dc
5907
+^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008r2dc
5908
+^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2000dc
5909
+^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2003dc
5910
+^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008dc
5911
+^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008r2dc
5912
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2000dc
5913
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2003dc
5914
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008dc
5915
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008r2dc
5916
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2000dc
5917
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2003dc
5918
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008dc
5919
+^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008r2dc
5920
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2000dc
5921
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2003dc
5922
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008dc
5923
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008r2dc
5924
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2000dc
5925
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2003dc
5926
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008dc
5927
+^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008r2dc
5928
diff --git source4/torture/rpc/remote_pac.c source4/torture/rpc/remote_pac.c
5929
index c94decef5ce..14c23f674f1 100644
5930
--- source4/torture/rpc/remote_pac.c
5931
+++ source4/torture/rpc/remote_pac.c
5932
@@ -266,7 +266,7 @@ static bool test_PACVerify(struct torture_context *tctx,
5933
 				       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
5934
 	torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed");
5935
 
5936
-	num_pac_buffers = 7;
5937
+	num_pac_buffers = 5;
5938
 	if (expect_pac_upn_dns_info) {
5939
 		num_pac_buffers += 1;
5940
 	}
5941
@@ -323,18 +323,6 @@ static bool test_PACVerify(struct torture_context *tctx,
5942
 		       pac_buf->info != NULL,
5943
 		       "PAC_TYPE_TICKET_CHECKSUM info");
5944
 
5945
-	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_ATTRIBUTES_INFO);
5946
-	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_ATTRIBUTES_INFO");
5947
-	torture_assert(tctx,
5948
-		       pac_buf->info != NULL,
5949
-		       "PAC_TYPE_ATTRIBUTES_INFO info");
5950
-
5951
-	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_REQUESTER_SID);
5952
-	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_REQUESTER_SID");
5953
-	torture_assert(tctx,
5954
-		       pac_buf->info != NULL,
5955
-		       "PAC_TYPE_REQUESTER_SID info");
5956
-
5957
 	ok = netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name,
5958
 				   negotiate_flags, pac_data, session_info);
5959
 
5960
@@ -1094,7 +1082,7 @@ static bool test_S4U2Proxy(struct torture_context *tctx,
5961
 				       (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
5962
 	torture_assert(tctx, NDR_ERR_CODE_IS_SUCCESS(ndr_err), "ndr_pull_struct_blob of PAC_DATA structure failed");
5963
 
5964
-	num_pac_buffers = 9;
5965
+	num_pac_buffers = 7;
5966
 
5967
 	torture_assert_int_equal(tctx, pac_data_struct.version, 0, "version");
5968
 	torture_assert_int_equal(tctx, pac_data_struct.num_buffers, num_pac_buffers, "num_buffers");
5969
@@ -1134,14 +1122,6 @@ static bool test_S4U2Proxy(struct torture_context *tctx,
5970
 				 talloc_asprintf(tctx, "%s@%s", self_princ, cli_credentials_get_realm(credentials)),
5971
 				 "wrong transited_services[0]");
5972
 
5973
-	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_ATTRIBUTES_INFO);
5974
-	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_ATTRIBUTES_INFO");
5975
-	torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_ATTRIBUTES_INFO info");
5976
-
5977
-	pac_buf = get_pac_buffer(&pac_data_struct, PAC_TYPE_REQUESTER_SID);
5978
-	torture_assert_not_null(tctx, pac_buf, "PAC_TYPE_REQUESTER_SID");
5979
-	torture_assert_not_null(tctx, pac_buf->info, "PAC_TYPE_REQUESTER_SID info");
5980
-
5981
 	return netlogon_validate_pac(tctx, p, server_creds, secure_channel_type, test_machine_name,
5982
 				     negotiate_flags, pac_data, session_info);
5983
 }
5984
-- 
5985
2.25.1
5986
5987
5988
From 72afa2641c24bd18a32463f0b0de7e91feb54290 Mon Sep 17 00:00:00 2001
5989
From: Joseph Sutton <josephsutton@catalyst.net.nz>
5990
Date: Wed, 24 Nov 2021 20:42:22 +1300
5991
Subject: [PATCH 44/99] kdc: Don't include extra PAC buffers in service tickets
5992
5993
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
5994
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
5995
(cherry picked from commit 90025b6a4d250a15c0f988a9a9150ecfb63069ef)
5996
---
5997
 selftest/knownfail_heimdal_kdc | 42 ----------------------------------
5998
 source4/kdc/wdc-samba4.c       | 31 +++++++++++++++++--------
5999
 2 files changed, 21 insertions(+), 52 deletions(-)
6000
6001
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6002
index 65e4fee9510..ea08cb44122 100644
6003
--- selftest/knownfail_heimdal_kdc
6004
+++ selftest/knownfail_heimdal_kdc
6005
@@ -285,11 +285,8 @@
6006
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none
6007
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true
6008
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
6009
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
6010
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
6011
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
6012
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
6013
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid(?!_)
6014
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
6015
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
6016
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
6017
@@ -297,42 +294,3 @@
6018
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
6019
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
6020
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
6021
-#
6022
-# PAC tests
6023
-#
6024
-^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc:local
6025
-^samba4.blackbox.pkinit_pac.STEP1 remote.pac verification.ad_dc_ntvfs:local
6026
-^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc:local
6027
-^samba4.blackbox.pkinit_pac.netr-bdc-aes.verify-sig-aes.ad_dc_ntvfs:local
6028
-^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc:local
6029
-^samba4.blackbox.pkinit_pac.netr-mem-aes.s4u2proxy-aes.ad_dc_ntvfs:local
6030
-^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc:local
6031
-^samba4.blackbox.pkinit_pac.netr-mem-aes.verify-sig-aes.ad_dc_ntvfs:local
6032
-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc:local
6033
-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.s4u2proxy-arcfour.ad_dc_ntvfs:local
6034
-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc:local
6035
-^samba4.blackbox.pkinit_pac.netr-mem-arcfour.verify-sig-arcfour.ad_dc_ntvfs:local
6036
-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2000dc
6037
-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2003dc
6038
-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008dc
6039
-^samba4.rpc.pac on ncacn_np.netr-bdc-aes.verify-sig-aes.fl2008r2dc
6040
-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2000dc
6041
-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2003dc
6042
-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008dc
6043
-^samba4.rpc.pac on ncacn_np.netr-bdc-arcfour.verify-sig-arcfour.fl2008r2dc
6044
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2000dc
6045
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2003dc
6046
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008dc
6047
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.s4u2proxy-aes.fl2008r2dc
6048
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2000dc
6049
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2003dc
6050
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008dc
6051
-^samba4.rpc.pac on ncacn_np.netr-mem-aes.verify-sig-aes.fl2008r2dc
6052
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2000dc
6053
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2003dc
6054
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008dc
6055
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.s4u2proxy-arcfour.fl2008r2dc
6056
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2000dc
6057
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2003dc
6058
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008dc
6059
-^samba4.rpc.pac on ncacn_np.netr-mem-arcfour.verify-sig-arcfour.fl2008r2dc
6060
diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c
6061
index 8c3ce71529c..17af76f4edb 100644
6062
--- source4/kdc/wdc-samba4.c
6063
+++ source4/kdc/wdc-samba4.c
6064
@@ -132,6 +132,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
6065
 	krb5_error_code ret;
6066
 	NTSTATUS nt_status;
6067
 	bool is_in_db, is_untrusted;
6068
+	bool is_krbtgt;
6069
 	size_t num_types = 0;
6070
 	uint32_t *types = NULL;
6071
 	uint32_t forced_next_type = 0;
6072
@@ -471,7 +472,9 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
6073
 		goto out;
6074
 	}
6075
 
6076
-	if (!is_untrusted && !server_skdc_entry->is_krbtgt) {
6077
+	is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal);
6078
+
6079
+	if (!is_untrusted && !is_krbtgt) {
6080
 		/*
6081
 		 * The client may have requested no PAC when obtaining the
6082
 		 * TGT.
6083
@@ -576,17 +579,25 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
6084
 			type_blob = data_blob_const(&zero_byte, 1);
6085
 			break;
6086
 		case PAC_TYPE_ATTRIBUTES_INFO:
6087
-			/* just copy... */
6088
-			break;
6089
+			if (is_krbtgt) {
6090
+				/* just copy... */
6091
+				break;
6092
+			} else {
6093
+				continue;
6094
+			}
6095
 		case PAC_TYPE_REQUESTER_SID:
6096
-			/*
6097
-			 * Replace in the RODC case, otherwise
6098
-			 * requester_sid_blob is NULL and we just copy.
6099
-			 */
6100
-			if (requester_sid_blob != NULL) {
6101
-				type_blob = *requester_sid_blob;
6102
+			if (is_krbtgt) {
6103
+				/*
6104
+				 * Replace in the RODC case, otherwise
6105
+				 * requester_sid_blob is NULL and we just copy.
6106
+				 */
6107
+				if (requester_sid_blob != NULL) {
6108
+					type_blob = *requester_sid_blob;
6109
+				}
6110
+				break;
6111
+			} else {
6112
+				continue;
6113
 			}
6114
-			break;
6115
 		default:
6116
 			/* just copy... */
6117
 			break;
6118
-- 
6119
2.25.1
6120
6121
6122
From 29f15fe2d92831dcf5f4eb6d295df866ff689ee3 Mon Sep 17 00:00:00 2001
6123
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6124
Date: Thu, 25 Nov 2021 10:53:49 +1300
6125
Subject: [PATCH 45/99] kdc: Remove PAC_TYPE_ATTRIBUTES_INFO from RODC-issued
6126
 tickets
6127
6128
Windows ignores PAC_TYPE_ATTRIBUTES_INFO and always issues a PAC when
6129
presented with an RODC-issued TGT. By removing this PAC buffer from
6130
RODC-issued tickets, we ensure that an RODC-issued ticket will still
6131
result in a PAC if it is first renewed or validated by the main DC.
6132
6133
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6134
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6135
(cherry picked from commit 4b60e9516497c2e7f1545fe50887d0336b9893f2)
6136
---
6137
 selftest/knownfail_heimdal_kdc | 13 -------------
6138
 source4/kdc/wdc-samba4.c       |  2 +-
6139
 2 files changed, 1 insertion(+), 14 deletions(-)
6140
6141
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6142
index ea08cb44122..5e94cb63d7a 100644
6143
--- selftest/knownfail_heimdal_kdc
6144
+++ selftest/knownfail_heimdal_kdc
6145
@@ -274,16 +274,6 @@
6146
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
6147
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
6148
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
6149
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
6150
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
6151
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
6152
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_revealed
6153
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_false
6154
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_none
6155
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_renew_pac_request_true
6156
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_false
6157
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_none
6158
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_rodc_validate_pac_request_true
6159
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
6160
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
6161
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
6162
@@ -291,6 +281,3 @@
6163
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
6164
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
6165
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
6166
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
6167
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
6168
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_revealed
6169
diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c
6170
index 17af76f4edb..713720bcb99 100644
6171
--- source4/kdc/wdc-samba4.c
6172
+++ source4/kdc/wdc-samba4.c
6173
@@ -579,7 +579,7 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
6174
 			type_blob = data_blob_const(&zero_byte, 1);
6175
 			break;
6176
 		case PAC_TYPE_ATTRIBUTES_INFO:
6177
-			if (is_krbtgt) {
6178
+			if (!is_untrusted && is_krbtgt) {
6179
 				/* just copy... */
6180
 				break;
6181
 			} else {
6182
-- 
6183
2.25.1
6184
6185
6186
From d3436300745c41226d7ed146f269c929133f8f49 Mon Sep 17 00:00:00 2001
6187
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6188
Date: Thu, 25 Nov 2021 12:46:40 +1300
6189
Subject: [PATCH 46/99] tests/krb5: Add a test for S4U2Self with no
6190
 authorization data required
6191
6192
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6193
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6194
(cherry picked from commit 192d6edfe912105ec344dc554f872a24c03540a3)
6195
---
6196
 python/samba/tests/krb5/s4u_tests.py | 34 ++++++++++++++++++++++++++++
6197
 selftest/knownfail_heimdal_kdc       |  1 +
6198
 2 files changed, 35 insertions(+)
6199
6200
diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py
6201
index 2953766ef21..6ec9af11423 100755
6202
--- python/samba/tests/krb5/s4u_tests.py
6203
+++ python/samba/tests/krb5/s4u_tests.py
6204
@@ -324,6 +324,13 @@ class S4UKerberosTests(KDCBaseTest):
6205
                                    sname=service_sname,
6206
                                    etypes=etypes)
6207
 
6208
+        if not expected_error_mode:
6209
+            # Check that the ticket contains a PAC.
6210
+            ticket = kdc_exchange_dict['rep_ticket_creds']
6211
+
6212
+            pac = self.get_ticket_pac(ticket)
6213
+            self.assertIsNotNone(pac)
6214
+
6215
         # Ensure we used all the parameters given to us.
6216
         self.assertEqual({}, kdc_dict)
6217
 
6218
@@ -504,6 +511,24 @@ class S4UKerberosTests(KDCBaseTest):
6219
                     self.set_ticket_forwardable, flag=True)
6220
             })
6221
 
6222
+    # Do an S4U2Self where the service does not require authorization data. The
6223
+    # resulting ticket should still contain a PAC.
6224
+    def test_s4u2self_no_auth_data_required(self):
6225
+        self._run_s4u2self_test(
6226
+            {
6227
+                'client_opts': {
6228
+                    'not_delegated': False
6229
+                },
6230
+                'service_opts': {
6231
+                    'trusted_to_auth_for_delegation': True,
6232
+                    'no_auth_data_required': True
6233
+                },
6234
+                'kdc_options': 'forwardable',
6235
+                'modify_service_tgt_fn': functools.partial(
6236
+                    self.set_ticket_forwardable, flag=True),
6237
+                'expected_flags': 'forwardable'
6238
+            })
6239
+
6240
     def _run_delegation_test(self, kdc_dict):
6241
         client_opts = kdc_dict.pop('client_opts', None)
6242
         client_creds = self.get_cached_creds(
6243
@@ -654,6 +679,15 @@ class S4UKerberosTests(KDCBaseTest):
6244
                                    etypes=etypes,
6245
                                    additional_tickets=additional_tickets)
6246
 
6247
+        if not expected_error_mode:
6248
+            # Check whether the ticket contains a PAC.
6249
+            ticket = kdc_exchange_dict['rep_ticket_creds']
6250
+            pac = self.get_ticket_pac(ticket, expect_pac=expect_pac)
6251
+            if expect_pac:
6252
+                self.assertIsNotNone(pac)
6253
+            else:
6254
+                self.assertIsNone(pac)
6255
+
6256
         # Ensure we used all the parameters given to us.
6257
         self.assertEqual({}, kdc_dict)
6258
 
6259
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6260
index 5e94cb63d7a..2025032a278 100644
6261
--- selftest/knownfail_heimdal_kdc
6262
+++ selftest/knownfail_heimdal_kdc
6263
@@ -242,6 +242,7 @@
6264
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum
6265
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
6266
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
6267
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required
6268
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
6269
 #
6270
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
6271
-- 
6272
2.25.1
6273
6274
6275
From 8f97f78dd8023d88d76fc7de063661d94ebe5400 Mon Sep 17 00:00:00 2001
6276
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6277
Date: Tue, 23 Nov 2021 17:30:50 +1300
6278
Subject: [PATCH 47/99] heimdal:kdc: Always generate a PAC for S4U2Self
6279
6280
If we decided not to put a PAC into the ticket, mspac would be NULL
6281
here, and the resulting ticket would not contain a PAC. This could
6282
happen if there was a request to omit the PAC or the service did not
6283
require authorization data. Ensure that we always generate a PAC.
6284
6285
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6286
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6287
(cherry picked from commit 1f4f3018c5001b289b91959a72d00575c8fc0ac1)
6288
---
6289
 selftest/knownfail_heimdal_kdc |  2 --
6290
 source4/heimdal/kdc/krb5tgs.c  | 13 +++++++------
6291
 2 files changed, 7 insertions(+), 8 deletions(-)
6292
6293
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6294
index 2025032a278..53cc8e6b6a2 100644
6295
--- selftest/knownfail_heimdal_kdc
6296
+++ selftest/knownfail_heimdal_kdc
6297
@@ -242,7 +242,6 @@
6298
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum
6299
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
6300
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
6301
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required
6302
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
6303
 #
6304
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
6305
@@ -275,7 +274,6 @@
6306
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
6307
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
6308
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
6309
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
6310
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
6311
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
6312
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
6313
diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c
6314
index 6c5c51aa448..dc356b4daa5 100644
6315
--- source4/heimdal/kdc/krb5tgs.c
6316
+++ source4/heimdal/kdc/krb5tgs.c
6317
@@ -1846,12 +1846,13 @@ server_lookup:
6318
 	    if (mspac) {
6319
 		krb5_pac_free(context, mspac);
6320
 		mspac = NULL;
6321
-		ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac);
6322
-		if (ret) {
6323
-		    kdc_log(context, config, 0, "PAC generation failed for -- %s",
6324
-			    tpn);
6325
-		    goto out;
6326
-		}
6327
+	    }
6328
+
6329
+	    ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac);
6330
+	    if (ret) {
6331
+		kdc_log(context, config, 0, "PAC generation failed for -- %s",
6332
+			tpn);
6333
+		goto out;
6334
 	    }
6335
 
6336
 	    /*
6337
-- 
6338
2.25.1
6339
6340
6341
From 8585333a8ef54295a60faf47689a8978c0740361 Mon Sep 17 00:00:00 2001
6342
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6343
Date: Thu, 25 Nov 2021 09:29:42 +1300
6344
Subject: [PATCH 48/99] selftest: Properly check extra PAC buffers with Heimdal
6345
6346
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6347
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6348
(cherry picked from commit ee4aa21c487fa80082a548b2e4f115a791e30340)
6349
6350
[jsutton@samba.org Fixed conflicts]
6351
---
6352
 selftest/knownfail_heimdal_kdc | 12 ++++++++++++
6353
 source4/selftest/tests.py      |  2 +-
6354
 2 files changed, 13 insertions(+), 1 deletion(-)
6355
6356
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6357
index 53cc8e6b6a2..f71b95f306e 100644
6358
--- selftest/knownfail_heimdal_kdc
6359
+++ selftest/knownfail_heimdal_kdc
6360
@@ -241,8 +241,15 @@
6361
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum
6362
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum
6363
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
6364
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_client_not_delegated
6365
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
6366
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required
6367
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_forwardable
6368
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
6369
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_nonempty_allowed
6370
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_empty_allowed
6371
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_nonempty_allowed
6372
+^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_without_forwardable
6373
 #
6374
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
6375
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required
6376
@@ -274,6 +281,11 @@
6377
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
6378
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
6379
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
6380
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
6381
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_none
6382
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_true
6383
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid)
6384
+^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_revealed
6385
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
6386
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
6387
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
6388
6389
6390
From 65bb0e3201d60d87a3f228ea161644d9a5f918c5 Mon Sep 17 00:00:00 2001
6391
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6392
Date: Tue, 23 Nov 2021 19:38:35 +1300
6393
Subject: [PATCH 49/99] heimdal:kdc: Do not generate extra PAC buffers for
6394
 S4U2Self service ticket
6395
6396
Normally samba_wdc_get_pac() is used to generate the PAC for a TGT, but
6397
when generating a service ticket for S4U2Self, we want to avoid adding
6398
the additional PAC_ATTRIBUTES_INFO and PAC_REQUESTER_SID buffers.
6399
6400
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6401
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6402
(cherry picked from commit 9bd26804852d957f81cb311e5142f9190f9afa65)
6403
---
6404
 selftest/knownfail_heimdal_kdc     | 12 ------------
6405
 source4/heimdal/kdc/kerberos5.c    |  2 +-
6406
 source4/heimdal/kdc/krb5tgs.c      |  3 ++-
6407
 source4/heimdal/kdc/windc.c        |  5 +++--
6408
 source4/heimdal/kdc/windc_plugin.h |  2 ++
6409
 source4/kdc/wdc-samba4.c           | 11 ++++++++---
6410
 6 files changed, 16 insertions(+), 19 deletions(-)
6411
6412
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6413
index f71b95f306e..53cc8e6b6a2 100644
6414
--- selftest/knownfail_heimdal_kdc
6415
+++ selftest/knownfail_heimdal_kdc
6416
@@ -241,15 +241,8 @@
6417
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_unkeyed_service_checksum
6418
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_client_checksum
6419
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_zeroed_service_checksum
6420
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_client_not_delegated
6421
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_forwardable
6422
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_no_auth_data_required
6423
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_forwardable
6424
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_empty_allowed
6425
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_not_trusted_nonempty_allowed
6426
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_empty_allowed
6427
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_trusted_nonempty_allowed
6428
-^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_s4u2self_without_forwardable
6429
 #
6430
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_constrained_delegation_no_auth_data_required
6431
 ^samba.tests.krb5.s4u_tests.samba.tests.krb5.s4u_tests.S4UKerberosTests.test_rbcd_no_auth_data_required
6432
@@ -281,11 +274,6 @@
6433
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
6434
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
6435
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
6436
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_false
6437
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_none
6438
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_pac_request_true
6439
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_req(?!_invalid)
6440
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_s4u2self_rodc_revealed
6441
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
6442
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
6443
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
6444
diff --git source4/heimdal/kdc/kerberos5.c source4/heimdal/kdc/kerberos5.c
6445
index 9684364c519..a9e81336615 100644
6446
--- source4/heimdal/kdc/kerberos5.c
6447
+++ source4/heimdal/kdc/kerberos5.c
6448
@@ -1776,7 +1776,7 @@ _kdc_as_rep(krb5_context context,
6449
 
6450
 	sent_pac_request = send_pac_p(context, req, &pac_request);
6451
 
6452
-	ret = _kdc_pac_generate(context, client, pk_reply_key,
6453
+	ret = _kdc_pac_generate(context, client, server, pk_reply_key,
6454
 				sent_pac_request ? &pac_request : NULL,
6455
 				&p);
6456
 	if (ret) {
6457
diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c
6458
index dc356b4daa5..38dba8493ae 100644
6459
--- source4/heimdal/kdc/krb5tgs.c
6460
+++ source4/heimdal/kdc/krb5tgs.c
6461
@@ -1848,7 +1848,8 @@ server_lookup:
6462
 		mspac = NULL;
6463
 	    }
6464
 
6465
-	    ret = _kdc_pac_generate(context, s4u2self_impersonated_client, NULL, NULL, &mspac);
6466
+	    ret = _kdc_pac_generate(context, s4u2self_impersonated_client, server,
6467
+				    NULL, NULL, &mspac);
6468
 	    if (ret) {
6469
 		kdc_log(context, config, 0, "PAC generation failed for -- %s",
6470
 			tpn);
6471
diff --git source4/heimdal/kdc/windc.c source4/heimdal/kdc/windc.c
6472
index 93b973f576b..0a5ae5025ec 100644
6473
--- source4/heimdal/kdc/windc.c
6474
+++ source4/heimdal/kdc/windc.c
6475
@@ -73,6 +73,7 @@ krb5_kdc_windc_init(krb5_context context)
6476
 krb5_error_code
6477
 _kdc_pac_generate(krb5_context context,
6478
 		  hdb_entry_ex *client,
6479
+		  hdb_entry_ex *server,
6480
 		  const krb5_keyblock *pk_reply_key,
6481
 		  const krb5_boolean *pac_request,
6482
 		  krb5_pac *pac)
6483
@@ -88,9 +89,9 @@ _kdc_pac_generate(krb5_context context,
6484
 
6485
     if (windcft->pac_pk_generate != NULL && pk_reply_key != NULL)
6486
 	return (windcft->pac_pk_generate)(windcctx, context,
6487
-					  client, pk_reply_key,
6488
+					  client, server, pk_reply_key,
6489
 					  pac_request, pac);
6490
-    return (windcft->pac_generate)(windcctx, context, client,
6491
+    return (windcft->pac_generate)(windcctx, context, client, server,
6492
 				   pac_request, pac);
6493
 }
6494
 
6495
diff --git source4/heimdal/kdc/windc_plugin.h source4/heimdal/kdc/windc_plugin.h
6496
index c7f2bcb5ed9..d239d0260e7 100644
6497
--- source4/heimdal/kdc/windc_plugin.h
6498
+++ source4/heimdal/kdc/windc_plugin.h
6499
@@ -55,12 +55,14 @@ struct hdb_entry_ex;
6500
 typedef krb5_error_code
6501
 (*krb5plugin_windc_pac_generate)(void *, krb5_context,
6502
 				 struct hdb_entry_ex *, /* client */
6503
+				 struct hdb_entry_ex *, /* server */
6504
 				 const krb5_boolean *, /* pac_request */
6505
 				 krb5_pac *);
6506
 
6507
 typedef krb5_error_code
6508
 (*krb5plugin_windc_pac_pk_generate)(void *, krb5_context,
6509
 				    struct hdb_entry_ex *, /* client */
6510
+				    struct hdb_entry_ex *, /* server */
6511
 				    const krb5_keyblock *, /* pk_replykey */
6512
 				    const krb5_boolean *, /* pac_request */
6513
 				    krb5_pac *);
6514
diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c
6515
index 713720bcb99..b1d011c09a9 100644
6516
--- source4/kdc/wdc-samba4.c
6517
+++ source4/kdc/wdc-samba4.c
6518
@@ -37,6 +37,7 @@
6519
  */
6520
 static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
6521
 					 struct hdb_entry_ex *client,
6522
+					 struct hdb_entry_ex *server,
6523
 					 const krb5_keyblock *pk_reply_key,
6524
 					 const krb5_boolean *pac_request,
6525
 					 krb5_pac *pac)
6526
@@ -55,6 +56,7 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
6527
 	struct samba_kdc_entry *skdc_entry =
6528
 		talloc_get_type_abort(client->ctx,
6529
 		struct samba_kdc_entry);
6530
+	bool is_krbtgt;
6531
 
6532
 	mem_ctx = talloc_named(client->ctx, 0, "samba_get_pac context");
6533
 	if (!mem_ctx) {
6534
@@ -65,13 +67,15 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
6535
 		cred_ndr_ptr = &cred_ndr;
6536
 	}
6537
 
6538
+	is_krbtgt = krb5_principal_is_krbtgt(context, server->entry.principal);
6539
+
6540
 	nt_status = samba_kdc_get_pac_blobs(mem_ctx, skdc_entry,
6541
 					    &logon_blob,
6542
 					    cred_ndr_ptr,
6543
 					    &upn_blob,
6544
-					    &pac_attrs_blob,
6545
+					    is_krbtgt ? &pac_attrs_blob : NULL,
6546
 					    pac_request,
6547
-					    &requester_sid_blob,
6548
+					    is_krbtgt ? &requester_sid_blob : NULL,
6549
 					    NULL);
6550
 	if (!NT_STATUS_IS_OK(nt_status)) {
6551
 		talloc_free(mem_ctx);
6552
@@ -101,10 +105,11 @@ static krb5_error_code samba_wdc_get_pac(void *priv, krb5_context context,
6553
 
6554
 static krb5_error_code samba_wdc_get_pac_compat(void *priv, krb5_context context,
6555
 						struct hdb_entry_ex *client,
6556
+						struct hdb_entry_ex *server,
6557
 						const krb5_boolean *pac_request,
6558
 						krb5_pac *pac)
6559
 {
6560
-	return samba_wdc_get_pac(priv, context, client, NULL, pac_request, pac);
6561
+	return samba_wdc_get_pac(priv, context, client, server, NULL, pac_request, pac);
6562
 }
6563
 
6564
 static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
6565
-- 
6566
2.25.1
6567
6568
6569
From 49aafce0a705d47ffd4753ce6c6f452c4f7aa882 Mon Sep 17 00:00:00 2001
6570
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6571
Date: Wed, 24 Nov 2021 20:41:54 +1300
6572
Subject: [PATCH 50/99] kdc: Require that PAC_REQUESTER_SID buffer is present
6573
 for TGTs
6574
6575
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6576
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6577
6578
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
6579
Autobuild-Date(master): Tue Nov 30 03:33:26 UTC 2021 on sn-devel-184
6580
6581
(cherry picked from commit 38c5bad4a853b19fe9a51fb059e150b153c4632a)
6582
---
6583
 selftest/knownfail_heimdal_kdc | 6 ------
6584
 source4/kdc/wdc-samba4.c       | 6 ++++++
6585
 2 files changed, 6 insertions(+), 6 deletions(-)
6586
6587
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6588
index 53cc8e6b6a2..32465cb6042 100644
6589
--- selftest/knownfail_heimdal_kdc
6590
+++ selftest/knownfail_heimdal_kdc
6591
@@ -274,9 +274,3 @@
6592
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
6593
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
6594
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
6595
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
6596
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
6597
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
6598
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
6599
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
6600
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
6601
diff --git source4/kdc/wdc-samba4.c source4/kdc/wdc-samba4.c
6602
index b1d011c09a9..d7ce34fb3a9 100644
6603
--- source4/kdc/wdc-samba4.c
6604
+++ source4/kdc/wdc-samba4.c
6605
@@ -459,6 +459,12 @@ static krb5_error_code samba_wdc_reget_pac2(krb5_context context,
6606
 		talloc_free(mem_ctx);
6607
 		return EINVAL;
6608
 	}
6609
+	if (delegated_proxy_principal == NULL && requester_sid_idx == -1) {
6610
+		DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n"));
6611
+		SAFE_FREE(types);
6612
+		talloc_free(mem_ctx);
6613
+		return KRB5KDC_ERR_TGT_REVOKED;
6614
+	}
6615
 
6616
 	/*
6617
 	 * The server account may be set not to want the PAC.
6618
-- 
6619
2.25.1
6620
6621
6622
From 3fc519edec0159535baa0b659861b73f40632110 Mon Sep 17 00:00:00 2001
6623
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6624
Date: Tue, 7 Dec 2021 13:15:38 +1300
6625
Subject: [PATCH 51/99] kdc: Canonicalize realm for enterprise principals
6626
6627
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6628
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6629
6630
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
6631
Autobuild-Date(master): Tue Dec  7 04:54:35 UTC 2021 on sn-devel-184
6632
6633
(cherry picked from commit 8bd7b316bd61ef35f6e0baa0b65f0ef00910112c)
6634
---
6635
 selftest/knownfail.d/kdc-enterprise | 63 -----------------------------
6636
 selftest/knownfail_heimdal_kdc      |  3 --
6637
 selftest/knownfail_mit_kdc          | 36 +++++++++++++++++
6638
 source4/kdc/db-glue.c               | 24 +++++------
6639
 4 files changed, 47 insertions(+), 79 deletions(-)
6640
 delete mode 100644 selftest/knownfail.d/kdc-enterprise
6641
6642
diff --git selftest/knownfail.d/kdc-enterprise selftest/knownfail.d/kdc-enterprise
6643
deleted file mode 100644
6644
index c9b6c98a2ee..00000000000
6645
--- selftest/knownfail.d/kdc-enterprise
6646
+++ /dev/null
6647
@@ -1,63 +0,0 @@
6648
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise\(
6649
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm\(
6650
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\(
6651
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN\(
6652
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar\(
6653
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar\(
6654
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN\(
6655
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar\(
6656
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm\(
6657
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\(
6658
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\(
6659
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\(
6660
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\(
6661
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\(
6662
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\(
6663
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\(
6664
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName\(
6665
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm\(
6666
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\(
6667
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\(
6668
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\(
6669
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar\(
6670
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN\(
6671
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar\(
6672
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise\(
6673
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_NetbiosRealm\(
6674
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_NetbiosRealm_UPN\(
6675
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UPN\(
6676
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_NetbiosRealm\(
6677
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\(
6678
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\(
6679
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\(
6680
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName\(
6681
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_NetbiosRealm\(
6682
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\(
6683
-samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_UserCredentials_Enterprise_UpperUserName_UPN\(
6684
-
6685
-
6686
-
6687
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_AsReqSelf\(
6688
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_AsReqSelf\(
6689
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\(
6690
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_AsReqSelf\(
6691
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6692
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar_AsReqSelf\(
6693
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_AsReqSelf\(
6694
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar_AsReqSelf\(
6695
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\(
6696
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\(
6697
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\(
6698
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6699
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\(
6700
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\(
6701
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\(
6702
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6703
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_AsReqSelf\(
6704
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\(
6705
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\(
6706
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\(
6707
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6708
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\(
6709
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_AsReqSelf\(
6710
-^samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\(
6711
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
6712
index 32465cb6042..424a8b81c38 100644
6713
--- selftest/knownfail_heimdal_kdc
6714
+++ selftest/knownfail_heimdal_kdc
6715
@@ -5,9 +5,6 @@
6716
 #
6717
 # Heimdal currently fails the following MS-KILE client principal lookup
6718
 # tests
6719
-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_1_3
6720
-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_4
6721
-^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_5
6722
 ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_enterprise_principal_step_6_a
6723
 ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_enterprise_principal_step_6_b
6724
 ^samba.tests.krb5.ms_kile_client_principal_lookup_tests.samba.tests.krb5.ms_kile_client_principal_lookup_tests.MS_Kile_Client_Principal_Lookup_Tests.test_nt_principal_step_4_a
6725
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
6726
index 73e64145e42..4d685af7140 100644
6727
--- selftest/knownfail_mit_kdc
6728
+++ selftest/knownfail_mit_kdc
6729
@@ -56,17 +56,53 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
6730
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN\(
6731
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Canonicalize_UpperUserName_UPN_RemoveDollar\(
6732
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise\(
6733
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_AsReqSelf\(
6734
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm\(
6735
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_AsReqSelf\(
6736
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar\(
6737
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_RemoveDollar_AsReqSelf\(
6738
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN\(
6739
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_AsReqSelf\(
6740
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar\(
6741
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6742
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar\(
6743
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_RemoveDollar_AsReqSelf\(
6744
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN\(
6745
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_AsReqSelf\(
6746
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar\(
6747
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UPN_RemoveDollar_AsReqSelf\(
6748
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm\(
6749
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_AsReqSelf\(
6750
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar\(
6751
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_RemoveDollar_AsReqSelf\(
6752
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN\(
6753
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_AsReqSelf\(
6754
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar\(
6755
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6756
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm\(
6757
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_AsReqSelf\(
6758
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar\(
6759
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\(
6760
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN\(
6761
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_AsReqSelf\(
6762
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar\(
6763
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperRealm_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6764
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName\(
6765
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_AsReqSelf\(
6766
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm\(
6767
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_AsReqSelf\(
6768
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar\(
6769
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_RemoveDollar_AsReqSelf\(
6770
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN\(
6771
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_AsReqSelf\(
6772
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar\(
6773
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_NetbiosRealm_UPN_RemoveDollar_AsReqSelf\(
6774
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar\(
6775
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_RemoveDollar_AsReqSelf\(
6776
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN\(
6777
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_AsReqSelf\(
6778
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar\(
6779
+samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_Enterprise_UpperUserName_UPN_RemoveDollar_AsReqSelf\(
6780
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm\(
6781
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_RemoveDollar\(
6782
 samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_tests.KerberosASCanonicalizationTests.test_MachineCredentials_NetbiosRealm_UPN\(
6783
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
6784
index bed0ff773f9..5752ffb821c 100644
6785
--- source4/kdc/db-glue.c
6786
+++ source4/kdc/db-glue.c
6787
@@ -980,19 +980,17 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
6788
 			goto out;
6789
 		}
6790
 
6791
-		if (smb_krb5_principal_get_type(context, principal) != KRB5_NT_ENTERPRISE_PRINCIPAL) {
6792
-			/* While we have copied the client principal, tests
6793
-			 * show that Win2k3 returns the 'corrected' realm, not
6794
-			 * the client-specified realm.  This code attempts to
6795
-			 * replace the client principal's realm with the one
6796
-			 * we determine from our records */
6797
-			
6798
-			/* this has to be with malloc() */
6799
-			ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx));
6800
-			if (ret) {
6801
-				krb5_clear_error_message(context);
6802
-				goto out;
6803
-			}
6804
+		/* While we have copied the client principal, tests
6805
+		 * show that Win2k3 returns the 'corrected' realm, not
6806
+		 * the client-specified realm.  This code attempts to
6807
+		 * replace the client principal's realm with the one
6808
+		 * we determine from our records */
6809
+
6810
+		/* this has to be with malloc() */
6811
+		ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx));
6812
+		if (ret) {
6813
+			krb5_clear_error_message(context);
6814
+			goto out;
6815
 		}
6816
 	}
6817
 
6818
-- 
6819
2.25.1
6820
6821
6822
From 787405ef59b70cef011f005a6ed98898c5d43adb Mon Sep 17 00:00:00 2001
6823
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6824
Date: Tue, 14 Dec 2021 19:16:00 +1300
6825
Subject: [PATCH 52/99] tests/krb5: Correctly determine whether tickets are
6826
 service tickets
6827
6828
Previously we expected tickets to contain a ticket checksum if the sname
6829
was not the krbtgt. However, the ticket checksum should not be present
6830
if we are performing an AS-REQ to our own account. Now we determine a
6831
ticket is a service ticket only if the request is also a TGS-REQ.
6832
6833
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6834
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
6835
(cherry picked from commit 100be7eb8e70ba270a8e92957a5e47466160a901)
6836
---
6837
 python/samba/tests/krb5/compatability_tests.py | 10 ++++++----
6838
 python/samba/tests/krb5/kdc_base_test.py       |  2 +-
6839
 python/samba/tests/krb5/raw_testcase.py        | 18 ++++++++++--------
6840
 python/samba/tests/krb5/rodc_tests.py          |  4 ++--
6841
 4 files changed, 19 insertions(+), 15 deletions(-)
6842
6843
diff --git python/samba/tests/krb5/compatability_tests.py python/samba/tests/krb5/compatability_tests.py
6844
index ed2dc565b6d..65e9e3788d5 100755
6845
--- python/samba/tests/krb5/compatability_tests.py
6846
+++ python/samba/tests/krb5/compatability_tests.py
6847
@@ -132,13 +132,14 @@ class SimpleKerberosTests(KDCBaseTest):
6848
         tgt = self.get_tgt(user_creds)
6849
 
6850
         # Ensure the PAC contains the expected checksums.
6851
-        self.verify_ticket(tgt, key)
6852
+        self.verify_ticket(tgt, key, service_ticket=False)
6853
 
6854
         # Get a service ticket from the DC.
6855
         service_ticket = self.get_service_ticket(tgt, target_creds)
6856
 
6857
         # Ensure the PAC contains the expected checksums.
6858
-        self.verify_ticket(service_ticket, key, expect_ticket_checksum=True)
6859
+        self.verify_ticket(service_ticket, key, service_ticket=True,
6860
+                           expect_ticket_checksum=True)
6861
 
6862
     def test_mit_ticket_signature(self):
6863
         # Ensure that a DC does not issue tickets signed with its krbtgt key.
6864
@@ -152,13 +153,14 @@ class SimpleKerberosTests(KDCBaseTest):
6865
         tgt = self.get_tgt(user_creds)
6866
 
6867
         # Ensure the PAC contains the expected checksums.
6868
-        self.verify_ticket(tgt, key)
6869
+        self.verify_ticket(tgt, key, service_ticket=False)
6870
 
6871
         # Get a service ticket from the DC.
6872
         service_ticket = self.get_service_ticket(tgt, target_creds)
6873
 
6874
         # Ensure the PAC does not contain the expected checksums.
6875
-        self.verify_ticket(service_ticket, key, expect_ticket_checksum=False)
6876
+        self.verify_ticket(service_ticket, key, service_ticket=True,
6877
+                           expect_ticket_checksum=False)
6878
 
6879
     def as_pre_auth_req(self, creds, etypes):
6880
         user = creds.get_username()
6881
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
6882
index 6e96b982167..9506048ee2a 100644
6883
--- python/samba/tests/krb5/kdc_base_test.py
6884
+++ python/samba/tests/krb5/kdc_base_test.py
6885
@@ -1395,7 +1395,7 @@ class KDCBaseTest(RawKerberosTest):
6886
             krbtgt_creds = self.get_krbtgt_creds()
6887
         krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
6888
         self.verify_ticket(service_ticket_creds, krbtgt_key,
6889
-                           expect_pac=expect_pac,
6890
+                           service_ticket=True, expect_pac=expect_pac,
6891
                            expect_ticket_checksum=self.tkt_sig_support)
6892
 
6893
         self.tkt_cache[cache_key] = service_ticket_creds
6894
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
6895
index 14e655313fc..a2241707d44 100644
6896
--- python/samba/tests/krb5/raw_testcase.py
6897
+++ python/samba/tests/krb5/raw_testcase.py
6898
@@ -2587,7 +2587,11 @@ class RawKerberosTest(TestCaseInTempDir):
6899
             self.assertIsNotNone(ticket_decryption_key)
6900
 
6901
         if ticket_decryption_key is not None:
6902
-            self.verify_ticket(ticket_creds, krbtgt_keys, expect_pac=expect_pac,
6903
+            service_ticket = (not self.is_tgs(expected_sname)
6904
+                              and rep_msg_type == KRB_TGS_REP)
6905
+            self.verify_ticket(ticket_creds, krbtgt_keys,
6906
+                               service_ticket=service_ticket,
6907
+                               expect_pac=expect_pac,
6908
                                expect_ticket_checksum=expect_ticket_checksum
6909
                                or self.tkt_sig_support)
6910
 
6911
@@ -2624,14 +2628,14 @@ class RawKerberosTest(TestCaseInTempDir):
6912
                 expected_types.append(krb5pac.PAC_TYPE_DEVICE_INFO)
6913
                 expected_types.append(krb5pac.PAC_TYPE_DEVICE_CLAIMS_INFO)
6914
 
6915
-        if not self.is_tgs(expected_sname):
6916
+        if not self.is_tgs(expected_sname) and rep_msg_type == KRB_TGS_REP:
6917
             expected_types.append(krb5pac.PAC_TYPE_TICKET_CHECKSUM)
6918
 
6919
         require_strict = {krb5pac.PAC_TYPE_CLIENT_CLAIMS_INFO}
6920
         if not self.tkt_sig_support:
6921
             require_strict.add(krb5pac.PAC_TYPE_TICKET_CHECKSUM)
6922
 
6923
-        expect_extra_pac_buffers = rep_msg_type == KRB_AS_REP
6924
+        expect_extra_pac_buffers = self.is_tgs(expected_sname)
6925
 
6926
         expect_pac_attrs = kdc_exchange_dict['expect_pac_attrs']
6927
 
6928
@@ -3233,11 +3237,9 @@ class RawKerberosTest(TestCaseInTempDir):
6929
                                         ticket_blob)
6930
         self.assertEqual(expected_checksum, checksum)
6931
 
6932
-    def verify_ticket(self, ticket, krbtgt_keys, expect_pac=True,
6933
+    def verify_ticket(self, ticket, krbtgt_keys, service_ticket,
6934
+                      expect_pac=True,
6935
                       expect_ticket_checksum=True):
6936
-        # Check if the ticket is a TGT.
6937
-        is_tgt = self.is_tgt(ticket)
6938
-
6939
         # Decrypt the ticket.
6940
 
6941
         key = ticket.decryption_key
6942
@@ -3336,7 +3338,7 @@ class RawKerberosTest(TestCaseInTempDir):
6943
                                         kdc_ctype,
6944
                                         kdc_checksum)
6945
 
6946
-        if is_tgt:
6947
+        if not service_ticket:
6948
             self.assertNotIn(krb5pac.PAC_TYPE_TICKET_CHECKSUM, checksums)
6949
         else:
6950
             ticket_checksum, ticket_ctype = checksums.get(
6951
diff --git python/samba/tests/krb5/rodc_tests.py python/samba/tests/krb5/rodc_tests.py
6952
index 0e252d90262..83ee35d650a 100755
6953
--- python/samba/tests/krb5/rodc_tests.py
6954
+++ python/samba/tests/krb5/rodc_tests.py
6955
@@ -58,14 +58,14 @@ class RodcKerberosTests(KDCBaseTest):
6956
         tgt = self.get_tgt(user_creds, to_rodc=True)
6957
 
6958
         # Ensure the PAC contains the expected checksums.
6959
-        self.verify_ticket(tgt, rodc_key)
6960
+        self.verify_ticket(tgt, rodc_key, service_ticket=False)
6961
 
6962
         # Get a service ticket from the RODC.
6963
         service_ticket = self.get_service_ticket(tgt, target_creds,
6964
                                                  to_rodc=True)
6965
 
6966
         # Ensure the PAC contains the expected checksums.
6967
-        self.verify_ticket(service_ticket, rodc_key)
6968
+        self.verify_ticket(service_ticket, rodc_key, service_ticket=True)
6969
 
6970
 
6971
 if __name__ == "__main__":
6972
-- 
6973
2.25.1
6974
6975
6976
From c0977bee5b8c2f72cb5467e95a6ab034f696eee7 Mon Sep 17 00:00:00 2001
6977
From: Joseph Sutton <josephsutton@catalyst.net.nz>
6978
Date: Tue, 8 Feb 2022 12:15:36 +1300
6979
Subject: [PATCH 53/99] tests/krb5: Add helper function to modify ticket flags
6980
6981
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
6982
Reviewed-by: Stefan Metzmacher <metze@samba.org>
6983
(cherry picked from commit ded5115f73dff5b8b2f3212988e03f9dbe0c2aa3)
6984
---
6985
 python/samba/tests/krb5/kdc_base_test.py | 14 ++++++++++++++
6986
 python/samba/tests/krb5/kdc_tgs_tests.py | 18 ++----------------
6987
 python/samba/tests/krb5/s4u_tests.py     | 17 +++--------------
6988
 3 files changed, 19 insertions(+), 30 deletions(-)
6989
6990
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
6991
index 9506048ee2a..58b87eab25b 100644
6992
--- python/samba/tests/krb5/kdc_base_test.py
6993
+++ python/samba/tests/krb5/kdc_base_test.py
6994
@@ -1602,6 +1602,20 @@ class KDCBaseTest(RawKerberosTest):
6995
             enc_part, asn1Spec=krb5_asn1.EncTicketPart())
6996
         return enc_ticket_part
6997
 
6998
+    def modify_ticket_flag(self, enc_part, flag, value):
6999
+        self.assertIsInstance(value, bool)
7000
+
7001
+        flag = krb5_asn1.TicketFlags(flag)
7002
+        pos = len(tuple(flag)) - 1
7003
+
7004
+        flags = enc_part['flags']
7005
+        self.assertLessEqual(pos, len(flags))
7006
+
7007
+        new_flags = flags[:pos] + str(int(value)) + flags[pos + 1:]
7008
+        enc_part['flags'] = new_flags
7009
+
7010
+        return enc_part
7011
+
7012
     def get_objectSid(self, samdb, dn):
7013
         ''' Get the objectSID for a DN
7014
             Note: performs an Ldb query.
7015
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
7016
index 2923d53772a..8cd27dec2aa 100755
7017
--- python/samba/tests/krb5/kdc_tgs_tests.py
7018
+++ python/samba/tests/krb5/kdc_tgs_tests.py
7019
@@ -2177,14 +2177,7 @@ class KdcTgsTests(KDCBaseTest):
7020
 
7021
     def _modify_renewable(self, enc_part):
7022
         # Set the renewable flag.
7023
-        renewable_flag = krb5_asn1.TicketFlags('renewable')
7024
-        pos = len(tuple(renewable_flag)) - 1
7025
-
7026
-        flags = enc_part['flags']
7027
-        self.assertLessEqual(pos, len(flags))
7028
-
7029
-        new_flags = flags[:pos] + '1' + flags[pos + 1:]
7030
-        enc_part['flags'] = new_flags
7031
+        enc_part = self.modify_ticket_flag(enc_part, 'renewable', value=True)
7032
 
7033
         # Set the renew-till time to be in the future.
7034
         renew_till = self.get_KerberosTime(offset=100 * 60 * 60)
7035
@@ -2194,14 +2187,7 @@ class KdcTgsTests(KDCBaseTest):
7036
 
7037
     def _modify_invalid(self, enc_part):
7038
         # Set the invalid flag.
7039
-        invalid_flag = krb5_asn1.TicketFlags('invalid')
7040
-        pos = len(tuple(invalid_flag)) - 1
7041
-
7042
-        flags = enc_part['flags']
7043
-        self.assertLessEqual(pos, len(flags))
7044
-
7045
-        new_flags = flags[:pos] + '1' + flags[pos + 1:]
7046
-        enc_part['flags'] = new_flags
7047
+        enc_part = self.modify_ticket_flag(enc_part, 'invalid', value=True)
7048
 
7049
         # Set the ticket start time to be in the past.
7050
         past_time = self.get_KerberosTime(offset=-100 * 60 * 60)
7051
diff --git python/samba/tests/krb5/s4u_tests.py python/samba/tests/krb5/s4u_tests.py
7052
index 6ec9af11423..49dd89cd764 100755
7053
--- python/samba/tests/krb5/s4u_tests.py
7054
+++ python/samba/tests/krb5/s4u_tests.py
7055
@@ -1336,20 +1336,9 @@ class S4UKerberosTests(KDCBaseTest):
7056
                                     modify_pac_fn=modify_pac_fn)
7057
 
7058
     def set_ticket_forwardable(self, ticket, flag, update_pac_checksums=True):
7059
-        flag = '1' if flag else '0'
7060
-
7061
-        def modify_fn(enc_part):
7062
-            # Reset the forwardable flag
7063
-            forwardable_pos = (len(tuple(krb5_asn1.TicketFlags('forwardable')))
7064
-                               - 1)
7065
-
7066
-            flags = enc_part['flags']
7067
-            self.assertLessEqual(forwardable_pos, len(flags))
7068
-            enc_part['flags'] = (flags[:forwardable_pos] +
7069
-                                 flag +
7070
-                                 flags[forwardable_pos+1:])
7071
-
7072
-            return enc_part
7073
+        modify_fn = functools.partial(self.modify_ticket_flag,
7074
+                                      flag='forwardable',
7075
+                                      value=flag)
7076
 
7077
         if update_pac_checksums:
7078
             checksum_keys = self.get_krbtgt_checksum_key()
7079
-- 
7080
2.25.1
7081
7082
7083
From c0395578c50fbc4f1946e2f5a065d94f67212eb0 Mon Sep 17 00:00:00 2001
7084
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7085
Date: Wed, 15 Jun 2022 19:37:39 +1200
7086
Subject: [PATCH 55/99] CVE-2022-2031 s4:kdc: Add MIT support for
7087
 ATTRIBUTES_INFO and REQUESTER_SID PAC buffers
7088
7089
So that we do not confuse TGTs and kpasswd tickets, it is critical to
7090
check that the REQUESTER_SID buffer exists in TGTs, and to ensure that
7091
it is not propagated to service tickets.
7092
7093
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
7094
7095
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7096
7097
[jsutton@samba.org Brought in changes to add ATTRIBUTES_INFO and
7098
 REQUESTER_SID buffers to new PACs, and updated knownfails]
7099
7100
[jsutton@samba.org Adjusted MIT knownfails]
7101
---
7102
 selftest/knownfail_mit_kdc               | 17 -----
7103
 source4/kdc/mit-kdb/kdb_samba_policies.c |  5 +-
7104
 source4/kdc/mit_samba.c                  | 93 +++++++++++++++++++++++-
7105
 source4/kdc/mit_samba.h                  |  1 +
7106
 4 files changed, 94 insertions(+), 22 deletions(-)
7107
7108
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
7109
index 4d685af7140..108c6055d0c 100644
7110
--- selftest/knownfail_mit_kdc
7111
+++ selftest/knownfail_mit_kdc
7112
@@ -445,7 +445,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
7113
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
7114
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_authdata_no_pac
7115
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_no_pac
7116
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_none
7117
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_pac_request_true
7118
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_req
7119
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_renew_rodc_allowed_denied
7120
@@ -482,7 +481,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
7121
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_no_pac
7122
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rename
7123
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_invalid
7124
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_no_requester_sid
7125
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_allowed_denied
7126
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_denied
7127
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_no_krbtgt_link
7128
@@ -518,7 +516,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
7129
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_user2user_wrong_srealm
7130
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_authdata_no_pac
7131
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_no_pac
7132
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_none
7133
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_pac_request_true
7134
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_req
7135
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_validate_rodc_allowed_denied
7136
@@ -536,21 +533,17 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
7137
 #
7138
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_false
7139
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_false
7140
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_none
7141
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_renew_true
7142
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_false
7143
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_none
7144
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_missing_rodc_renew_true
7145
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_none
7146
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_false
7147
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_none
7148
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_renew_true
7149
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_false
7150
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_none
7151
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_rodc_renew_true
7152
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_pac_attrs_true
7153
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_false
7154
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_none
7155
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_pac_attrs_true
7156
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_pac_attrs
7157
 #
7158
@@ -571,21 +564,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
7159
 #
7160
 # PAC requester SID tests
7161
 #
7162
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_as_requester_sid
7163
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_existing
7164
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_logon_info_sid_mismatch_nonexisting
7165
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_existing
7166
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_requester_sid_mismatch_nonexisting
7167
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_req_from_rodc_no_requester_sid
7168
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid
7169
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_renew
7170
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_renew
7171
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_rodc_validate
7172
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_missing_validate
7173
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_renew
7174
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_renew
7175
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_rodc_validate
7176
-^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_requester_sid_validate
7177
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_existing
7178
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_only_sid_mismatch_nonexisting
7179
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_existing
7180
diff --git source4/kdc/mit-kdb/kdb_samba_policies.c source4/kdc/mit-kdb/kdb_samba_policies.c
7181
index 7bc9a7b3347..3b25fff410b 100644
7182
--- source4/kdc/mit-kdb/kdb_samba_policies.c
7183
+++ source4/kdc/mit-kdb/kdb_samba_policies.c
7184
@@ -159,6 +159,7 @@ done:
7185
 
7186
 static krb5_error_code ks_get_pac(krb5_context context,
7187
 				  krb5_db_entry *client,
7188
+				  krb5_db_entry *server,
7189
 				  krb5_keyblock *client_key,
7190
 				  krb5_pac *pac)
7191
 {
7192
@@ -173,6 +174,7 @@ static krb5_error_code ks_get_pac(krb5_context context,
7193
 	code = mit_samba_get_pac(mit_ctx,
7194
 				 context,
7195
 				 client,
7196
+				 server,
7197
 				 client_key,
7198
 				 pac);
7199
 	if (code != 0) {
7200
@@ -439,7 +441,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
7201
 	 */
7202
 	if (with_pac && generate_pac) {
7203
 		DBG_DEBUG("Generate PAC for AS-REQ [%s]\n", client_name);
7204
-		code = ks_get_pac(context, client_entry, client_key, &pac);
7205
+		code = ks_get_pac(context, client_entry, server, client_key, &pac);
7206
 		if (code != 0) {
7207
 			goto done;
7208
 		}
7209
@@ -490,6 +492,7 @@ krb5_error_code kdb_samba_db_sign_auth_data(krb5_context context,
7210
 
7211
 				code = ks_get_pac(context,
7212
 						  client_entry,
7213
+						  server,
7214
 						  client_key,
7215
 						  &pac);
7216
 				if (code != 0 && code != ENOENT) {
7217
diff --git source4/kdc/mit_samba.c source4/kdc/mit_samba.c
7218
index c2a604045d9..df2ba0a906f 100644
7219
--- source4/kdc/mit_samba.c
7220
+++ source4/kdc/mit_samba.c
7221
@@ -407,6 +407,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx,
7222
 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
7223
 		      krb5_context context,
7224
 		      krb5_db_entry *client,
7225
+		      krb5_db_entry *server,
7226
 		      krb5_keyblock *client_key,
7227
 		      krb5_pac *pac)
7228
 {
7229
@@ -417,9 +418,12 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
7230
 	DATA_BLOB **cred_ndr_ptr = NULL;
7231
 	DATA_BLOB cred_blob = data_blob_null;
7232
 	DATA_BLOB *pcred_blob = NULL;
7233
+	DATA_BLOB *pac_attrs_blob = NULL;
7234
+	DATA_BLOB *requester_sid_blob = NULL;
7235
 	NTSTATUS nt_status;
7236
 	krb5_error_code code;
7237
 	struct samba_kdc_entry *skdc_entry;
7238
+	bool is_krbtgt;
7239
 
7240
 	skdc_entry = talloc_get_type_abort(client->e_data,
7241
 					   struct samba_kdc_entry);
7242
@@ -438,12 +442,16 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
7243
 	}
7244
 #endif
7245
 
7246
+	is_krbtgt = ks_is_tgs_principal(smb_ctx, server->princ);
7247
+
7248
 	nt_status = samba_kdc_get_pac_blobs(tmp_ctx,
7249
 					    skdc_entry,
7250
 					    &logon_info_blob,
7251
 					    cred_ndr_ptr,
7252
 					    &upn_dns_info_blob,
7253
-					    NULL, NULL, NULL,
7254
+					    is_krbtgt ? &pac_attrs_blob : NULL,
7255
+					    NULL,
7256
+					    is_krbtgt ? &requester_sid_blob : NULL,
7257
 					    NULL);
7258
 	if (!NT_STATUS_IS_OK(nt_status)) {
7259
 		talloc_free(tmp_ctx);
7260
@@ -471,8 +479,8 @@ int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
7261
 				   logon_info_blob,
7262
 				   pcred_blob,
7263
 				   upn_dns_info_blob,
7264
-				   NULL,
7265
-				   NULL,
7266
+				   pac_attrs_blob,
7267
+				   requester_sid_blob,
7268
 				   NULL,
7269
 				   pac);
7270
 
7271
@@ -496,6 +504,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7272
 	DATA_BLOB *pac_blob = NULL;
7273
 	DATA_BLOB *upn_blob = NULL;
7274
 	DATA_BLOB *deleg_blob = NULL;
7275
+	DATA_BLOB *requester_sid_blob = NULL;
7276
 	struct samba_kdc_entry *client_skdc_entry = NULL;
7277
 	struct samba_kdc_entry *krbtgt_skdc_entry = NULL;
7278
 	struct samba_kdc_entry *server_skdc_entry = NULL;
7279
@@ -511,8 +520,12 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7280
 	ssize_t upn_dns_info_idx = -1;
7281
 	ssize_t srv_checksum_idx = -1;
7282
 	ssize_t kdc_checksum_idx = -1;
7283
+	ssize_t tkt_checksum_idx = -1;
7284
+	ssize_t attrs_info_idx = -1;
7285
+	ssize_t requester_sid_idx = -1;
7286
 	krb5_pac new_pac = NULL;
7287
 	bool ok;
7288
+	bool is_krbtgt;
7289
 
7290
 	/* Create a memory context early so code can use talloc_stackframe() */
7291
 	tmp_ctx = talloc_named(ctx, 0, "mit_samba_reget_pac context");
7292
@@ -520,6 +533,8 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7293
 		return ENOMEM;
7294
 	}
7295
 
7296
+	is_krbtgt = ks_is_tgs_principal(ctx, server->princ);
7297
+
7298
 	if (client != NULL) {
7299
 		client_skdc_entry =
7300
 			talloc_get_type_abort(client->e_data,
7301
@@ -578,7 +593,7 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7302
 						    NULL,
7303
 						    &upn_blob,
7304
 						    NULL, NULL,
7305
-						    NULL,
7306
+						    &requester_sid_blob,
7307
 						    NULL);
7308
 		if (!NT_STATUS_IS_OK(nt_status)) {
7309
 			code = EINVAL;
7310
@@ -737,6 +752,45 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7311
 			}
7312
 			kdc_checksum_idx = i;
7313
 			break;
7314
+		case PAC_TYPE_TICKET_CHECKSUM:
7315
+			if (tkt_checksum_idx != -1) {
7316
+				DBG_WARNING("ticket checksum type[%u] twice "
7317
+					    "[%zd] and [%zu]: \n",
7318
+					    types[i],
7319
+					    tkt_checksum_idx,
7320
+					    i);
7321
+				SAFE_FREE(types);
7322
+				code = EINVAL;
7323
+				goto done;
7324
+			}
7325
+			tkt_checksum_idx = i;
7326
+			break;
7327
+		case PAC_TYPE_ATTRIBUTES_INFO:
7328
+			if (attrs_info_idx != -1) {
7329
+				DBG_WARNING("attributes info type[%u] twice "
7330
+					    "[%zd] and [%zu]: \n",
7331
+					    types[i],
7332
+					    attrs_info_idx,
7333
+					    i);
7334
+				SAFE_FREE(types);
7335
+				code = EINVAL;
7336
+				goto done;
7337
+			}
7338
+			attrs_info_idx = i;
7339
+			break;
7340
+		case PAC_TYPE_REQUESTER_SID:
7341
+			if (requester_sid_idx != -1) {
7342
+				DBG_WARNING("requester sid type[%u] twice"
7343
+					    "[%zd] and [%zu]: \n",
7344
+					    types[i],
7345
+					    requester_sid_idx,
7346
+					    i);
7347
+				SAFE_FREE(types);
7348
+				code = EINVAL;
7349
+				goto done;
7350
+			}
7351
+			requester_sid_idx = i;
7352
+			break;
7353
 		default:
7354
 			continue;
7355
 		}
7356
@@ -766,6 +820,13 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7357
 		code = EINVAL;
7358
 		goto done;
7359
 	}
7360
+	if (!(flags & KRB5_KDB_FLAG_CONSTRAINED_DELEGATION) &&
7361
+	    requester_sid_idx == -1) {
7362
+		DEBUG(1, ("PAC_TYPE_REQUESTER_SID missing\n"));
7363
+		SAFE_FREE(types);
7364
+		code = KRB5KDC_ERR_TGT_REVOKED;
7365
+		goto done;
7366
+	}
7367
 
7368
 	/* Build an updated PAC */
7369
 	code = krb5_pac_init(context, &new_pac);
7370
@@ -831,6 +892,10 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7371
 			}
7372
 			break;
7373
 		case PAC_TYPE_SRV_CHECKSUM:
7374
+			if (requester_sid_idx == -1 && requester_sid_blob != NULL) {
7375
+				/* inject REQUESTER_SID */
7376
+				forced_next_type = PAC_TYPE_REQUESTER_SID;
7377
+			}
7378
 			/*
7379
 			 * This is generated in the main KDC code
7380
 			 */
7381
@@ -840,6 +905,26 @@ krb5_error_code mit_samba_reget_pac(struct mit_samba_context *ctx,
7382
 			 * This is generated in the main KDC code
7383
 			 */
7384
 			continue;
7385
+		case PAC_TYPE_ATTRIBUTES_INFO:
7386
+			if (!is_untrusted && is_krbtgt) {
7387
+				/* just copy... */
7388
+				break;
7389
+			}
7390
+
7391
+			continue;
7392
+		case PAC_TYPE_REQUESTER_SID:
7393
+			if (!is_krbtgt) {
7394
+				continue;
7395
+			}
7396
+
7397
+			/*
7398
+			 * Replace in the RODC case, otherwise
7399
+			 * requester_sid_blob is NULL and we just copy.
7400
+			 */
7401
+			if (requester_sid_blob != NULL) {
7402
+				type_blob = *requester_sid_blob;
7403
+			}
7404
+			break;
7405
 		default:
7406
 			/* just copy... */
7407
 			break;
7408
diff --git source4/kdc/mit_samba.h source4/kdc/mit_samba.h
7409
index 636c77ec97c..4431e82a1b2 100644
7410
--- source4/kdc/mit_samba.h
7411
+++ source4/kdc/mit_samba.h
7412
@@ -50,6 +50,7 @@ int mit_samba_get_nextkey(struct mit_samba_context *ctx,
7413
 int mit_samba_get_pac(struct mit_samba_context *smb_ctx,
7414
 		      krb5_context context,
7415
 		      krb5_db_entry *client,
7416
+		      krb5_db_entry *server,
7417
 		      krb5_keyblock *client_key,
7418
 		      krb5_pac *pac);
7419
 
7420
-- 
7421
2.25.1
7422
7423
7424
From 6843c44a45044808f90687f85183e7111a465d1f Mon Sep 17 00:00:00 2001
7425
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7426
Date: Thu, 16 Jun 2022 10:33:29 +1200
7427
Subject: [PATCH 56/99] heimdal:kdc: Accommodate NULL data parameter in
7428
 krb5_pac_get_buffer()
7429
7430
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7431
---
7432
 source4/heimdal/lib/krb5/pac.c | 10 ++++++----
7433
 1 file changed, 6 insertions(+), 4 deletions(-)
7434
7435
diff --git source4/heimdal/lib/krb5/pac.c source4/heimdal/lib/krb5/pac.c
7436
index 05bcc523080..100de904662 100644
7437
--- source4/heimdal/lib/krb5/pac.c
7438
+++ source4/heimdal/lib/krb5/pac.c
7439
@@ -394,10 +394,12 @@ krb5_pac_get_buffer(krb5_context context, krb5_pac p,
7440
 	if (p->pac->buffers[i].type != type)
7441
 	    continue;
7442
 
7443
-	ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len);
7444
-	if (ret) {
7445
-	    krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
7446
-	    return ret;
7447
+	if (data) {
7448
+	    ret = krb5_data_copy(data, (unsigned char *)p->data.data + offset, len);
7449
+	    if (ret) {
7450
+		krb5_set_error_message(context, ret, N_("malloc: out of memory", ""));
7451
+		return ret;
7452
+	    }
7453
 	}
7454
 	return 0;
7455
     }
7456
-- 
7457
2.25.1
7458
7459
7460
From 1b38a28bcaebdae0128518605a422a194747a60f Mon Sep 17 00:00:00 2001
7461
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7462
Date: Fri, 27 May 2022 19:17:02 +1200
7463
Subject: [PATCH 57/99] CVE-2022-2031 s4:kpasswd: Account for missing target
7464
 principal
7465
7466
This field is supposed to be optional.
7467
7468
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
7469
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
7470
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
7471
7472
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7473
Reviewed-by: Andreas Schneider <asn@samba.org>
7474
---
7475
 source4/kdc/kpasswd-service-mit.c | 22 ++++++++++++----------
7476
 1 file changed, 12 insertions(+), 10 deletions(-)
7477
7478
diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c
7479
index 2117c1c1696..b53c1a4618a 100644
7480
--- source4/kdc/kpasswd-service-mit.c
7481
+++ source4/kdc/kpasswd-service-mit.c
7482
@@ -143,16 +143,18 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
7483
 		return KRB5_KPASSWD_HARDERROR;
7484
 	}
7485
 
7486
-	target_realm = smb_krb5_principal_get_realm(
7487
-		mem_ctx, context, target_principal);
7488
-	code = krb5_unparse_name_flags(context,
7489
-				       target_principal,
7490
-				       KRB5_PRINCIPAL_UNPARSE_NO_REALM,
7491
-				       &target_name);
7492
-	if (code != 0) {
7493
-		DBG_WARNING("Failed to parse principal\n");
7494
-		*error_string = "String conversion failed";
7495
-		return KRB5_KPASSWD_HARDERROR;
7496
+	if (target_principal != NULL) {
7497
+		target_realm = smb_krb5_principal_get_realm(
7498
+			mem_ctx, context, target_principal);
7499
+		code = krb5_unparse_name_flags(context,
7500
+					       target_principal,
7501
+					       KRB5_PRINCIPAL_UNPARSE_NO_REALM,
7502
+					       &target_name);
7503
+		if (code != 0) {
7504
+			DBG_WARNING("Failed to parse principal\n");
7505
+			*error_string = "String conversion failed";
7506
+			return KRB5_KPASSWD_HARDERROR;
7507
+		}
7508
 	}
7509
 
7510
 	if ((target_name != NULL && target_realm == NULL) ||
7511
-- 
7512
2.25.1
7513
7514
7515
From f6c5a60336de8fd67a2ef371dd2ee4cf75c53904 Mon Sep 17 00:00:00 2001
7516
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7517
Date: Mon, 30 May 2022 19:17:41 +1200
7518
Subject: [PATCH 58/99] CVE-2022-2031 s4:kpasswd: Add MIT fallback for decoding
7519
 setpw structure
7520
7521
The target principal and realm fields of the setpw structure are
7522
supposed to be optional, but in MIT Kerberos they are mandatory. For
7523
better compatibility and ease of testing, fall back to parsing the
7524
simpler (containing only the new password) structure if the MIT function
7525
fails to decode it.
7526
7527
Although the target principal and realm fields should be optional, one
7528
is not supposed to specified without the other, so we don't have to deal
7529
with the case where only one is specified.
7530
7531
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
7532
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
7533
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
7534
7535
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7536
Reviewed-by: Andreas Schneider <asn@samba.org>
7537
---
7538
 source4/kdc/kpasswd-service-mit.c | 94 ++++++++++++++++++++++++++-----
7539
 1 file changed, 79 insertions(+), 15 deletions(-)
7540
7541
diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c
7542
index b53c1a4618a..9c4d2801669 100644
7543
--- source4/kdc/kpasswd-service-mit.c
7544
+++ source4/kdc/kpasswd-service-mit.c
7545
@@ -28,6 +28,7 @@
7546
 #include "kdc/kpasswd_glue.h"
7547
 #include "kdc/kpasswd-service.h"
7548
 #include "kdc/kpasswd-helper.h"
7549
+#include "../lib/util/asn1.h"
7550
 
7551
 #define RFC3244_VERSION 0xff80
7552
 
7553
@@ -35,6 +36,52 @@ krb5_error_code decode_krb5_setpw_req(const krb5_data *code,
7554
 				      krb5_data **password_out,
7555
 				      krb5_principal *target_out);
7556
 
7557
+/*
7558
+ * A fallback for when MIT refuses to parse a setpw structure without the
7559
+ * (optional) target principal and realm
7560
+ */
7561
+static bool decode_krb5_setpw_req_simple(TALLOC_CTX *mem_ctx,
7562
+					 const DATA_BLOB *decoded_data,
7563
+					 DATA_BLOB *clear_data)
7564
+{
7565
+	struct asn1_data *asn1 = NULL;
7566
+	bool ret;
7567
+
7568
+	asn1 = asn1_init(mem_ctx, 3);
7569
+	if (asn1 == NULL) {
7570
+		return false;
7571
+	}
7572
+
7573
+	ret = asn1_load(asn1, *decoded_data);
7574
+	if (!ret) {
7575
+		goto out;
7576
+	}
7577
+
7578
+	ret = asn1_start_tag(asn1, ASN1_SEQUENCE(0));
7579
+	if (!ret) {
7580
+		goto out;
7581
+	}
7582
+	ret = asn1_start_tag(asn1, ASN1_CONTEXT(0));
7583
+	if (!ret) {
7584
+		goto out;
7585
+	}
7586
+	ret = asn1_read_OctetString(asn1, mem_ctx, clear_data);
7587
+	if (!ret) {
7588
+		goto out;
7589
+	}
7590
+
7591
+	ret = asn1_end_tag(asn1);
7592
+	if (!ret) {
7593
+		goto out;
7594
+	}
7595
+	ret = asn1_end_tag(asn1);
7596
+
7597
+out:
7598
+	asn1_free(asn1);
7599
+
7600
+	return ret;
7601
+}
7602
+
7603
 static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
7604
 					       TALLOC_CTX *mem_ctx,
7605
 					       struct auth_session_info *session_info,
7606
@@ -93,9 +140,10 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
7607
 					    const char **error_string)
7608
 {
7609
 	krb5_context context = kdc->smb_krb5_context->krb5_context;
7610
+	DATA_BLOB clear_data;
7611
 	krb5_data k_dec_data;
7612
-	krb5_data *k_clear_data;
7613
-	krb5_principal target_principal;
7614
+	krb5_data *k_clear_data = NULL;
7615
+	krb5_principal target_principal = NULL;
7616
 	krb5_error_code code;
7617
 	DATA_BLOB password;
7618
 	char *target_realm = NULL;
7619
@@ -114,29 +162,45 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
7620
 	code = decode_krb5_setpw_req(&k_dec_data,
7621
 				     &k_clear_data,
7622
 				     &target_principal);
7623
-	if (code != 0) {
7624
-		DBG_WARNING("decode_krb5_setpw_req failed: %s\n",
7625
-			    error_message(code));
7626
-		ok = kpasswd_make_error_reply(mem_ctx,
7627
-					      KRB5_KPASSWD_MALFORMED,
7628
-					      "Failed to decode packet",
7629
-					      kpasswd_reply);
7630
+	if (code == 0) {
7631
+		clear_data.data = (uint8_t *)k_clear_data->data;
7632
+		clear_data.length = k_clear_data->length;
7633
+	} else {
7634
+		target_principal = NULL;
7635
+
7636
+		/*
7637
+		 * The MIT decode failed, so fall back to trying the simple
7638
+		 * case, without target_principal.
7639
+		 */
7640
+		ok = decode_krb5_setpw_req_simple(mem_ctx,
7641
+						  decoded_data,
7642
+						  &clear_data);
7643
 		if (!ok) {
7644
-			*error_string = "Failed to create reply";
7645
-			return KRB5_KPASSWD_HARDERROR;
7646
+			DBG_WARNING("decode_krb5_setpw_req failed: %s\n",
7647
+				    error_message(code));
7648
+			ok = kpasswd_make_error_reply(mem_ctx,
7649
+						      KRB5_KPASSWD_MALFORMED,
7650
+						      "Failed to decode packet",
7651
+						      kpasswd_reply);
7652
+			if (!ok) {
7653
+				*error_string = "Failed to create reply";
7654
+				return KRB5_KPASSWD_HARDERROR;
7655
+			}
7656
+			return 0;
7657
 		}
7658
-		return 0;
7659
 	}
7660
 
7661
 	ok = convert_string_talloc_handle(mem_ctx,
7662
 					  lpcfg_iconv_handle(kdc->task->lp_ctx),
7663
 					  CH_UTF8,
7664
 					  CH_UTF16,
7665
-					  (const char *)k_clear_data->data,
7666
-					  k_clear_data->length,
7667
+					  clear_data.data,
7668
+					  clear_data.length,
7669
 					  (void **)&password.data,
7670
 					  &password.length);
7671
-	krb5_free_data(context, k_clear_data);
7672
+	if (k_clear_data != NULL) {
7673
+		krb5_free_data(context, k_clear_data);
7674
+	}
7675
 	if (!ok) {
7676
 		DBG_WARNING("String conversion failed\n");
7677
 		*error_string = "String conversion failed";
7678
-- 
7679
2.25.1
7680
7681
7682
From 6305a55870287191ce4268f6af7fe278ca7f2a30 Mon Sep 17 00:00:00 2001
7683
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7684
Date: Thu, 26 May 2022 16:34:01 +1200
7685
Subject: [PATCH 59/99] CVE-2022-32744 tests/krb5: Correctly handle specifying
7686
 account kvno
7687
7688
The environment variable is a string, but we expect an integer.
7689
7690
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
7691
7692
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7693
Reviewed-by: Andreas Schneider <asn@samba.org>
7694
---
7695
 python/samba/tests/krb5/raw_testcase.py | 2 +-
7696
 1 file changed, 1 insertion(+), 1 deletion(-)
7697
7698
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
7699
index a2241707d44..4120edf93b9 100644
7700
--- python/samba/tests/krb5/raw_testcase.py
7701
+++ python/samba/tests/krb5/raw_testcase.py
7702
@@ -724,7 +724,7 @@ class RawKerberosTest(TestCaseInTempDir):
7703
                                 fallback_default=False,
7704
                                 allow_missing=kvno_allow_missing)
7705
         if kvno is not None:
7706
-            c.set_kvno(kvno)
7707
+            c.set_kvno(int(kvno))
7708
         aes256_key = self.env_get_var('AES256_KEY_HEX', prefix,
7709
                                       fallback_default=False,
7710
                                       allow_missing=aes256_allow_missing)
7711
-- 
7712
2.25.1
7713
7714
7715
From 8917979641abb03ef858ba72b652178475b6e918 Mon Sep 17 00:00:00 2001
7716
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7717
Date: Thu, 26 May 2022 20:52:04 +1200
7718
Subject: [PATCH 60/99] CVE-2022-2031 tests/krb5: Split out _make_tgs_request()
7719
7720
This allows us to make use of it in other tests.
7721
7722
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
7723
7724
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7725
Reviewed-by: Andreas Schneider <asn@samba.org>
7726
7727
[jsutton@samba.org Fixed conflicts due to having older version of
7728
 _make_tgs_request()]
7729
---
7730
 python/samba/tests/krb5/kdc_base_test.py | 77 ++++++++++++++++++++++++
7731
 python/samba/tests/krb5/kdc_tgs_tests.py | 76 -----------------------
7732
 2 files changed, 77 insertions(+), 76 deletions(-)
7733
7734
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
7735
index 58b87eab25b..2117663b26b 100644
7736
--- python/samba/tests/krb5/kdc_base_test.py
7737
+++ python/samba/tests/krb5/kdc_base_test.py
7738
@@ -67,6 +67,7 @@ from samba.tests.krb5.rfc4120_constants import (
7739
     AES256_CTS_HMAC_SHA1_96,
7740
     ARCFOUR_HMAC_MD5,
7741
     KDC_ERR_PREAUTH_REQUIRED,
7742
+    KDC_ERR_TGT_REVOKED,
7743
     KRB_AS_REP,
7744
     KRB_TGS_REP,
7745
     KRB_ERROR,
7746
@@ -1538,6 +1539,82 @@ class KDCBaseTest(RawKerberosTest):
7747
 
7748
         return ticket_creds
7749
 
7750
+    def _make_tgs_request(self, client_creds, service_creds, tgt,
7751
+                          pac_request=None, expect_pac=True,
7752
+                          expect_error=False,
7753
+                          expected_account_name=None,
7754
+                          expected_upn_name=None,
7755
+                          expected_sid=None):
7756
+        client_account = client_creds.get_username()
7757
+        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
7758
+                                          names=[client_account])
7759
+
7760
+        service_account = service_creds.get_username()
7761
+        sname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
7762
+                                          names=[service_account])
7763
+
7764
+        realm = service_creds.get_realm()
7765
+
7766
+        expected_crealm = realm
7767
+        expected_cname = cname
7768
+        expected_srealm = realm
7769
+        expected_sname = sname
7770
+
7771
+        expected_supported_etypes = service_creds.tgs_supported_enctypes
7772
+
7773
+        etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
7774
+
7775
+        kdc_options = str(krb5_asn1.KDCOptions('canonicalize'))
7776
+
7777
+        target_decryption_key = self.TicketDecryptionKey_from_creds(
7778
+            service_creds)
7779
+
7780
+        authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
7781
+
7782
+        if expect_error:
7783
+            expected_error_mode = KDC_ERR_TGT_REVOKED
7784
+            check_error_fn = self.generic_check_kdc_error
7785
+            check_rep_fn = None
7786
+        else:
7787
+            expected_error_mode = 0
7788
+            check_error_fn = None
7789
+            check_rep_fn = self.generic_check_kdc_rep
7790
+
7791
+        kdc_exchange_dict = self.tgs_exchange_dict(
7792
+            expected_crealm=expected_crealm,
7793
+            expected_cname=expected_cname,
7794
+            expected_srealm=expected_srealm,
7795
+            expected_sname=expected_sname,
7796
+            expected_account_name=expected_account_name,
7797
+            expected_upn_name=expected_upn_name,
7798
+            expected_sid=expected_sid,
7799
+            expected_supported_etypes=expected_supported_etypes,
7800
+            ticket_decryption_key=target_decryption_key,
7801
+            check_error_fn=check_error_fn,
7802
+            check_rep_fn=check_rep_fn,
7803
+            check_kdc_private_fn=self.generic_check_kdc_private,
7804
+            expected_error_mode=expected_error_mode,
7805
+            tgt=tgt,
7806
+            authenticator_subkey=authenticator_subkey,
7807
+            kdc_options=kdc_options,
7808
+            pac_request=pac_request,
7809
+            expect_pac=expect_pac,
7810
+            expect_edata=False)
7811
+
7812
+        rep = self._generic_kdc_exchange(kdc_exchange_dict,
7813
+                                         cname=cname,
7814
+                                         realm=realm,
7815
+                                         sname=sname,
7816
+                                         etypes=etypes)
7817
+        if expect_error:
7818
+            self.check_error_rep(rep, expected_error_mode)
7819
+
7820
+            return None
7821
+        else:
7822
+            self.check_reply(rep, KRB_TGS_REP)
7823
+
7824
+            return kdc_exchange_dict['rep_ticket_creds']
7825
+
7826
     # Named tuple to contain values of interest when the PAC is decoded.
7827
     PacData = namedtuple(
7828
         "PacData",
7829
diff --git python/samba/tests/krb5/kdc_tgs_tests.py python/samba/tests/krb5/kdc_tgs_tests.py
7830
index 8cd27dec2aa..e52f46152fa 100755
7831
--- python/samba/tests/krb5/kdc_tgs_tests.py
7832
+++ python/samba/tests/krb5/kdc_tgs_tests.py
7833
@@ -230,82 +230,6 @@ class KdcTgsTests(KDCBaseTest):
7834
             pac_data.account_sid,
7835
             "rep = {%s},%s" % (rep, pac_data))
7836
 
7837
-    def _make_tgs_request(self, client_creds, service_creds, tgt,
7838
-                          pac_request=None, expect_pac=True,
7839
-                          expect_error=False,
7840
-                          expected_account_name=None,
7841
-                          expected_upn_name=None,
7842
-                          expected_sid=None):
7843
-        client_account = client_creds.get_username()
7844
-        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
7845
-                                          names=[client_account])
7846
-
7847
-        service_account = service_creds.get_username()
7848
-        sname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
7849
-                                          names=[service_account])
7850
-
7851
-        realm = service_creds.get_realm()
7852
-
7853
-        expected_crealm = realm
7854
-        expected_cname = cname
7855
-        expected_srealm = realm
7856
-        expected_sname = sname
7857
-
7858
-        expected_supported_etypes = service_creds.tgs_supported_enctypes
7859
-
7860
-        etypes = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
7861
-
7862
-        kdc_options = str(krb5_asn1.KDCOptions('canonicalize'))
7863
-
7864
-        target_decryption_key = self.TicketDecryptionKey_from_creds(
7865
-            service_creds)
7866
-
7867
-        authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
7868
-
7869
-        if expect_error:
7870
-            expected_error_mode = KDC_ERR_TGT_REVOKED
7871
-            check_error_fn = self.generic_check_kdc_error
7872
-            check_rep_fn = None
7873
-        else:
7874
-            expected_error_mode = 0
7875
-            check_error_fn = None
7876
-            check_rep_fn = self.generic_check_kdc_rep
7877
-
7878
-        kdc_exchange_dict = self.tgs_exchange_dict(
7879
-            expected_crealm=expected_crealm,
7880
-            expected_cname=expected_cname,
7881
-            expected_srealm=expected_srealm,
7882
-            expected_sname=expected_sname,
7883
-            expected_account_name=expected_account_name,
7884
-            expected_upn_name=expected_upn_name,
7885
-            expected_sid=expected_sid,
7886
-            expected_supported_etypes=expected_supported_etypes,
7887
-            ticket_decryption_key=target_decryption_key,
7888
-            check_error_fn=check_error_fn,
7889
-            check_rep_fn=check_rep_fn,
7890
-            check_kdc_private_fn=self.generic_check_kdc_private,
7891
-            expected_error_mode=expected_error_mode,
7892
-            tgt=tgt,
7893
-            authenticator_subkey=authenticator_subkey,
7894
-            kdc_options=kdc_options,
7895
-            pac_request=pac_request,
7896
-            expect_pac=expect_pac,
7897
-            expect_edata=False)
7898
-
7899
-        rep = self._generic_kdc_exchange(kdc_exchange_dict,
7900
-                                         cname=cname,
7901
-                                         realm=realm,
7902
-                                         sname=sname,
7903
-                                         etypes=etypes)
7904
-        if expect_error:
7905
-            self.check_error_rep(rep, expected_error_mode)
7906
-
7907
-            return None
7908
-        else:
7909
-            self.check_reply(rep, KRB_TGS_REP)
7910
-
7911
-            return kdc_exchange_dict['rep_ticket_creds']
7912
-
7913
     def test_request(self):
7914
         client_creds = self.get_client_creds()
7915
         service_creds = self.get_service_creds()
7916
-- 
7917
2.25.1
7918
7919
7920
From 245d9a42329a1bfeb3db8431ef105e7758080e14 Mon Sep 17 00:00:00 2001
7921
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7922
Date: Tue, 24 May 2022 19:06:53 +1200
7923
Subject: [PATCH 61/99] CVE-2022-32744 tests/krb5: Correctly calculate salt for
7924
 pre-existing accounts
7925
7926
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
7927
7928
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7929
Reviewed-by: Andreas Schneider <asn@samba.org>
7930
---
7931
 python/samba/tests/krb5/kdc_base_test.py | 1 +
7932
 python/samba/tests/krb5/raw_testcase.py  | 1 +
7933
 2 files changed, 2 insertions(+)
7934
7935
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
7936
index 2117663b26b..685a6f71f88 100644
7937
--- python/samba/tests/krb5/kdc_base_test.py
7938
+++ python/samba/tests/krb5/kdc_base_test.py
7939
@@ -1048,6 +1048,7 @@ class KDCBaseTest(RawKerberosTest):
7940
 
7941
             kvno = int(res[0]['msDS-KeyVersionNumber'][0])
7942
             creds.set_kvno(kvno)
7943
+            creds.set_workstation(username[:-1])
7944
             creds.set_dn(dn)
7945
 
7946
             keys = self.get_keys(samdb, dn)
7947
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
7948
index 4120edf93b9..a9a98c36cbf 100644
7949
--- python/samba/tests/krb5/raw_testcase.py
7950
+++ python/samba/tests/krb5/raw_testcase.py
7951
@@ -834,6 +834,7 @@ class RawKerberosTest(TestCaseInTempDir):
7952
                                  allow_missing_password=allow_missing_password,
7953
                                  allow_missing_keys=allow_missing_keys)
7954
         c.set_gensec_features(c.get_gensec_features() | FEATURE_SEAL)
7955
+        c.set_workstation('')
7956
         return c
7957
 
7958
     def get_rodc_krbtgt_creds(self,
7959
-- 
7960
2.25.1
7961
7962
7963
From f7fad997cc06a14c9ffd101b26e16598f334148b Mon Sep 17 00:00:00 2001
7964
From: Joseph Sutton <josephsutton@catalyst.net.nz>
7965
Date: Tue, 24 May 2022 19:13:54 +1200
7966
Subject: [PATCH 62/99] CVE-2022-2031 tests/krb5: Add new definitions for
7967
 kpasswd
7968
7969
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
7970
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
7971
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
7972
7973
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
7974
Reviewed-by: Andreas Schneider <asn@samba.org>
7975
---
7976
 python/samba/tests/krb5/rfc4120.asn1         |  6 ++++++
7977
 python/samba/tests/krb5/rfc4120_constants.py | 13 +++++++++++++
7978
 python/samba/tests/krb5/rfc4120_pyasn1.py    | 13 ++++++++++++-
7979
 3 files changed, 31 insertions(+), 1 deletion(-)
7980
7981
diff --git python/samba/tests/krb5/rfc4120.asn1 python/samba/tests/krb5/rfc4120.asn1
7982
index e0831e1f86f..cac884be985 100644
7983
--- python/samba/tests/krb5/rfc4120.asn1
7984
+++ python/samba/tests/krb5/rfc4120.asn1
7985
@@ -567,6 +567,12 @@ PA-FX-FAST-REPLY ::= CHOICE {
7986
         ...
7987
 }
7988
 
7989
+ChangePasswdDataMS ::= SEQUENCE {
7990
+        newpasswd       [0] OCTET STRING,
7991
+        targname        [1] PrincipalName OPTIONAL,
7992
+        targrealm       [2] Realm OPTIONAL
7993
+}
7994
+
7995
 -- MS-KILE End
7996
 --
7997
 --
7998
diff --git python/samba/tests/krb5/rfc4120_constants.py python/samba/tests/krb5/rfc4120_constants.py
7999
index a9fdc5735dd..7f0f44500c7 100644
8000
--- python/samba/tests/krb5/rfc4120_constants.py
8001
+++ python/samba/tests/krb5/rfc4120_constants.py
8002
@@ -27,11 +27,13 @@ ARCFOUR_HMAC_MD5 = int(
8003
 
8004
 # Message types
8005
 KRB_ERROR = int(krb5_asn1.MessageTypeValues('krb-error'))
8006
+KRB_AP_REP = int(krb5_asn1.MessageTypeValues('krb-ap-rep'))
8007
 KRB_AP_REQ = int(krb5_asn1.MessageTypeValues('krb-ap-req'))
8008
 KRB_AS_REP = int(krb5_asn1.MessageTypeValues('krb-as-rep'))
8009
 KRB_AS_REQ = int(krb5_asn1.MessageTypeValues('krb-as-req'))
8010
 KRB_TGS_REP = int(krb5_asn1.MessageTypeValues('krb-tgs-rep'))
8011
 KRB_TGS_REQ = int(krb5_asn1.MessageTypeValues('krb-tgs-req'))
8012
+KRB_PRIV = int(krb5_asn1.MessageTypeValues('krb-priv'))
8013
 
8014
 # PAData types
8015
 PADATA_ENC_TIMESTAMP = int(
8016
@@ -76,6 +78,7 @@ KDC_ERR_TGT_REVOKED = 20
8017
 KDC_ERR_PREAUTH_FAILED = 24
8018
 KDC_ERR_PREAUTH_REQUIRED = 25
8019
 KDC_ERR_BAD_INTEGRITY = 31
8020
+KDC_ERR_TKT_EXPIRED = 32
8021
 KRB_ERR_TKT_NYV = 33
8022
 KDC_ERR_NOT_US = 35
8023
 KDC_ERR_BADMATCH = 36
8024
@@ -87,6 +90,16 @@ KDC_ERR_WRONG_REALM = 68
8025
 KDC_ERR_CLIENT_NAME_MISMATCH = 75
8026
 KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS = 93
8027
 
8028
+# Kpasswd error codes
8029
+KPASSWD_SUCCESS = 0
8030
+KPASSWD_MALFORMED = 1
8031
+KPASSWD_HARDERROR = 2
8032
+KPASSWD_AUTHERROR = 3
8033
+KPASSWD_SOFTERROR = 4
8034
+KPASSWD_ACCESSDENIED = 5
8035
+KPASSWD_BAD_VERSION = 6
8036
+KPASSWD_INITIAL_FLAG_NEEDED = 7
8037
+
8038
 # Extended error types
8039
 KERB_AP_ERR_TYPE_SKEW_RECOVERY = int(
8040
     krb5_asn1.KerbErrorDataTypeValues('kERB-AP-ERR-TYPE-SKEW-RECOVERY'))
8041
diff --git python/samba/tests/krb5/rfc4120_pyasn1.py python/samba/tests/krb5/rfc4120_pyasn1.py
8042
index 348dd8c63fb..3c02b0efbc1 100644
8043
--- python/samba/tests/krb5/rfc4120_pyasn1.py
8044
+++ python/samba/tests/krb5/rfc4120_pyasn1.py
8045
@@ -1,5 +1,5 @@
8046
 # Auto-generated by asn1ate v.0.6.1.dev0 from rfc4120.asn1
8047
-# (last modified on 2021-06-25 12:10:34.484667)
8048
+# (last modified on 2022-05-13 20:03:06.039817)
8049
 
8050
 # KerberosV5Spec2
8051
 from pyasn1.type import univ, char, namedtype, namedval, tag, constraint, useful
8052
@@ -364,6 +364,17 @@ Authenticator.componentType = namedtype.NamedTypes(
8053
 )
8054
 
8055
 
8056
+class ChangePasswdDataMS(univ.Sequence):
8057
+    pass
8058
+
8059
+
8060
+ChangePasswdDataMS.componentType = namedtype.NamedTypes(
8061
+    namedtype.NamedType('newpasswd', univ.OctetString().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 0))),
8062
+    namedtype.OptionalNamedType('targname', PrincipalName().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatConstructed, 1))),
8063
+    namedtype.OptionalNamedType('targrealm', Realm().subtype(explicitTag=tag.Tag(tag.tagClassContext, tag.tagFormatSimple, 2)))
8064
+)
8065
+
8066
+
8067
 class ChecksumTypeValues(univ.Integer):
8068
     pass
8069
 
8070
-- 
8071
2.25.1
8072
8073
8074
From 695c662bdc286d7a4699025f00656f8339ceecd8 Mon Sep 17 00:00:00 2001
8075
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8076
Date: Tue, 24 May 2022 19:17:45 +1200
8077
Subject: [PATCH 63/99] CVE-2022-2031 tests/krb5: Add methods to create ASN1
8078
 kpasswd structures
8079
8080
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
8081
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
8082
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
8083
8084
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8085
Reviewed-by: Andreas Schneider <asn@samba.org>
8086
---
8087
 python/samba/tests/krb5/raw_testcase.py | 95 +++++++++++++++++++++++++
8088
 1 file changed, 95 insertions(+)
8089
8090
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
8091
index a9a98c36cbf..df41dff688d 100644
8092
--- python/samba/tests/krb5/raw_testcase.py
8093
+++ python/samba/tests/krb5/raw_testcase.py
8094
@@ -54,6 +54,7 @@ from samba.tests.krb5.rfc4120_constants import (
8095
     KRB_AS_REP,
8096
     KRB_AS_REQ,
8097
     KRB_ERROR,
8098
+    KRB_PRIV,
8099
     KRB_TGS_REP,
8100
     KRB_TGS_REQ,
8101
     KU_AP_REQ_AUTH,
8102
@@ -63,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import (
8103
     KU_FAST_FINISHED,
8104
     KU_FAST_REP,
8105
     KU_FAST_REQ_CHKSUM,
8106
+    KU_KRB_PRIV,
8107
     KU_NON_KERB_CKSUM_SALT,
8108
     KU_TGS_REP_ENC_PART_SESSION,
8109
     KU_TGS_REP_ENC_PART_SUB_KEY,
8110
@@ -1780,6 +1782,99 @@ class RawKerberosTest(TestCaseInTempDir):
8111
             PA_S4U2Self_obj, asn1Spec=krb5_asn1.PA_S4U2Self())
8112
         return self.PA_DATA_create(PADATA_FOR_USER, pa_s4u2self)
8113
 
8114
+    def ChangePasswdDataMS_create(self,
8115
+                                  new_password,
8116
+                                  target_princ=None,
8117
+                                  target_realm=None):
8118
+        ChangePasswdDataMS_obj = {
8119
+            'newpasswd': new_password,
8120
+        }
8121
+        if target_princ is not None:
8122
+            ChangePasswdDataMS_obj['targname'] = target_princ
8123
+        if target_realm is not None:
8124
+            ChangePasswdDataMS_obj['targrealm'] = target_realm
8125
+
8126
+        change_password_data = self.der_encode(
8127
+            ChangePasswdDataMS_obj, asn1Spec=krb5_asn1.ChangePasswdDataMS())
8128
+
8129
+        return change_password_data
8130
+
8131
+    def KRB_PRIV_create(self,
8132
+                        subkey,
8133
+                        user_data,
8134
+                        s_address,
8135
+                        timestamp=None,
8136
+                        usec=None,
8137
+                        seq_number=None,
8138
+                        r_address=None):
8139
+        EncKrbPrivPart_obj = {
8140
+            'user-data': user_data,
8141
+            's-address': s_address,
8142
+        }
8143
+        if timestamp is not None:
8144
+            EncKrbPrivPart_obj['timestamp'] = timestamp
8145
+        if usec is not None:
8146
+            EncKrbPrivPart_obj['usec'] = usec
8147
+        if seq_number is not None:
8148
+            EncKrbPrivPart_obj['seq-number'] = seq_number
8149
+        if r_address is not None:
8150
+            EncKrbPrivPart_obj['r-address'] = r_address
8151
+
8152
+        enc_krb_priv_part = self.der_encode(
8153
+            EncKrbPrivPart_obj, asn1Spec=krb5_asn1.EncKrbPrivPart())
8154
+
8155
+        enc_data = self.EncryptedData_create(subkey,
8156
+                                             KU_KRB_PRIV,
8157
+                                             enc_krb_priv_part)
8158
+
8159
+        KRB_PRIV_obj = {
8160
+            'pvno': 5,
8161
+            'msg-type': KRB_PRIV,
8162
+            'enc-part': enc_data,
8163
+        }
8164
+
8165
+        krb_priv = self.der_encode(
8166
+            KRB_PRIV_obj, asn1Spec=krb5_asn1.KRB_PRIV())
8167
+
8168
+        return krb_priv
8169
+
8170
+    def kpasswd_create(self,
8171
+                       subkey,
8172
+                       user_data,
8173
+                       version,
8174
+                       seq_number,
8175
+                       ap_req,
8176
+                       local_address,
8177
+                       remote_address):
8178
+        self.assertIsNotNone(self.s, 'call self.connect() first')
8179
+
8180
+        timestamp, usec = self.get_KerberosTimeWithUsec()
8181
+
8182
+        krb_priv = self.KRB_PRIV_create(subkey,
8183
+                                        user_data,
8184
+                                        s_address=local_address,
8185
+                                        timestamp=timestamp,
8186
+                                        usec=usec,
8187
+                                        seq_number=seq_number,
8188
+                                        r_address=remote_address)
8189
+
8190
+        size = 6 + len(ap_req) + len(krb_priv)
8191
+        self.assertLess(size, 0x10000)
8192
+
8193
+        msg = bytearray()
8194
+        msg.append(size >> 8)
8195
+        msg.append(size & 0xff)
8196
+        msg.append(version >> 8)
8197
+        msg.append(version & 0xff)
8198
+        msg.append(len(ap_req) >> 8)
8199
+        msg.append(len(ap_req) & 0xff)
8200
+        # Note: for sets, there could be a little-endian four-byte length here.
8201
+
8202
+        msg.extend(ap_req)
8203
+        msg.extend(krb_priv)
8204
+
8205
+        return msg
8206
+
8207
     def _generic_kdc_exchange(self,
8208
                               kdc_exchange_dict,  # required
8209
                               cname=None,  # optional
8210
-- 
8211
2.25.1
8212
8213
8214
From ae7dd875cd4362ed4346716db493164c421b889f Mon Sep 17 00:00:00 2001
8215
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8216
Date: Tue, 24 May 2022 19:21:37 +1200
8217
Subject: [PATCH 64/99] CVE-2022-2031 tests/krb5: Add 'port' parameter to
8218
 connect()
8219
8220
This allows us to use the kpasswd port, 464.
8221
8222
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
8223
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
8224
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
8225
8226
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8227
Reviewed-by: Andreas Schneider <asn@samba.org>
8228
---
8229
 python/samba/tests/krb5/raw_testcase.py | 11 ++++++-----
8230
 1 file changed, 6 insertions(+), 5 deletions(-)
8231
8232
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
8233
index df41dff688d..421143781ae 100644
8234
--- python/samba/tests/krb5/raw_testcase.py
8235
+++ python/samba/tests/krb5/raw_testcase.py
8236
@@ -638,10 +638,11 @@ class RawKerberosTest(TestCaseInTempDir):
8237
         if self.do_hexdump:
8238
             sys.stderr.write("disconnect[%s]\n" % reason)
8239
 
8240
-    def _connect_tcp(self, host):
8241
-        tcp_port = 88
8242
+    def _connect_tcp(self, host, port=None):
8243
+        if port is None:
8244
+            port = 88
8245
         try:
8246
-            self.a = socket.getaddrinfo(host, tcp_port, socket.AF_UNSPEC,
8247
+            self.a = socket.getaddrinfo(host, port, socket.AF_UNSPEC,
8248
                                         socket.SOCK_STREAM, socket.SOL_TCP,
8249
                                         0)
8250
             self.s = socket.socket(self.a[0][0], self.a[0][1], self.a[0][2])
8251
@@ -654,9 +655,9 @@ class RawKerberosTest(TestCaseInTempDir):
8252
             self.s.close()
8253
             raise
8254
 
8255
-    def connect(self, host):
8256
+    def connect(self, host, port=None):
8257
         self.assertNotConnected()
8258
-        self._connect_tcp(host)
8259
+        self._connect_tcp(host, port)
8260
         if self.do_hexdump:
8261
             sys.stderr.write("connected[%s]\n" % host)
8262
 
8263
-- 
8264
2.25.1
8265
8266
8267
From 13fe7e013eccca2c86258084f4443ddb7abaf089 Mon Sep 17 00:00:00 2001
8268
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8269
Date: Tue, 24 May 2022 19:20:28 +1200
8270
Subject: [PATCH 65/99] CVE-2022-2031 tests/krb5: Add methods to send and
8271
 receive generic messages
8272
8273
This allows us to send and receive kpasswd messages, while avoiding the
8274
existing logic for encoding and decoding other Kerberos message types.
8275
8276
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
8277
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
8278
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
8279
8280
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8281
Reviewed-by: Andreas Schneider <asn@samba.org>
8282
---
8283
 python/samba/tests/krb5/raw_testcase.py | 44 +++++++++++++++----------
8284
 1 file changed, 27 insertions(+), 17 deletions(-)
8285
8286
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
8287
index 421143781ae..2aed5530455 100644
8288
--- python/samba/tests/krb5/raw_testcase.py
8289
+++ python/samba/tests/krb5/raw_testcase.py
8290
@@ -920,24 +920,28 @@ class RawKerberosTest(TestCaseInTempDir):
8291
         return blob
8292
 
8293
     def send_pdu(self, req, asn1_print=None, hexdump=None):
8294
+        k5_pdu = self.der_encode(
8295
+            req, native_decode=False, asn1_print=asn1_print, hexdump=False)
8296
+        self.send_msg(k5_pdu, hexdump=hexdump)
8297
+
8298
+    def send_msg(self, msg, hexdump=None):
8299
+        header = struct.pack('>I', len(msg))
8300
+        req_pdu = header
8301
+        req_pdu += msg
8302
+        self.hex_dump("send_msg", header, hexdump=hexdump)
8303
+        self.hex_dump("send_msg", msg, hexdump=hexdump)
8304
+
8305
         try:
8306
-            k5_pdu = self.der_encode(
8307
-                req, native_decode=False, asn1_print=asn1_print, hexdump=False)
8308
-            header = struct.pack('>I', len(k5_pdu))
8309
-            req_pdu = header
8310
-            req_pdu += k5_pdu
8311
-            self.hex_dump("send_pdu", header, hexdump=hexdump)
8312
-            self.hex_dump("send_pdu", k5_pdu, hexdump=hexdump)
8313
             while True:
8314
                 sent = self.s.send(req_pdu, 0)
8315
                 if sent == len(req_pdu):
8316
-                    break
8317
+                    return
8318
                 req_pdu = req_pdu[sent:]
8319
         except socket.error as e:
8320
-            self._disconnect("send_pdu: %s" % e)
8321
+            self._disconnect("send_msg: %s" % e)
8322
             raise
8323
         except IOError as e:
8324
-            self._disconnect("send_pdu: %s" % e)
8325
+            self._disconnect("send_msg: %s" % e)
8326
             raise
8327
 
8328
     def recv_raw(self, num_recv=0xffff, hexdump=None, timeout=None):
8329
@@ -963,16 +967,14 @@ class RawKerberosTest(TestCaseInTempDir):
8330
         return rep_pdu
8331
 
8332
     def recv_pdu_raw(self, asn1_print=None, hexdump=None, timeout=None):
8333
-        rep_pdu = None
8334
-        rep = None
8335
         raw_pdu = self.recv_raw(
8336
             num_recv=4, hexdump=hexdump, timeout=timeout)
8337
         if raw_pdu is None:
8338
-            return (None, None)
8339
+            return None
8340
         header = struct.unpack(">I", raw_pdu[0:4])
8341
         k5_len = header[0]
8342
         if k5_len == 0:
8343
-            return (None, "")
8344
+            return ""
8345
         missing = k5_len
8346
         rep_pdu = b''
8347
         while missing > 0:
8348
@@ -981,6 +983,14 @@ class RawKerberosTest(TestCaseInTempDir):
8349
             self.assertGreaterEqual(len(raw_pdu), 1)
8350
             rep_pdu += raw_pdu
8351
             missing = k5_len - len(rep_pdu)
8352
+        return rep_pdu
8353
+
8354
+    def recv_reply(self, asn1_print=None, hexdump=None, timeout=None):
8355
+        rep_pdu = self.recv_pdu_raw(asn1_print=asn1_print,
8356
+                                    hexdump=hexdump,
8357
+                                    timeout=timeout)
8358
+        if not rep_pdu:
8359
+            return None, rep_pdu
8360
         k5_raw = self.der_decode(
8361
             rep_pdu,
8362
             asn1Spec=None,
8363
@@ -1002,9 +1012,9 @@ class RawKerberosTest(TestCaseInTempDir):
8364
         return (rep, rep_pdu)
8365
 
8366
     def recv_pdu(self, asn1_print=None, hexdump=None, timeout=None):
8367
-        (rep, rep_pdu) = self.recv_pdu_raw(asn1_print=asn1_print,
8368
-                                           hexdump=hexdump,
8369
-                                           timeout=timeout)
8370
+        (rep, rep_pdu) = self.recv_reply(asn1_print=asn1_print,
8371
+                                         hexdump=hexdump,
8372
+                                         timeout=timeout)
8373
         return rep
8374
 
8375
     def assertIsConnected(self):
8376
-- 
8377
2.25.1
8378
8379
8380
From ca582250fcaf2ad3c585f7e31a1a4ce568b7ddb7 Mon Sep 17 00:00:00 2001
8381
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8382
Date: Tue, 24 May 2022 19:26:56 +1200
8383
Subject: [PATCH 66/99] tests/krb5: Fix enum typo
8384
8385
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8386
Reviewed-by: Andreas Schneider <asn@samba.org>
8387
---
8388
 python/samba/tests/krb5/kdc_base_test.py | 4 ++--
8389
 1 file changed, 2 insertions(+), 2 deletions(-)
8390
8391
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
8392
index 685a6f71f88..14f1d1a243d 100644
8393
--- python/samba/tests/krb5/kdc_base_test.py
8394
+++ python/samba/tests/krb5/kdc_base_test.py
8395
@@ -248,9 +248,9 @@ class KDCBaseTest(RawKerberosTest):
8396
            which is used by tearDownClass to clean up the created accounts.
8397
         '''
8398
         if ou is None:
8399
-            if account_type is account_type.COMPUTER:
8400
+            if account_type is self.AccountType.COMPUTER:
8401
                 guid = DS_GUID_COMPUTERS_CONTAINER
8402
-            elif account_type is account_type.SERVER:
8403
+            elif account_type is self.AccountType.SERVER:
8404
                 guid = DS_GUID_DOMAIN_CONTROLLERS_CONTAINER
8405
             else:
8406
                 guid = DS_GUID_USERS_CONTAINER
8407
-- 
8408
2.25.1
8409
8410
8411
From 5b030b176b853938b1895ec255e838147d8e7fa9 Mon Sep 17 00:00:00 2001
8412
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8413
Date: Tue, 24 May 2022 19:30:12 +1200
8414
Subject: [PATCH 67/99] tests/krb5: Add option for creating accounts with
8415
 expired passwords
8416
8417
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8418
Reviewed-by: Andreas Schneider <asn@samba.org>
8419
---
8420
 python/samba/tests/krb5/kdc_base_test.py | 10 ++++++++--
8421
 1 file changed, 8 insertions(+), 2 deletions(-)
8422
8423
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
8424
index 14f1d1a243d..777b3b4aaf1 100644
8425
--- python/samba/tests/krb5/kdc_base_test.py
8426
+++ python/samba/tests/krb5/kdc_base_test.py
8427
@@ -242,7 +242,8 @@ class KDCBaseTest(RawKerberosTest):
8428
 
8429
     def create_account(self, samdb, name, account_type=AccountType.USER,
8430
                        spn=None, upn=None, additional_details=None,
8431
-                       ou=None, account_control=0, add_dollar=True):
8432
+                       ou=None, account_control=0, add_dollar=True,
8433
+                       expired_password=False):
8434
         '''Create an account for testing.
8435
            The dn of the created account is added to self.accounts,
8436
            which is used by tearDownClass to clean up the created accounts.
8437
@@ -294,6 +295,8 @@ class KDCBaseTest(RawKerberosTest):
8438
             details["servicePrincipalName"] = spn
8439
         if upn is not None:
8440
             details["userPrincipalName"] = upn
8441
+        if expired_password:
8442
+            details["pwdLastSet"] = "0"
8443
         if additional_details is not None:
8444
             details.update(additional_details)
8445
         samdb.add(details)
8446
@@ -653,6 +656,7 @@ class KDCBaseTest(RawKerberosTest):
8447
             'revealed_to_rodc': False,
8448
             'revealed_to_mock_rodc': False,
8449
             'no_auth_data_required': False,
8450
+            'expired_password': False,
8451
             'supported_enctypes': None,
8452
             'not_delegated': False,
8453
             'delegation_to_spn': None,
8454
@@ -695,6 +699,7 @@ class KDCBaseTest(RawKerberosTest):
8455
                             revealed_to_rodc,
8456
                             revealed_to_mock_rodc,
8457
                             no_auth_data_required,
8458
+                            expired_password,
8459
                             supported_enctypes,
8460
                             not_delegated,
8461
                             delegation_to_spn,
8462
@@ -754,7 +759,8 @@ class KDCBaseTest(RawKerberosTest):
8463
                                         spn=spn,
8464
                                         additional_details=details,
8465
                                         account_control=user_account_control,
8466
-                                        add_dollar=add_dollar)
8467
+                                        add_dollar=add_dollar,
8468
+                                        expired_password=expired_password)
8469
 
8470
         keys = self.get_keys(samdb, dn)
8471
         self.creds_set_keys(creds, keys)
8472
-- 
8473
2.25.1
8474
8475
8476
From 5c41e20fae268e04aa05e821c7f388ea090727af Mon Sep 17 00:00:00 2001
8477
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8478
Date: Tue, 24 May 2022 19:34:59 +1200
8479
Subject: [PATCH 68/99] CVE-2022-2031 tests/krb5: Allow requesting a TGT to a
8480
 different sname and realm
8481
8482
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
8483
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
8484
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
8485
8486
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8487
Reviewed-by: Andreas Schneider <asn@samba.org>
8488
8489
[jsutton@samba.org Fixed conflict due to lacking rc4_support parameter]
8490
8491
[jsutton@samba.org Fixed conflicts due to lacking client_name_type and
8492
 expected_cname parameters]
8493
---
8494
 python/samba/tests/krb5/kdc_base_test.py | 19 +++++++++++++------
8495
 1 file changed, 13 insertions(+), 6 deletions(-)
8496
8497
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
8498
index 777b3b4aaf1..c0ca881985a 100644
8499
--- python/samba/tests/krb5/kdc_base_test.py
8500
+++ python/samba/tests/krb5/kdc_base_test.py
8501
@@ -1344,10 +1344,12 @@ class KDCBaseTest(RawKerberosTest):
8502
                            expected_flags=None, unexpected_flags=None,
8503
                            pac_request=True, expect_pac=True, fresh=False):
8504
         user_name = tgt.cname['name-string'][0]
8505
+        ticket_sname = tgt.sname
8506
         if target_name is None:
8507
             target_name = target_creds.get_username()[:-1]
8508
         cache_key = (user_name, target_name, service, to_rodc, kdc_options,
8509
                      pac_request, str(expected_flags), str(unexpected_flags),
8510
+                     str(ticket_sname),
8511
                      expect_pac)
8512
 
8513
         if not fresh:
8514
@@ -1414,6 +1416,7 @@ class KDCBaseTest(RawKerberosTest):
8515
                 expected_flags=None, unexpected_flags=None,
8516
                 expected_account_name=None, expected_upn_name=None,
8517
                 expected_sid=None,
8518
+                sname=None, realm=None,
8519
                 pac_request=True, expect_pac=True,
8520
                 expect_pac_attrs=None, expect_pac_attrs_pac_request=None,
8521
                 expect_requester_sid=None,
8522
@@ -1422,6 +1425,7 @@ class KDCBaseTest(RawKerberosTest):
8523
         cache_key = (user_name, to_rodc, kdc_options, pac_request,
8524
                      str(expected_flags), str(unexpected_flags),
8525
                      expected_account_name, expected_upn_name, expected_sid,
8526
+                     str(sname), str(realm),
8527
                      expect_pac, expect_pac_attrs,
8528
                      expect_pac_attrs_pac_request, expect_requester_sid)
8529
 
8530
@@ -1431,15 +1435,21 @@ class KDCBaseTest(RawKerberosTest):
8531
             if tgt is not None:
8532
                 return tgt
8533
 
8534
-        realm = creds.get_realm()
8535
+        if realm is None:
8536
+            realm = creds.get_realm()
8537
 
8538
         salt = creds.get_salt()
8539
 
8540
         etype = (AES256_CTS_HMAC_SHA1_96, ARCFOUR_HMAC_MD5)
8541
         cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
8542
                                           names=[user_name])
8543
-        sname = self.PrincipalName_create(name_type=NT_SRV_INST,
8544
-                                          names=['krbtgt', realm])
8545
+        if sname is None:
8546
+            sname = self.PrincipalName_create(name_type=NT_SRV_INST,
8547
+                                              names=['krbtgt', realm])
8548
+            expected_sname = self.PrincipalName_create(
8549
+                name_type=NT_SRV_INST, names=['krbtgt', realm.upper()])
8550
+        else:
8551
+            expected_sname = sname
8552
 
8553
         till = self.get_KerberosTime(offset=36000)
8554
 
8555
@@ -1505,9 +1515,6 @@ class KDCBaseTest(RawKerberosTest):
8556
 
8557
         expected_realm = realm.upper()
8558
 
8559
-        expected_sname = self.PrincipalName_create(
8560
-            name_type=NT_SRV_INST, names=['krbtgt', realm.upper()])
8561
-
8562
         rep, kdc_exchange_dict = self._test_as_exchange(
8563
             cname=cname,
8564
             realm=realm,
8565
-- 
8566
2.25.1
8567
8568
8569
From 668825ad56ff70715c626bc3209a6868409e4969 Mon Sep 17 00:00:00 2001
8570
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8571
Date: Tue, 24 May 2022 19:57:57 +1200
8572
Subject: [PATCH 69/99] CVE-2022-2031 tests/krb5: Add kpasswd_exchange() method
8573
8574
Now we can test the kpasswd service from Python.
8575
8576
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
8577
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
8578
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
8579
8580
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8581
Reviewed-by: Andreas Schneider <asn@samba.org>
8582
8583
[jsutton@samba.org Fixed conflicts in imports]
8584
---
8585
 python/samba/tests/krb5/raw_testcase.py | 264 ++++++++++++++++++++++--
8586
 1 file changed, 251 insertions(+), 13 deletions(-)
8587
8588
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
8589
index 2aed5530455..57010ae73bd 100644
8590
--- python/samba/tests/krb5/raw_testcase.py
8591
+++ python/samba/tests/krb5/raw_testcase.py
8592
@@ -26,6 +26,8 @@ import binascii
8593
 import itertools
8594
 import collections
8595
 
8596
+from enum import Enum
8597
+
8598
 from pyasn1.codec.der.decoder import decode as pyasn1_der_decode
8599
 from pyasn1.codec.der.encoder import encode as pyasn1_der_encode
8600
 from pyasn1.codec.native.decoder import decode as pyasn1_native_decode
8601
@@ -33,6 +35,8 @@ from pyasn1.codec.native.encoder import encode as pyasn1_native_encode
8602
 
8603
 from pyasn1.codec.ber.encoder import BitStringEncoder
8604
 
8605
+from pyasn1.error import PyAsn1Error
8606
+
8607
 from samba.credentials import Credentials
8608
 from samba.dcerpc import krb5pac, security
8609
 from samba.gensec import FEATURE_SEAL
8610
@@ -50,6 +54,7 @@ from samba.tests.krb5.rfc4120_constants import (
8611
     KDC_ERR_PREAUTH_FAILED,
8612
     KDC_ERR_UNKNOWN_CRITICAL_FAST_OPTIONS,
8613
     KERB_ERR_TYPE_EXTENDED,
8614
+    KRB_AP_REP,
8615
     KRB_AP_REQ,
8616
     KRB_AS_REP,
8617
     KRB_AS_REQ,
8618
@@ -59,6 +64,7 @@ from samba.tests.krb5.rfc4120_constants import (
8619
     KRB_TGS_REQ,
8620
     KU_AP_REQ_AUTH,
8621
     KU_AS_REP_ENC_PART,
8622
+    KU_AP_REQ_ENC_PART,
8623
     KU_ENC_CHALLENGE_KDC,
8624
     KU_FAST_ENC,
8625
     KU_FAST_FINISHED,
8626
@@ -73,6 +79,7 @@ from samba.tests.krb5.rfc4120_constants import (
8627
     KU_TGS_REQ_AUTH_DAT_SESSION,
8628
     KU_TGS_REQ_AUTH_DAT_SUBKEY,
8629
     KU_TICKET,
8630
+    NT_PRINCIPAL,
8631
     NT_SRV_INST,
8632
     NT_WELLKNOWN,
8633
     PADATA_ENCRYPTED_CHALLENGE,
8634
@@ -515,6 +522,10 @@ class KerberosTicketCreds:
8635
 class RawKerberosTest(TestCaseInTempDir):
8636
     """A raw Kerberos Test case."""
8637
 
8638
+    class KpasswdMode(Enum):
8639
+        SET = object()
8640
+        CHANGE = object()
8641
+
8642
     pac_checksum_types = {krb5pac.PAC_TYPE_SRV_CHECKSUM,
8643
                           krb5pac.PAC_TYPE_KDC_CHECKSUM,
8644
                           krb5pac.PAC_TYPE_TICKET_CHECKSUM}
8645
@@ -1886,6 +1897,224 @@ class RawKerberosTest(TestCaseInTempDir):
8646
 
8647
         return msg
8648
 
8649
+    def get_enc_part(self, obj, key, usage):
8650
+        self.assertElementEqual(obj, 'pvno', 5)
8651
+
8652
+        enc_part = obj['enc-part']
8653
+        self.assertElementEqual(enc_part, 'etype', key.etype)
8654
+        self.assertElementKVNO(enc_part, 'kvno', key.kvno)
8655
+
8656
+        enc_part = key.decrypt(usage, enc_part['cipher'])
8657
+
8658
+        return enc_part
8659
+
8660
+    def kpasswd_exchange(self,
8661
+                         ticket,
8662
+                         new_password,
8663
+                         expected_code,
8664
+                         expected_msg,
8665
+                         mode,
8666
+                         target_princ=None,
8667
+                         target_realm=None,
8668
+                         ap_options=None,
8669
+                         send_seq_number=True):
8670
+        if mode is self.KpasswdMode.SET:
8671
+            version = 0xff80
8672
+            user_data = self.ChangePasswdDataMS_create(new_password,
8673
+                                                       target_princ,
8674
+                                                       target_realm)
8675
+        elif mode is self.KpasswdMode.CHANGE:
8676
+            self.assertIsNone(target_princ,
8677
+                              'target_princ only valid for pw set')
8678
+            self.assertIsNone(target_realm,
8679
+                              'target_realm only valid for pw set')
8680
+
8681
+            version = 1
8682
+            user_data = new_password.encode('utf-8')
8683
+        else:
8684
+            self.fail(f'invalid mode {mode}')
8685
+
8686
+        subkey = self.RandomKey(kcrypto.Enctype.AES256)
8687
+
8688
+        if ap_options is None:
8689
+            ap_options = '0'
8690
+        ap_options = str(krb5_asn1.APOptions(ap_options))
8691
+
8692
+        kdc_exchange_dict = {
8693
+            'tgt': ticket,
8694
+            'authenticator_subkey': subkey,
8695
+            'auth_data': None,
8696
+            'ap_options': ap_options,
8697
+        }
8698
+
8699
+        if send_seq_number:
8700
+            seq_number = random.randint(0, 0xfffffffe)
8701
+        else:
8702
+            seq_number = None
8703
+
8704
+        ap_req = self.generate_ap_req(kdc_exchange_dict,
8705
+                                      None,
8706
+                                      req_body=None,
8707
+                                      armor=False,
8708
+                                      usage=KU_AP_REQ_AUTH,
8709
+                                      seq_number=seq_number)
8710
+
8711
+        self.connect(self.host, port=464)
8712
+        self.assertIsNotNone(self.s)
8713
+
8714
+        family = self.s.family
8715
+
8716
+        if family == socket.AF_INET:
8717
+            addr_type = 2  # IPv4
8718
+        elif family == socket.AF_INET6:
8719
+            addr_type = 24  # IPv6
8720
+        else:
8721
+            self.fail(f'unknown family {family}')
8722
+
8723
+        def create_address(ip):
8724
+            return {
8725
+                'addr-type': addr_type,
8726
+                'address': socket.inet_pton(family, ip),
8727
+            }
8728
+
8729
+        local_ip = self.s.getsockname()[0]
8730
+        local_address = create_address(local_ip)
8731
+
8732
+        # remote_ip = self.s.getpeername()[0]
8733
+        # remote_address = create_address(remote_ip)
8734
+
8735
+        # TODO: due to a bug (?), MIT Kerberos will not accept the request
8736
+        # unless r-address is set to our _local_ address. Heimdal, on the other
8737
+        # hand, requires the r-address is set to the remote address (as
8738
+        # expected). To avoid problems, avoid sending r-address for now.
8739
+        remote_address = None
8740
+
8741
+        msg = self.kpasswd_create(subkey,
8742
+                                  user_data,
8743
+                                  version,
8744
+                                  seq_number,
8745
+                                  ap_req,
8746
+                                  local_address,
8747
+                                  remote_address)
8748
+
8749
+        self.send_msg(msg)
8750
+        rep_pdu = self.recv_pdu_raw()
8751
+
8752
+        self._disconnect('transaction done')
8753
+
8754
+        self.assertIsNotNone(rep_pdu)
8755
+
8756
+        header = rep_pdu[:6]
8757
+        reply = rep_pdu[6:]
8758
+
8759
+        reply_len = (header[0] << 8) | header[1]
8760
+        reply_version = (header[2] << 8) | header[3]
8761
+        ap_rep_len = (header[4] << 8) | header[5]
8762
+
8763
+        self.assertEqual(reply_len, len(rep_pdu))
8764
+        self.assertEqual(1, reply_version)  # KRB5_KPASSWD_VERS_CHANGEPW
8765
+        self.assertLess(ap_rep_len, reply_len)
8766
+
8767
+        self.assertNotEqual(0x7e, rep_pdu[1])
8768
+        self.assertNotEqual(0x5e, rep_pdu[1])
8769
+
8770
+        if ap_rep_len:
8771
+            # We received an AP-REQ and KRB-PRIV as a response. This may or may
8772
+            # not indicate an error, depending on the status code.
8773
+            ap_rep = reply[:ap_rep_len]
8774
+            krb_priv = reply[ap_rep_len:]
8775
+
8776
+            key = ticket.session_key
8777
+
8778
+            ap_rep = self.der_decode(ap_rep, asn1Spec=krb5_asn1.AP_REP())
8779
+            self.assertElementEqual(ap_rep, 'msg-type', KRB_AP_REP)
8780
+            enc_part = self.get_enc_part(ap_rep, key, KU_AP_REQ_ENC_PART)
8781
+            enc_part = self.der_decode(
8782
+                enc_part, asn1Spec=krb5_asn1.EncAPRepPart())
8783
+
8784
+            self.assertElementPresent(enc_part, 'ctime')
8785
+            self.assertElementPresent(enc_part, 'cusec')
8786
+            # self.assertElementMissing(enc_part, 'subkey') # TODO
8787
+            # self.assertElementPresent(enc_part, 'seq-number') # TODO
8788
+
8789
+            try:
8790
+                krb_priv = self.der_decode(krb_priv, asn1Spec=krb5_asn1.KRB_PRIV())
8791
+            except PyAsn1Error:
8792
+                self.fail()
8793
+
8794
+            self.assertElementEqual(krb_priv, 'msg-type', KRB_PRIV)
8795
+            priv_enc_part = self.get_enc_part(krb_priv, subkey, KU_KRB_PRIV)
8796
+            priv_enc_part = self.der_decode(
8797
+                priv_enc_part, asn1Spec=krb5_asn1.EncKrbPrivPart())
8798
+
8799
+            self.assertElementMissing(priv_enc_part, 'timestamp')
8800
+            self.assertElementMissing(priv_enc_part, 'usec')
8801
+            # self.assertElementPresent(priv_enc_part, 'seq-number') # TODO
8802
+            # self.assertElementEqual(priv_enc_part, 's-address', remote_address) # TODO
8803
+            # self.assertElementMissing(priv_enc_part, 'r-address') # TODO
8804
+
8805
+            result_data = priv_enc_part['user-data']
8806
+        else:
8807
+            # We received a KRB-ERROR as a response, indicating an error.
8808
+            krb_error = self.der_decode(reply, asn1Spec=krb5_asn1.KRB_ERROR())
8809
+
8810
+            sname = self.PrincipalName_create(
8811
+                name_type=NT_PRINCIPAL,
8812
+                names=['kadmin', 'changepw'])
8813
+            realm = self.get_krbtgt_creds().get_realm().upper()
8814
+
8815
+            self.assertElementEqual(krb_error, 'pvno', 5)
8816
+            self.assertElementEqual(krb_error, 'msg-type', KRB_ERROR)
8817
+            self.assertElementMissing(krb_error, 'ctime')
8818
+            self.assertElementMissing(krb_error, 'usec')
8819
+            self.assertElementPresent(krb_error, 'stime')
8820
+            self.assertElementPresent(krb_error, 'susec')
8821
+
8822
+            error_code = krb_error['error-code']
8823
+            if isinstance(expected_code, int):
8824
+                self.assertEqual(error_code, expected_code)
8825
+            else:
8826
+                self.assertIn(error_code, expected_code)
8827
+
8828
+            self.assertElementMissing(krb_error, 'crealm')
8829
+            self.assertElementMissing(krb_error, 'cname')
8830
+            self.assertElementEqual(krb_error, 'realm', realm.encode('utf-8'))
8831
+            self.assertElementEqualPrincipal(krb_error, 'sname', sname)
8832
+            self.assertElementMissing(krb_error, 'e-text')
8833
+
8834
+            result_data = krb_error['e-data']
8835
+
8836
+        status = result_data[:2]
8837
+        message = result_data[2:]
8838
+
8839
+        status_code = (status[0] << 8) | status[1]
8840
+        if isinstance(expected_code, int):
8841
+            self.assertEqual(status_code, expected_code)
8842
+        else:
8843
+            self.assertIn(status_code, expected_code)
8844
+
8845
+        if not message:
8846
+            self.assertEqual(0, status_code,
8847
+                             'got an error result, but no message')
8848
+            return
8849
+
8850
+        # Check the first character of the message.
8851
+        if message[0]:
8852
+            if isinstance(expected_msg, bytes):
8853
+                self.assertEqual(message, expected_msg)
8854
+            else:
8855
+                self.assertIn(message, expected_msg)
8856
+        else:
8857
+            # We got AD password policy information.
8858
+            self.assertEqual(30, len(message))
8859
+
8860
+            (empty_bytes,
8861
+             min_length,
8862
+             history_length,
8863
+             properties,
8864
+             expire_time,
8865
+             min_age) = struct.unpack('>HIIIQQ', message)
8866
+
8867
     def _generic_kdc_exchange(self,
8868
                               kdc_exchange_dict,  # required
8869
                               cname=None,  # optional
8870
@@ -1996,7 +2225,7 @@ class RawKerberosTest(TestCaseInTempDir):
8871
             self.assertIsNotNone(generate_fast_fn)
8872
             fast_ap_req = generate_fast_armor_fn(kdc_exchange_dict,
8873
                                                  callback_dict,
8874
-                                                 req_body,
8875
+                                                 None,
8876
                                                  armor=True)
8877
 
8878
             fast_armor_type = kdc_exchange_dict['fast_armor_type']
8879
@@ -3211,31 +3440,39 @@ class RawKerberosTest(TestCaseInTempDir):
8880
                         kdc_exchange_dict,
8881
                         _callback_dict,
8882
                         req_body,
8883
-                        armor):
8884
+                        armor,
8885
+                        usage=None,
8886
+                        seq_number=None):
8887
+        req_body_checksum = None
8888
+
8889
         if armor:
8890
+            self.assertIsNone(req_body)
8891
+
8892
             tgt = kdc_exchange_dict['armor_tgt']
8893
             authenticator_subkey = kdc_exchange_dict['armor_subkey']
8894
-
8895
-            req_body_checksum = None
8896
         else:
8897
             tgt = kdc_exchange_dict['tgt']
8898
             authenticator_subkey = kdc_exchange_dict['authenticator_subkey']
8899
-            body_checksum_type = kdc_exchange_dict['body_checksum_type']
8900
 
8901
-            req_body_blob = self.der_encode(req_body,
8902
-                                            asn1Spec=krb5_asn1.KDC_REQ_BODY())
8903
+            if req_body is not None:
8904
+                body_checksum_type = kdc_exchange_dict['body_checksum_type']
8905
+
8906
+                req_body_blob = self.der_encode(
8907
+                    req_body, asn1Spec=krb5_asn1.KDC_REQ_BODY())
8908
 
8909
-            req_body_checksum = self.Checksum_create(tgt.session_key,
8910
-                                                     KU_TGS_REQ_AUTH_CKSUM,
8911
-                                                     req_body_blob,
8912
-                                                     ctype=body_checksum_type)
8913
+                req_body_checksum = self.Checksum_create(
8914
+                    tgt.session_key,
8915
+                    KU_TGS_REQ_AUTH_CKSUM,
8916
+                    req_body_blob,
8917
+                    ctype=body_checksum_type)
8918
 
8919
         auth_data = kdc_exchange_dict['auth_data']
8920
 
8921
         subkey_obj = None
8922
         if authenticator_subkey is not None:
8923
             subkey_obj = authenticator_subkey.export_obj()
8924
-        seq_number = random.randint(0, 0xfffffffe)
8925
+        if seq_number is None:
8926
+            seq_number = random.randint(0, 0xfffffffe)
8927
         (ctime, cusec) = self.get_KerberosTimeWithUsec()
8928
         authenticator_obj = self.Authenticator_create(
8929
             crealm=tgt.crealm,
8930
@@ -3250,7 +3487,8 @@ class RawKerberosTest(TestCaseInTempDir):
8931
             authenticator_obj,
8932
             asn1Spec=krb5_asn1.Authenticator())
8933
 
8934
-        usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH
8935
+        if usage is None:
8936
+            usage = KU_AP_REQ_AUTH if armor else KU_TGS_REQ_AUTH
8937
         authenticator = self.EncryptedData_create(tgt.session_key,
8938
                                                   usage,
8939
                                                   authenticator_blob)
8940
-- 
8941
2.25.1
8942
8943
8944
From 450ff39d1c9f538bd828b7b2bee75c88d3dc1ee2 Mon Sep 17 00:00:00 2001
8945
From: Joseph Sutton <josephsutton@catalyst.net.nz>
8946
Date: Tue, 24 May 2022 19:59:16 +1200
8947
Subject: [PATCH 71/99] CVE-2022-2031 tests/krb5: Add tests for kpasswd service
8948
8949
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
8950
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
8951
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
8952
8953
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
8954
Reviewed-by: Andreas Schneider <asn@samba.org>
8955
8956
[jsutton@samba.org Fixed conflicts in usage.py and knownfails; removed
8957
 MIT KDC 1.20-specific knownfails as it's not supported]
8958
8959
[jsutton@samba.org Fixed conflicts in usage.py, knownfails, and
8960
 tests.py]
8961
---
8962
 python/samba/tests/krb5/kdc_base_test.py |    4 +-
8963
 python/samba/tests/krb5/kpasswd_tests.py | 1021 ++++++++++++++++++++++
8964
 python/samba/tests/krb5/raw_testcase.py  |    8 +
8965
 python/samba/tests/usage.py              |    1 +
8966
 selftest/knownfail_heimdal_kdc           |   26 +
8967
 selftest/knownfail_mit_kdc               |   26 +
8968
 source4/selftest/tests.py                |    4 +
8969
 7 files changed, 1089 insertions(+), 1 deletion(-)
8970
 create mode 100755 python/samba/tests/krb5/kpasswd_tests.py
8971
8972
diff --git python/samba/tests/krb5/kdc_base_test.py python/samba/tests/krb5/kdc_base_test.py
8973
index c0ca881985a..f0306dde110 100644
8974
--- python/samba/tests/krb5/kdc_base_test.py
8975
+++ python/samba/tests/krb5/kdc_base_test.py
8976
@@ -1586,7 +1586,9 @@ class KDCBaseTest(RawKerberosTest):
8977
         authenticator_subkey = self.RandomKey(kcrypto.Enctype.AES256)
8978
 
8979
         if expect_error:
8980
-            expected_error_mode = KDC_ERR_TGT_REVOKED
8981
+            expected_error_mode = expect_error
8982
+            if expected_error_mode is True:
8983
+                expected_error_mode = KDC_ERR_TGT_REVOKED
8984
             check_error_fn = self.generic_check_kdc_error
8985
             check_rep_fn = None
8986
         else:
8987
diff --git python/samba/tests/krb5/kpasswd_tests.py python/samba/tests/krb5/kpasswd_tests.py
8988
new file mode 100755
8989
index 00000000000..3a6c7d818dc
8990
--- /dev/null
8991
+++ python/samba/tests/krb5/kpasswd_tests.py
8992
@@ -0,0 +1,1021 @@
8993
+#!/usr/bin/env python3
8994
+# Unix SMB/CIFS implementation.
8995
+# Copyright (C) Stefan Metzmacher 2020
8996
+# Copyright (C) Catalyst.Net Ltd
8997
+#
8998
+# This program is free software; you can redistribute it and/or modify
8999
+# it under the terms of the GNU General Public License as published by
9000
+# the Free Software Foundation; either version 3 of the License, or
9001
+# (at your option) any later version.
9002
+#
9003
+# This program is distributed in the hope that it will be useful,
9004
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
9005
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
9006
+# GNU General Public License for more details.
9007
+#
9008
+# You should have received a copy of the GNU General Public License
9009
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
9010
+#
9011
+
9012
+import os
9013
+import sys
9014
+
9015
+from functools import partial
9016
+
9017
+from samba import generate_random_password, unix2nttime
9018
+from samba.dcerpc import krb5pac, security
9019
+from samba.sd_utils import SDUtils
9020
+
9021
+from samba.tests.krb5.kdc_base_test import KDCBaseTest
9022
+from samba.tests.krb5.rfc4120_constants import (
9023
+    KDC_ERR_TGT_REVOKED,
9024
+    KDC_ERR_TKT_EXPIRED,
9025
+    KPASSWD_ACCESSDENIED,
9026
+    KPASSWD_HARDERROR,
9027
+    KPASSWD_INITIAL_FLAG_NEEDED,
9028
+    KPASSWD_MALFORMED,
9029
+    KPASSWD_SOFTERROR,
9030
+    KPASSWD_SUCCESS,
9031
+    NT_PRINCIPAL,
9032
+    NT_SRV_INST,
9033
+)
9034
+
9035
+sys.path.insert(0, 'bin/python')
9036
+os.environ['PYTHONUNBUFFERED'] = '1'
9037
+
9038
+global_asn1_print = False
9039
+global_hexdump = False
9040
+
9041
+
9042
+# Note: these tests do not pass on Windows, which returns different error codes
9043
+# to the ones we have chosen, and does not always return additional error data.
9044
+class KpasswdTests(KDCBaseTest):
9045
+
9046
+    def setUp(self):
9047
+        super().setUp()
9048
+        self.do_asn1_print = global_asn1_print
9049
+        self.do_hexdump = global_hexdump
9050
+
9051
+        samdb = self.get_samdb()
9052
+
9053
+        # Get the old 'dSHeuristics' if it was set
9054
+        dsheuristics = samdb.get_dsheuristics()
9055
+
9056
+        # Reset the 'dSHeuristics' as they were before
9057
+        self.addCleanup(samdb.set_dsheuristics, dsheuristics)
9058
+
9059
+        # Set the 'dSHeuristics' to activate the correct 'userPassword'
9060
+        # behaviour
9061
+        samdb.set_dsheuristics('000000001')
9062
+
9063
+        # Get the old 'minPwdAge'
9064
+        minPwdAge = samdb.get_minPwdAge()
9065
+
9066
+        # Reset the 'minPwdAge' as it was before
9067
+        self.addCleanup(samdb.set_minPwdAge, minPwdAge)
9068
+
9069
+        # Set it temporarily to '0'
9070
+        samdb.set_minPwdAge('0')
9071
+
9072
+    def _get_creds(self, expired=False):
9073
+        opts = {
9074
+            'expired_password': expired
9075
+        }
9076
+
9077
+        # Create the account.
9078
+        creds = self.get_cached_creds(account_type=self.AccountType.USER,
9079
+                                      opts=opts,
9080
+                                      use_cache=False)
9081
+
9082
+        return creds
9083
+
9084
+    def issued_by_rodc(self, ticket):
9085
+        krbtgt_creds = self.get_mock_rodc_krbtgt_creds()
9086
+
9087
+        krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
9088
+        checksum_keys = {
9089
+            krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key,
9090
+        }
9091
+
9092
+        return self.modified_ticket(
9093
+            ticket,
9094
+            new_ticket_key=krbtgt_key,
9095
+            checksum_keys=checksum_keys)
9096
+
9097
+    def get_kpasswd_sname(self):
9098
+        return self.PrincipalName_create(name_type=NT_PRINCIPAL,
9099
+                                         names=['kadmin', 'changepw'])
9100
+
9101
+    def get_ticket_lifetime(self, ticket):
9102
+        enc_part = ticket.ticket_private
9103
+
9104
+        authtime = enc_part['authtime']
9105
+        starttime = enc_part.get('starttime', authtime)
9106
+        endtime = enc_part['endtime']
9107
+
9108
+        starttime = self.get_EpochFromKerberosTime(starttime)
9109
+        endtime = self.get_EpochFromKerberosTime(endtime)
9110
+
9111
+        return endtime - starttime
9112
+
9113
+    def add_requester_sid(self, pac, sid):
9114
+        pac_buffers = pac.buffers
9115
+
9116
+        buffer_types = [pac_buffer.type for pac_buffer in pac_buffers]
9117
+        self.assertNotIn(krb5pac.PAC_TYPE_REQUESTER_SID, buffer_types)
9118
+
9119
+        requester_sid = krb5pac.PAC_REQUESTER_SID()
9120
+        requester_sid.sid = security.dom_sid(sid)
9121
+
9122
+        requester_sid_buffer = krb5pac.PAC_BUFFER()
9123
+        requester_sid_buffer.type = krb5pac.PAC_TYPE_REQUESTER_SID
9124
+        requester_sid_buffer.info = requester_sid
9125
+
9126
+        pac_buffers.append(requester_sid_buffer)
9127
+
9128
+        pac.buffers = pac_buffers
9129
+        pac.num_buffers += 1
9130
+
9131
+        return pac
9132
+
9133
+    # Test setting a password with kpasswd.
9134
+    def test_kpasswd_set(self):
9135
+        # Create an account for testing.
9136
+        creds = self._get_creds()
9137
+
9138
+        # Get an initial ticket to kpasswd.
9139
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9140
+                              kdc_options='0')
9141
+
9142
+        expected_code = KPASSWD_SUCCESS
9143
+        expected_msg = b'Password changed'
9144
+
9145
+        # Set the password.
9146
+        new_password = generate_random_password(32, 32)
9147
+        self.kpasswd_exchange(ticket,
9148
+                              new_password,
9149
+                              expected_code,
9150
+                              expected_msg,
9151
+                              mode=self.KpasswdMode.SET)
9152
+
9153
+        # Test the newly set password.
9154
+        creds.update_password(new_password)
9155
+        self.get_tgt(creds, fresh=True)
9156
+
9157
+    # Test changing a password with kpasswd.
9158
+    def test_kpasswd_change(self):
9159
+        # Create an account for testing.
9160
+        creds = self._get_creds()
9161
+
9162
+        # Get an initial ticket to kpasswd.
9163
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9164
+                              kdc_options='0')
9165
+
9166
+        expected_code = KPASSWD_SUCCESS
9167
+        expected_msg = b'Password changed'
9168
+
9169
+        # Change the password.
9170
+        new_password = generate_random_password(32, 32)
9171
+        self.kpasswd_exchange(ticket,
9172
+                              new_password,
9173
+                              expected_code,
9174
+                              expected_msg,
9175
+                              mode=self.KpasswdMode.CHANGE)
9176
+
9177
+        # Test the newly set password.
9178
+        creds.update_password(new_password)
9179
+        self.get_tgt(creds, fresh=True)
9180
+
9181
+    # Test kpasswd without setting the canonicalize option.
9182
+    def test_kpasswd_no_canonicalize(self):
9183
+        # Create an account for testing.
9184
+        creds = self._get_creds()
9185
+
9186
+        sname = self.get_kpasswd_sname()
9187
+
9188
+        # Get an initial ticket to kpasswd.
9189
+        ticket = self.get_tgt(creds, sname=sname,
9190
+                              kdc_options='0')
9191
+
9192
+        expected_code = KPASSWD_SUCCESS
9193
+        expected_msg = b'Password changed'
9194
+
9195
+        # Set the password.
9196
+        new_password = generate_random_password(32, 32)
9197
+        self.kpasswd_exchange(ticket,
9198
+                              new_password,
9199
+                              expected_code,
9200
+                              expected_msg,
9201
+                              mode=self.KpasswdMode.SET)
9202
+
9203
+        creds.update_password(new_password)
9204
+
9205
+        # Get an initial ticket to kpasswd.
9206
+        ticket = self.get_tgt(creds, sname=sname,
9207
+                              kdc_options='0')
9208
+
9209
+        # Change the password.
9210
+        new_password = generate_random_password(32, 32)
9211
+        self.kpasswd_exchange(ticket,
9212
+                              new_password,
9213
+                              expected_code,
9214
+                              expected_msg,
9215
+                              mode=self.KpasswdMode.CHANGE)
9216
+
9217
+    # Test kpasswd with the canonicalize option reset and a non-canonical
9218
+    # (by conversion to title case) realm.
9219
+    def test_kpasswd_no_canonicalize_realm_case(self):
9220
+        # Create an account for testing.
9221
+        creds = self._get_creds()
9222
+
9223
+        sname = self.get_kpasswd_sname()
9224
+        realm = creds.get_realm().capitalize()  # We use a title-cased realm.
9225
+
9226
+        # Get an initial ticket to kpasswd.
9227
+        ticket = self.get_tgt(creds, sname=sname,
9228
+                              realm=realm,
9229
+                              kdc_options='0')
9230
+
9231
+        expected_code = KPASSWD_SUCCESS
9232
+        expected_msg = b'Password changed'
9233
+
9234
+        # Set the password.
9235
+        new_password = generate_random_password(32, 32)
9236
+        self.kpasswd_exchange(ticket,
9237
+                              new_password,
9238
+                              expected_code,
9239
+                              expected_msg,
9240
+                              mode=self.KpasswdMode.SET)
9241
+
9242
+        creds.update_password(new_password)
9243
+
9244
+        # Get an initial ticket to kpasswd.
9245
+        ticket = self.get_tgt(creds, sname=sname,
9246
+                              realm=realm,
9247
+                              kdc_options='0')
9248
+
9249
+        # Change the password.
9250
+        new_password = generate_random_password(32, 32)
9251
+        self.kpasswd_exchange(ticket,
9252
+                              new_password,
9253
+                              expected_code,
9254
+                              expected_msg,
9255
+                              mode=self.KpasswdMode.CHANGE)
9256
+
9257
+    # Test kpasswd with the canonicalize option set.
9258
+    def test_kpasswd_canonicalize(self):
9259
+        # Create an account for testing.
9260
+        creds = self._get_creds()
9261
+
9262
+        # Get an initial ticket to kpasswd. We set the canonicalize flag here.
9263
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9264
+                              kdc_options='canonicalize')
9265
+
9266
+        expected_code = KPASSWD_SUCCESS
9267
+        expected_msg = b'Password changed'
9268
+
9269
+        # Set the password.
9270
+        new_password = generate_random_password(32, 32)
9271
+        self.kpasswd_exchange(ticket,
9272
+                              new_password,
9273
+                              expected_code,
9274
+                              expected_msg,
9275
+                              mode=self.KpasswdMode.SET)
9276
+
9277
+        creds.update_password(new_password)
9278
+
9279
+        # Get an initial ticket to kpasswd. We set the canonicalize flag here.
9280
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9281
+                              kdc_options='canonicalize')
9282
+
9283
+        # Change the password.
9284
+        new_password = generate_random_password(32, 32)
9285
+        self.kpasswd_exchange(ticket,
9286
+                              new_password,
9287
+                              expected_code,
9288
+                              expected_msg,
9289
+                              mode=self.KpasswdMode.CHANGE)
9290
+
9291
+    # Test kpasswd with the canonicalize option set and a non-canonical (by
9292
+    # conversion to title case) realm.
9293
+    def test_kpasswd_canonicalize_realm_case(self):
9294
+        # Create an account for testing.
9295
+        creds = self._get_creds()
9296
+
9297
+        sname = self.get_kpasswd_sname()
9298
+        realm = creds.get_realm().capitalize()  # We use a title-cased realm.
9299
+
9300
+        # Get an initial ticket to kpasswd. We set the canonicalize flag here.
9301
+        ticket = self.get_tgt(creds, sname=sname,
9302
+                              realm=realm,
9303
+                              kdc_options='canonicalize')
9304
+
9305
+        expected_code = KPASSWD_SUCCESS
9306
+        expected_msg = b'Password changed'
9307
+
9308
+        # Set the password.
9309
+        new_password = generate_random_password(32, 32)
9310
+        self.kpasswd_exchange(ticket,
9311
+                              new_password,
9312
+                              expected_code,
9313
+                              expected_msg,
9314
+                              mode=self.KpasswdMode.SET)
9315
+
9316
+        creds.update_password(new_password)
9317
+
9318
+        # Get an initial ticket to kpasswd. We set the canonicalize flag here.
9319
+        ticket = self.get_tgt(creds, sname=sname,
9320
+                              realm=realm,
9321
+                              kdc_options='canonicalize')
9322
+
9323
+        # Change the password.
9324
+        new_password = generate_random_password(32, 32)
9325
+        self.kpasswd_exchange(ticket,
9326
+                              new_password,
9327
+                              expected_code,
9328
+                              expected_msg,
9329
+                              mode=self.KpasswdMode.CHANGE)
9330
+
9331
+    # Test kpasswd rejects a password that does not meet complexity
9332
+    # requirements.
9333
+    def test_kpasswd_too_weak(self):
9334
+        # Create an account for testing.
9335
+        creds = self._get_creds()
9336
+
9337
+        # Get an initial ticket to kpasswd.
9338
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9339
+                              kdc_options='0')
9340
+
9341
+        expected_code = KPASSWD_SOFTERROR
9342
+        expected_msg = b'Password does not meet complexity requirements'
9343
+
9344
+        # Set the password.
9345
+        new_password = 'password'
9346
+        self.kpasswd_exchange(ticket,
9347
+                              new_password,
9348
+                              expected_code,
9349
+                              expected_msg,
9350
+                              mode=self.KpasswdMode.SET)
9351
+
9352
+        # Change the password.
9353
+        self.kpasswd_exchange(ticket,
9354
+                              new_password,
9355
+                              expected_code,
9356
+                              expected_msg,
9357
+                              mode=self.KpasswdMode.CHANGE)
9358
+
9359
+    # Test kpasswd rejects an empty new password.
9360
+    def test_kpasswd_empty(self):
9361
+        # Create an account for testing.
9362
+        creds = self._get_creds()
9363
+
9364
+        # Get an initial ticket to kpasswd.
9365
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9366
+                              kdc_options='0')
9367
+
9368
+        expected_code = KPASSWD_SOFTERROR, KPASSWD_HARDERROR
9369
+        expected_msg = (b'Password too short, password must be at least 7 '
9370
+                        b'characters long.',
9371
+                        b'String conversion failed!')
9372
+
9373
+        # Set the password.
9374
+        new_password = ''
9375
+        self.kpasswd_exchange(ticket,
9376
+                              new_password,
9377
+                              expected_code,
9378
+                              expected_msg,
9379
+                              mode=self.KpasswdMode.SET)
9380
+
9381
+        expected_code = KPASSWD_HARDERROR
9382
+        expected_msg = b'String conversion failed!'
9383
+
9384
+        # Change the password.
9385
+        self.kpasswd_exchange(ticket,
9386
+                              new_password,
9387
+                              expected_code,
9388
+                              expected_msg,
9389
+                              mode=self.KpasswdMode.CHANGE)
9390
+
9391
+    # Test kpasswd rejects a request that does not include a random sequence
9392
+    # number.
9393
+    def test_kpasswd_no_seq_number(self):
9394
+        # Create an account for testing.
9395
+        creds = self._get_creds()
9396
+
9397
+        # Get an initial ticket to kpasswd.
9398
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9399
+                              kdc_options='0')
9400
+
9401
+        expected_code = KPASSWD_HARDERROR
9402
+        expected_msg = b'gensec_unwrap failed - NT_STATUS_ACCESS_DENIED\n'
9403
+
9404
+        # Set the password.
9405
+        new_password = generate_random_password(32, 32)
9406
+        self.kpasswd_exchange(ticket,
9407
+                              new_password,
9408
+                              expected_code,
9409
+                              expected_msg,
9410
+                              mode=self.KpasswdMode.SET,
9411
+                              send_seq_number=False)
9412
+
9413
+        # Change the password.
9414
+        self.kpasswd_exchange(ticket,
9415
+                              new_password,
9416
+                              expected_code,
9417
+                              expected_msg,
9418
+                              mode=self.KpasswdMode.CHANGE,
9419
+                              send_seq_number=False)
9420
+
9421
+    # Test kpasswd rejects a ticket issued by an RODC.
9422
+    def test_kpasswd_from_rodc(self):
9423
+        # Create an account for testing.
9424
+        creds = self._get_creds()
9425
+
9426
+        # Get an initial ticket to kpasswd.
9427
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9428
+                              kdc_options='0')
9429
+
9430
+        # Have the ticket be issued by the RODC.
9431
+        ticket = self.issued_by_rodc(ticket)
9432
+
9433
+        expected_code = KPASSWD_HARDERROR
9434
+        expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n'
9435
+
9436
+        # Set the password.
9437
+        new_password = generate_random_password(32, 32)
9438
+        self.kpasswd_exchange(ticket,
9439
+                              new_password,
9440
+                              expected_code,
9441
+                              expected_msg,
9442
+                              mode=self.KpasswdMode.SET)
9443
+
9444
+        # Change the password.
9445
+        self.kpasswd_exchange(ticket,
9446
+                              new_password,
9447
+                              expected_code,
9448
+                              expected_msg,
9449
+                              mode=self.KpasswdMode.CHANGE)
9450
+
9451
+    # Test setting a password, specifying the principal of the target user.
9452
+    def test_kpasswd_set_target_princ_only(self):
9453
+        # Create an account for testing.
9454
+        creds = self._get_creds()
9455
+        username = creds.get_username()
9456
+
9457
+        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
9458
+                                          names=username.split('/'))
9459
+
9460
+        # Get an initial ticket to kpasswd.
9461
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9462
+                              kdc_options='0')
9463
+
9464
+        expected_code = KPASSWD_MALFORMED
9465
+        expected_msg = (b'Realm and principal must be both present, or '
9466
+                        b'neither present',
9467
+                        b'Failed to decode packet')
9468
+
9469
+        # Change the password.
9470
+        new_password = generate_random_password(32, 32)
9471
+        self.kpasswd_exchange(ticket,
9472
+                              new_password,
9473
+                              expected_code,
9474
+                              expected_msg,
9475
+                              mode=self.KpasswdMode.SET,
9476
+                              target_princ=cname)
9477
+
9478
+    # Test that kpasswd rejects a password set specifying only the realm of the
9479
+    # target user.
9480
+    def test_kpasswd_set_target_realm_only(self):
9481
+        # Create an account for testing.
9482
+        creds = self._get_creds()
9483
+
9484
+        # Get an initial ticket to kpasswd.
9485
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9486
+                              kdc_options='0')
9487
+
9488
+        expected_code = KPASSWD_MALFORMED, KPASSWD_ACCESSDENIED
9489
+        expected_msg = (b'Realm and principal must be both present, or '
9490
+                        b'neither present',
9491
+                        b'Failed to decode packet',
9492
+                        b'No such user when changing password')
9493
+
9494
+        # Change the password.
9495
+        new_password = generate_random_password(32, 32)
9496
+        self.kpasswd_exchange(ticket,
9497
+                              new_password,
9498
+                              expected_code,
9499
+                              expected_msg,
9500
+                              mode=self.KpasswdMode.SET,
9501
+                              target_realm=creds.get_realm())
9502
+
9503
+    # Show that a user cannot set a password, specifying both principal and
9504
+    # realm of the target user, without having control access.
9505
+    def test_kpasswd_set_target_princ_and_realm_no_access(self):
9506
+        # Create an account for testing.
9507
+        creds = self._get_creds()
9508
+        username = creds.get_username()
9509
+
9510
+        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
9511
+                                          names=username.split('/'))
9512
+
9513
+        # Get an initial ticket to kpasswd.
9514
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9515
+                              kdc_options='0')
9516
+
9517
+        expected_code = KPASSWD_ACCESSDENIED
9518
+        expected_msg = b'Not permitted to change password'
9519
+
9520
+        # Change the password.
9521
+        new_password = generate_random_password(32, 32)
9522
+        self.kpasswd_exchange(ticket,
9523
+                              new_password,
9524
+                              expected_code,
9525
+                              expected_msg,
9526
+                              mode=self.KpasswdMode.SET,
9527
+                              target_princ=cname,
9528
+                              target_realm=creds.get_realm())
9529
+
9530
+    # Test setting a password, specifying both principal and realm of the
9531
+    # target user, whem the user has control access on their account.
9532
+    def test_kpasswd_set_target_princ_and_realm_access(self):
9533
+        # Create an account for testing.
9534
+        creds = self._get_creds()
9535
+        username = creds.get_username()
9536
+        tgt = self.get_tgt(creds)
9537
+
9538
+        cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
9539
+                                          names=username.split('/'))
9540
+
9541
+        samdb = self.get_samdb()
9542
+        sd_utils = SDUtils(samdb)
9543
+
9544
+        user_dn = creds.get_dn()
9545
+        user_sid = self.get_objectSid(samdb, user_dn)
9546
+
9547
+        # Give the user control access on their account.
9548
+        ace = f'(A;;CR;;;{user_sid})'
9549
+        sd_utils.dacl_add_ace(user_dn, ace)
9550
+
9551
+        # Get a non-initial ticket to kpasswd. Since we have the right to
9552
+        # change the account's password, we don't need an initial ticket.
9553
+        krbtgt_creds = self.get_krbtgt_creds()
9554
+        ticket = self.get_service_ticket(tgt,
9555
+                                         krbtgt_creds,
9556
+                                         service='kadmin',
9557
+                                         target_name='changepw',
9558
+                                         kdc_options='0')
9559
+
9560
+        expected_code = KPASSWD_SUCCESS
9561
+        expected_msg = b'Password changed'
9562
+
9563
+        # Change the password.
9564
+        new_password = generate_random_password(32, 32)
9565
+        self.kpasswd_exchange(ticket,
9566
+                              new_password,
9567
+                              expected_code,
9568
+                              expected_msg,
9569
+                              mode=self.KpasswdMode.SET,
9570
+                              target_princ=cname,
9571
+                              target_realm=creds.get_realm())
9572
+
9573
+    # Test setting a password when the existing password has expired.
9574
+    def test_kpasswd_set_expired_password(self):
9575
+        # Create an account for testing, with an expired password.
9576
+        creds = self._get_creds(expired=True)
9577
+
9578
+        # Get an initial ticket to kpasswd.
9579
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9580
+                              kdc_options='0')
9581
+
9582
+        expected_code = KPASSWD_SUCCESS
9583
+        expected_msg = b'Password changed'
9584
+
9585
+        # Set the password.
9586
+        new_password = generate_random_password(32, 32)
9587
+        self.kpasswd_exchange(ticket,
9588
+                              new_password,
9589
+                              expected_code,
9590
+                              expected_msg,
9591
+                              mode=self.KpasswdMode.SET)
9592
+
9593
+    # Test changing a password when the existing password has expired.
9594
+    def test_kpasswd_change_expired_password(self):
9595
+        # Create an account for testing, with an expired password.
9596
+        creds = self._get_creds(expired=True)
9597
+
9598
+        # Get an initial ticket to kpasswd.
9599
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9600
+                              kdc_options='0')
9601
+
9602
+        expected_code = KPASSWD_SUCCESS
9603
+        expected_msg = b'Password changed'
9604
+
9605
+        # Change the password.
9606
+        new_password = generate_random_password(32, 32)
9607
+        self.kpasswd_exchange(ticket,
9608
+                              new_password,
9609
+                              expected_code,
9610
+                              expected_msg,
9611
+                              mode=self.KpasswdMode.CHANGE)
9612
+
9613
+    # Check the lifetime of a kpasswd ticket is not more than two minutes.
9614
+    def test_kpasswd_ticket_lifetime(self):
9615
+        # Create an account for testing.
9616
+        creds = self._get_creds()
9617
+
9618
+        # Get an initial ticket to kpasswd.
9619
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9620
+                              kdc_options='0')
9621
+
9622
+        # Check the lifetime of the ticket is equal to two minutes.
9623
+        lifetime = self.get_ticket_lifetime(ticket)
9624
+        self.assertEqual(2 * 60, lifetime)
9625
+
9626
+    # Ensure we cannot perform a TGS-REQ with a kpasswd ticket.
9627
+    def test_kpasswd_ticket_tgs(self):
9628
+        creds = self.get_client_creds()
9629
+
9630
+        # Get an initial ticket to kpasswd.
9631
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9632
+                              kdc_options='0')
9633
+
9634
+        # Change the sname of the ticket to match that of a TGT.
9635
+        realm = creds.get_realm()
9636
+        krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST,
9637
+                                                 names=['krbtgt', realm])
9638
+        ticket.set_sname(krbtgt_sname)
9639
+
9640
+        # Try to use that ticket to get a service ticket.
9641
+        service_creds = self.get_service_creds()
9642
+
9643
+        # This fails due to missing REQUESTER_SID buffer.
9644
+        self._make_tgs_request(creds, service_creds, ticket,
9645
+                               expect_error=(KDC_ERR_TGT_REVOKED,
9646
+                                             KDC_ERR_TKT_EXPIRED))
9647
+
9648
+    def modify_requester_sid_time(self, ticket, sid, lifetime):
9649
+        # Get the krbtgt key.
9650
+        krbtgt_creds = self.get_krbtgt_creds()
9651
+
9652
+        krbtgt_key = self.TicketDecryptionKey_from_creds(krbtgt_creds)
9653
+        checksum_keys = {
9654
+            krb5pac.PAC_TYPE_KDC_CHECKSUM: krbtgt_key,
9655
+        }
9656
+
9657
+        # Set authtime and starttime to an hour in the past, to show that they
9658
+        # do not affect ticket rejection.
9659
+        start_time = self.get_KerberosTime(offset=-60 * 60)
9660
+
9661
+        # Set the endtime of the ticket relative to our current time, so that
9662
+        # the ticket has 'lifetime' seconds remaining to live.
9663
+        end_time = self.get_KerberosTime(offset=lifetime)
9664
+
9665
+        # Modify the times in the ticket.
9666
+        def modify_ticket_times(enc_part):
9667
+            enc_part['authtime'] = start_time
9668
+            if 'starttime' in enc_part:
9669
+                enc_part['starttime'] = start_time
9670
+
9671
+            enc_part['endtime'] = end_time
9672
+
9673
+            return enc_part
9674
+
9675
+        # We have to set the times in both the ticket and the PAC, otherwise
9676
+        # Heimdal will complain.
9677
+        def modify_pac_time(pac):
9678
+            pac_buffers = pac.buffers
9679
+
9680
+            for pac_buffer in pac_buffers:
9681
+                if pac_buffer.type == krb5pac.PAC_TYPE_LOGON_NAME:
9682
+                    logon_time = self.get_EpochFromKerberosTime(start_time)
9683
+                    pac_buffer.info.logon_time = unix2nttime(logon_time)
9684
+                    break
9685
+            else:
9686
+                self.fail('failed to find LOGON_NAME PAC buffer')
9687
+
9688
+            pac.buffers = pac_buffers
9689
+
9690
+            return pac
9691
+
9692
+        # Add a requester SID to show that the KDC will then accept this
9693
+        # kpasswd ticket as if it were a TGT.
9694
+        def modify_pac_fn(pac):
9695
+            pac = self.add_requester_sid(pac, sid=sid)
9696
+            pac = modify_pac_time(pac)
9697
+            return pac
9698
+
9699
+        # Do the actual modification.
9700
+        return self.modified_ticket(ticket,
9701
+                                    new_ticket_key=krbtgt_key,
9702
+                                    modify_fn=modify_ticket_times,
9703
+                                    modify_pac_fn=modify_pac_fn,
9704
+                                    checksum_keys=checksum_keys)
9705
+
9706
+    # Ensure we cannot perform a TGS-REQ with a kpasswd ticket containing a
9707
+    # requester SID and having a remaining lifetime of two minutes.
9708
+    def test_kpasswd_ticket_requester_sid_tgs(self):
9709
+        creds = self.get_client_creds()
9710
+
9711
+        # Get an initial ticket to kpasswd.
9712
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9713
+                              kdc_options='0')
9714
+
9715
+        # Change the sname of the ticket to match that of a TGT.
9716
+        realm = creds.get_realm()
9717
+        krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST,
9718
+                                                 names=['krbtgt', realm])
9719
+        ticket.set_sname(krbtgt_sname)
9720
+
9721
+        # Get the user's SID.
9722
+        samdb = self.get_samdb()
9723
+
9724
+        user_dn = creds.get_dn()
9725
+        user_sid = self.get_objectSid(samdb, user_dn)
9726
+
9727
+        # Modify the ticket to add a requester SID and give it two minutes to
9728
+        # live.
9729
+        ticket = self.modify_requester_sid_time(ticket,
9730
+                                                sid=user_sid,
9731
+                                                lifetime=2 * 60)
9732
+
9733
+        # Try to use that ticket to get a service ticket.
9734
+        service_creds = self.get_service_creds()
9735
+
9736
+        # This fails due to the lifetime being too short.
9737
+        self._make_tgs_request(creds, service_creds, ticket,
9738
+                               expect_error=KDC_ERR_TKT_EXPIRED)
9739
+
9740
+    # Show we can perform a TGS-REQ with a kpasswd ticket containing a
9741
+    # requester SID if the remaining lifetime exceeds two minutes.
9742
+    def test_kpasswd_ticket_requester_sid_lifetime_tgs(self):
9743
+        creds = self.get_client_creds()
9744
+
9745
+        # Get an initial ticket to kpasswd.
9746
+        ticket = self.get_tgt(creds, sname=self.get_kpasswd_sname(),
9747
+                              kdc_options='0')
9748
+
9749
+        # Change the sname of the ticket to match that of a TGT.
9750
+        realm = creds.get_realm()
9751
+        krbtgt_sname = self.PrincipalName_create(name_type=NT_SRV_INST,
9752
+                                                 names=['krbtgt', realm])
9753
+        ticket.set_sname(krbtgt_sname)
9754
+
9755
+        # Get the user's SID.
9756
+        samdb = self.get_samdb()
9757
+
9758
+        user_dn = creds.get_dn()
9759
+        user_sid = self.get_objectSid(samdb, user_dn)
9760
+
9761
+        # Modify the ticket to add a requester SID and give it two minutes and
9762
+        # ten seconds to live.
9763
+        ticket = self.modify_requester_sid_time(ticket,
9764
+                                                sid=user_sid,
9765
+                                                lifetime=2 * 60 + 10)
9766
+
9767
+        # Try to use that ticket to get a service ticket.
9768
+        service_creds = self.get_service_creds()
9769
+
9770
+        # This succeeds.
9771
+        self._make_tgs_request(creds, service_creds, ticket,
9772
+                               expect_error=False)
9773
+
9774
+    # Test that kpasswd rejects requests with a service ticket.
9775
+    def test_kpasswd_non_initial(self):
9776
+        # Create an account for testing, and get a TGT.
9777
+        creds = self._get_creds()
9778
+        tgt = self.get_tgt(creds)
9779
+
9780
+        # Get a non-initial ticket to kpasswd.
9781
+        krbtgt_creds = self.get_krbtgt_creds()
9782
+        ticket = self.get_service_ticket(tgt,
9783
+                                         krbtgt_creds,
9784
+                                         service='kadmin',
9785
+                                         target_name='changepw',
9786
+                                         kdc_options='0')
9787
+
9788
+        expected_code = KPASSWD_INITIAL_FLAG_NEEDED
9789
+        expected_msg = b'Expected an initial ticket'
9790
+
9791
+        # Set the password.
9792
+        new_password = generate_random_password(32, 32)
9793
+        self.kpasswd_exchange(ticket,
9794
+                              new_password,
9795
+                              expected_code,
9796
+                              expected_msg,
9797
+                              mode=self.KpasswdMode.SET)
9798
+
9799
+        # Change the password.
9800
+        self.kpasswd_exchange(ticket,
9801
+                              new_password,
9802
+                              expected_code,
9803
+                              expected_msg,
9804
+                              mode=self.KpasswdMode.CHANGE)
9805
+
9806
+    # Show that kpasswd accepts requests with a service ticket modified to set
9807
+    # the 'initial' flag.
9808
+    def test_kpasswd_initial(self):
9809
+        # Create an account for testing, and get a TGT.
9810
+        creds = self._get_creds()
9811
+
9812
+        krbtgt_creds = self.get_krbtgt_creds()
9813
+
9814
+        # Get a service ticket, and modify it to set the 'initial' flag.
9815
+        def get_ticket():
9816
+            tgt = self.get_tgt(creds, fresh=True)
9817
+
9818
+            # Get a non-initial ticket to kpasswd.
9819
+            ticket = self.get_service_ticket(tgt,
9820
+                                             krbtgt_creds,
9821
+                                             service='kadmin',
9822
+                                             target_name='changepw',
9823
+                                             kdc_options='0',
9824
+                                             fresh=True)
9825
+
9826
+            set_initial_flag = partial(self.modify_ticket_flag, flag='initial',
9827
+                                       value=True)
9828
+
9829
+            checksum_keys = self.get_krbtgt_checksum_key()
9830
+            return self.modified_ticket(ticket,
9831
+                                        modify_fn=set_initial_flag,
9832
+                                        checksum_keys=checksum_keys)
9833
+
9834
+        expected_code = KPASSWD_SUCCESS
9835
+        expected_msg = b'Password changed'
9836
+
9837
+        ticket = get_ticket()
9838
+
9839
+        # Set the password.
9840
+        new_password = generate_random_password(32, 32)
9841
+        self.kpasswd_exchange(ticket,
9842
+                              new_password,
9843
+                              expected_code,
9844
+                              expected_msg,
9845
+                              mode=self.KpasswdMode.SET)
9846
+
9847
+        creds.update_password(new_password)
9848
+        ticket = get_ticket()
9849
+
9850
+        # Change the password.
9851
+        new_password = generate_random_password(32, 32)
9852
+        self.kpasswd_exchange(ticket,
9853
+                              new_password,
9854
+                              expected_code,
9855
+                              expected_msg,
9856
+                              mode=self.KpasswdMode.CHANGE)
9857
+
9858
+    # Test that kpasswd rejects requests where the ticket is encrypted with a
9859
+    # key other than the krbtgt's.
9860
+    def test_kpasswd_wrong_key(self):
9861
+        # Create an account for testing.
9862
+        creds = self._get_creds()
9863
+
9864
+        sname = self.get_kpasswd_sname()
9865
+
9866
+        # Get an initial ticket to kpasswd.
9867
+        ticket = self.get_tgt(creds, sname=sname,
9868
+                              kdc_options='0')
9869
+
9870
+        # Get a key belonging to the Administrator account.
9871
+        admin_creds = self.get_admin_creds()
9872
+        admin_key = self.TicketDecryptionKey_from_creds(admin_creds)
9873
+        self.assertIsNotNone(admin_key.kvno,
9874
+                             'a kvno is required to tell the DB '
9875
+                             'which key to look up.')
9876
+        checksum_keys = {
9877
+            krb5pac.PAC_TYPE_KDC_CHECKSUM: admin_key,
9878
+        }
9879
+
9880
+        # Re-encrypt the ticket using the Administrator's key.
9881
+        ticket = self.modified_ticket(ticket,
9882
+                                      new_ticket_key=admin_key,
9883
+                                      checksum_keys=checksum_keys)
9884
+
9885
+        # Set the sname of the ticket to that of the Administrator account.
9886
+        admin_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
9887
+                                                names=['Administrator'])
9888
+        ticket.set_sname(admin_sname)
9889
+
9890
+        expected_code = KPASSWD_HARDERROR
9891
+        expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n'
9892
+
9893
+        # Set the password.
9894
+        new_password = generate_random_password(32, 32)
9895
+        self.kpasswd_exchange(ticket,
9896
+                              new_password,
9897
+                              expected_code,
9898
+                              expected_msg,
9899
+                              mode=self.KpasswdMode.SET)
9900
+
9901
+        # Change the password.
9902
+        self.kpasswd_exchange(ticket,
9903
+                              new_password,
9904
+                              expected_code,
9905
+                              expected_msg,
9906
+                              mode=self.KpasswdMode.CHANGE)
9907
+
9908
+    def test_kpasswd_wrong_key_service(self):
9909
+        # Create an account for testing.
9910
+        creds = self.get_cached_creds(account_type=self.AccountType.COMPUTER,
9911
+                                      use_cache=False)
9912
+
9913
+        sname = self.get_kpasswd_sname()
9914
+
9915
+        # Get an initial ticket to kpasswd.
9916
+        ticket = self.get_tgt(creds, sname=sname,
9917
+                              kdc_options='0')
9918
+
9919
+        # Get a key belonging to our account.
9920
+        our_key = self.TicketDecryptionKey_from_creds(creds)
9921
+        self.assertIsNotNone(our_key.kvno,
9922
+                             'a kvno is required to tell the DB '
9923
+                             'which key to look up.')
9924
+        checksum_keys = {
9925
+            krb5pac.PAC_TYPE_KDC_CHECKSUM: our_key,
9926
+        }
9927
+
9928
+        # Re-encrypt the ticket using our key.
9929
+        ticket = self.modified_ticket(ticket,
9930
+                                      new_ticket_key=our_key,
9931
+                                      checksum_keys=checksum_keys)
9932
+
9933
+        # Set the sname of the ticket to that of our account.
9934
+        username = creds.get_username()
9935
+        sname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
9936
+                                          names=username.split('/'))
9937
+        ticket.set_sname(sname)
9938
+
9939
+        expected_code = KPASSWD_HARDERROR
9940
+        expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n'
9941
+
9942
+        # Set the password.
9943
+        new_password = generate_random_password(32, 32)
9944
+        self.kpasswd_exchange(ticket,
9945
+                              new_password,
9946
+                              expected_code,
9947
+                              expected_msg,
9948
+                              mode=self.KpasswdMode.SET)
9949
+
9950
+        # Change the password.
9951
+        self.kpasswd_exchange(ticket,
9952
+                              new_password,
9953
+                              expected_code,
9954
+                              expected_msg,
9955
+                              mode=self.KpasswdMode.CHANGE)
9956
+
9957
+    # Test that kpasswd rejects requests where the ticket is encrypted with a
9958
+    # key belonging to a server account other than the krbtgt.
9959
+    def test_kpasswd_wrong_key_server(self):
9960
+        # Create an account for testing.
9961
+        creds = self._get_creds()
9962
+
9963
+        sname = self.get_kpasswd_sname()
9964
+
9965
+        # Get an initial ticket to kpasswd.
9966
+        ticket = self.get_tgt(creds, sname=sname,
9967
+                              kdc_options='0')
9968
+
9969
+        # Get a key belonging to the DC's account.
9970
+        dc_creds = self.get_dc_creds()
9971
+        dc_key = self.TicketDecryptionKey_from_creds(dc_creds)
9972
+        self.assertIsNotNone(dc_key.kvno,
9973
+                             'a kvno is required to tell the DB '
9974
+                             'which key to look up.')
9975
+        checksum_keys = {
9976
+            krb5pac.PAC_TYPE_KDC_CHECKSUM: dc_key,
9977
+        }
9978
+
9979
+        # Re-encrypt the ticket using the DC's key.
9980
+        ticket = self.modified_ticket(ticket,
9981
+                                      new_ticket_key=dc_key,
9982
+                                      checksum_keys=checksum_keys)
9983
+
9984
+        # Set the sname of the ticket to that of the DC's account.
9985
+        dc_username = dc_creds.get_username()
9986
+        dc_sname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
9987
+                                             names=dc_username.split('/'))
9988
+        ticket.set_sname(dc_sname)
9989
+
9990
+        expected_code = KPASSWD_HARDERROR
9991
+        expected_msg = b'gensec_update failed - NT_STATUS_LOGON_FAILURE\n'
9992
+
9993
+        # Set the password.
9994
+        new_password = generate_random_password(32, 32)
9995
+        self.kpasswd_exchange(ticket,
9996
+                              new_password,
9997
+                              expected_code,
9998
+                              expected_msg,
9999
+                              mode=self.KpasswdMode.SET)
10000
+
10001
+        # Change the password.
10002
+        self.kpasswd_exchange(ticket,
10003
+                              new_password,
10004
+                              expected_code,
10005
+                              expected_msg,
10006
+                              mode=self.KpasswdMode.CHANGE)
10007
+
10008
+
10009
+if __name__ == '__main__':
10010
+    global_asn1_print = False
10011
+    global_hexdump = False
10012
+    import unittest
10013
+    unittest.main()
10014
diff --git python/samba/tests/krb5/raw_testcase.py python/samba/tests/krb5/raw_testcase.py
10015
index 57010ae73bd..4a78a8eadf3 100644
10016
--- python/samba/tests/krb5/raw_testcase.py
10017
+++ python/samba/tests/krb5/raw_testcase.py
10018
@@ -500,6 +500,10 @@ class KerberosCredentials(Credentials):
10019
     def get_upn(self):
10020
         return self.upn
10021
 
10022
+    def update_password(self, password):
10023
+        self.set_password(password)
10024
+        self.set_kvno(self.get_kvno() + 1)
10025
+
10026
 
10027
 class KerberosTicketCreds:
10028
     def __init__(self, ticket, session_key,
10029
@@ -518,6 +522,10 @@ class KerberosTicketCreds:
10030
         self.ticket_private = ticket_private
10031
         self.encpart_private = encpart_private
10032
 
10033
+    def set_sname(self, sname):
10034
+        self.ticket['sname'] = sname
10035
+        self.sname = sname
10036
+
10037
 
10038
 class RawKerberosTest(TestCaseInTempDir):
10039
     """A raw Kerberos Test case."""
10040
diff --git python/samba/tests/usage.py python/samba/tests/usage.py
10041
index 6bbd96e7a08..a1210ada579 100644
10042
--- python/samba/tests/usage.py
10043
+++ python/samba/tests/usage.py
10044
@@ -109,6 +109,7 @@ EXCLUDE_USAGE = {
10045
     'python/samba/tests/krb5/alias_tests.py',
10046
     'python/samba/tests/krb5/test_min_domain_uid.py',
10047
     'python/samba/tests/krb5/test_idmap_nss.py',
10048
+    'python/samba/tests/krb5/kpasswd_tests.py',
10049
 }
10050
 
10051
 EXCLUDE_HELP = {
10052
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
10053
index 424a8b81c38..54e69a48bc1 100644
10054
--- selftest/knownfail_heimdal_kdc
10055
+++ selftest/knownfail_heimdal_kdc
10056
@@ -271,3 +271,29 @@
10057
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
10058
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
10059
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
10060
+#
10061
+# Kpasswd tests
10062
+#
10063
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
10064
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10065
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc
10066
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc
10067
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10068
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10069
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc
10070
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc
10071
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10072
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10073
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10074
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc
10075
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc
10076
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc
10077
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc
10078
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc
10079
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc
10080
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10081
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10082
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc
10083
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10084
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10085
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
10086
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
10087
index 108c6055d0c..53638afc17a 100644
10088
--- selftest/knownfail_mit_kdc
10089
+++ selftest/knownfail_mit_kdc
10090
@@ -575,3 +575,29 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
10091
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_logon_info_sid_mismatch_nonexisting
10092
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_existing
10093
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_tgs_rodc_requester_sid_mismatch_nonexisting
10094
+#
10095
+# Kpasswd tests
10096
+#
10097
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
10098
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10099
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc
10100
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc
10101
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10102
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10103
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc
10104
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc
10105
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10106
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10107
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10108
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc
10109
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc
10110
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc
10111
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc
10112
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc
10113
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc
10114
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10115
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10116
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc
10117
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10118
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10119
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
10120
-- 
10121
2.25.1
10122
10123
10124
From 29ec8b2369b5f5e2a660a3165d2528982514a0f2 Mon Sep 17 00:00:00 2001
10125
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10126
Date: Fri, 27 May 2022 19:21:06 +1200
10127
Subject: [PATCH 72/99] CVE-2022-2031 s4:kpasswd: Correctly generate error
10128
 strings
10129
10130
The error_data we create already has an explicit length, and should not
10131
be zero-terminated, so we omit the trailing null byte. Previously,
10132
Heimdal builds would leave a superfluous trailing null byte on error
10133
strings, while MIT builds would omit the final character.
10134
10135
The two bytes added to the string's length are for the prepended error
10136
code.
10137
10138
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10139
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
10140
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
10141
10142
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10143
Reviewed-by: Andreas Schneider <asn@samba.org>
10144
10145
[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails]
10146
---
10147
 selftest/knownfail_heimdal_kdc | 12 ------------
10148
 selftest/knownfail_mit_kdc     | 15 ---------------
10149
 source4/kdc/kpasswd-helper.c   | 13 ++++++-------
10150
 3 files changed, 6 insertions(+), 34 deletions(-)
10151
10152
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
10153
index 54e69a48bc1..40e24f3155b 100644
10154
--- selftest/knownfail_heimdal_kdc
10155
+++ selftest/knownfail_heimdal_kdc
10156
@@ -276,24 +276,12 @@
10157
 #
10158
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
10159
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10160
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc
10161
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc
10162
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10163
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10164
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc
10165
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc
10166
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10167
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10168
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10169
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc
10170
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc
10171
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc
10172
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc
10173
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc
10174
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc
10175
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10176
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10177
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc
10178
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10179
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10180
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
10181
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
10182
index 53638afc17a..a914c4d3492 100644
10183
--- selftest/knownfail_mit_kdc
10184
+++ selftest/knownfail_mit_kdc
10185
@@ -578,26 +578,11 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
10186
 #
10187
 # Kpasswd tests
10188
 #
10189
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
10190
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10191
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change.ad_dc
10192
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_change_expired_password.ad_dc
10193
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10194
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10195
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_initial.ad_dc
10196
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize.ad_dc
10197
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10198
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10199
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10200
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set.ad_dc
10201
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_expired_password.ad_dc
10202
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_access.ad_dc
10203
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_and_realm_no_access.ad_dc
10204
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_princ_only.ad_dc
10205
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_set_target_realm_only.ad_dc
10206
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10207
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10208
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_too_weak.ad_dc
10209
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10210
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10211
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
10212
diff --git source4/kdc/kpasswd-helper.c source4/kdc/kpasswd-helper.c
10213
index 995f54825b5..55a2f5b3bf6 100644
10214
--- source4/kdc/kpasswd-helper.c
10215
+++ source4/kdc/kpasswd-helper.c
10216
@@ -48,17 +48,16 @@ bool kpasswd_make_error_reply(TALLOC_CTX *mem_ctx,
10217
 	}
10218
 
10219
 	/*
10220
-	 * The string 's' has two terminating nul-bytes which are also
10221
-	 * reflected by 'slen'. Normally Kerberos doesn't expect that strings
10222
-	 * are nul-terminated, but Heimdal does!
10223
+	 * The string 's' has one terminating nul-byte which is also
10224
+	 * reflected by 'slen'. We subtract it from the length.
10225
 	 */
10226
-#ifndef SAMBA4_USES_HEIMDAL
10227
-	if (slen < 2) {
10228
+	if (slen < 1) {
10229
 		talloc_free(s);
10230
 		return false;
10231
 	}
10232
-	slen -= 2;
10233
-#endif
10234
+	slen--;
10235
+
10236
+	/* Two bytes are added to the length to account for the error code. */
10237
 	if (2 + slen < slen) {
10238
 		talloc_free(s);
10239
 		return false;
10240
-- 
10241
2.25.1
10242
10243
10244
From 3a8da51396f3bf9d4caf8dbd4e75a0314aa47046 Mon Sep 17 00:00:00 2001
10245
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10246
Date: Wed, 18 May 2022 16:48:59 +1200
10247
Subject: [PATCH 73/99] CVE-2022-2031 s4:kpasswd: Don't return AP-REP on
10248
 failure
10249
10250
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10251
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
10252
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
10253
10254
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10255
Reviewed-by: Andreas Schneider <asn@samba.org>
10256
10257
[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails]
10258
---
10259
 selftest/knownfail_mit_kdc    | 1 -
10260
 source4/kdc/kpasswd-service.c | 2 ++
10261
 2 files changed, 2 insertions(+), 1 deletion(-)
10262
10263
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
10264
index a914c4d3492..f64291e776d 100644
10265
--- selftest/knownfail_mit_kdc
10266
+++ selftest/knownfail_mit_kdc
10267
@@ -579,7 +579,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
10268
 # Kpasswd tests
10269
 #
10270
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10271
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10272
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10273
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10274
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10275
diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c
10276
index 8f1679e4a28..a3c57a67dd1 100644
10277
--- source4/kdc/kpasswd-service.c
10278
+++ source4/kdc/kpasswd-service.c
10279
@@ -253,6 +253,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc,
10280
 				      &kpasswd_dec_reply,
10281
 				      &error_string);
10282
 	if (code != 0) {
10283
+		ap_rep_blob = data_blob_null;
10284
 		error_code = code;
10285
 		goto reply;
10286
 	}
10287
@@ -262,6 +263,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc,
10288
 			     &kpasswd_dec_reply,
10289
 			     &enc_data_blob);
10290
 	if (!NT_STATUS_IS_OK(status)) {
10291
+		ap_rep_blob = data_blob_null;
10292
 		error_code = KRB5_KPASSWD_HARDERROR;
10293
 		error_string = talloc_asprintf(tmp_ctx,
10294
 					       "gensec_wrap failed - %s\n",
10295
-- 
10296
2.25.1
10297
10298
10299
From cf9e37604409ba0c3c5904af40beb2975c309ad4 Mon Sep 17 00:00:00 2001
10300
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10301
Date: Fri, 27 May 2022 19:29:34 +1200
10302
Subject: [PATCH 74/99] CVE-2022-2031 lib:krb5_wrap: Generate valid error codes
10303
 in smb_krb5_mk_error()
10304
10305
The error code passed in will be an offset from ERROR_TABLE_BASE_krb5,
10306
so we need to subtract that before creating the error. Heimdal does this
10307
internally, so it isn't needed there.
10308
10309
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10310
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
10311
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
10312
10313
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10314
Reviewed-by: Andreas Schneider <asn@samba.org>
10315
---
10316
 lib/krb5_wrap/krb5_samba.c | 2 +-
10317
 selftest/knownfail_mit_kdc | 4 ++++
10318
 2 files changed, 5 insertions(+), 1 deletion(-)
10319
10320
diff --git lib/krb5_wrap/krb5_samba.c lib/krb5_wrap/krb5_samba.c
10321
index 76c2dcd2126..610efcc9b87 100644
10322
--- lib/krb5_wrap/krb5_samba.c
10323
+++ lib/krb5_wrap/krb5_samba.c
10324
@@ -237,7 +237,7 @@ krb5_error_code smb_krb5_mk_error(krb5_context context,
10325
 		return code;
10326
 	}
10327
 
10328
-	errpkt.error = error_code;
10329
+	errpkt.error = error_code - ERROR_TABLE_BASE_krb5;
10330
 
10331
 	errpkt.text.length = 0;
10332
 	if (e_text != NULL) {
10333
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
10334
index f64291e776d..633bf79e8e0 100644
10335
--- selftest/knownfail_mit_kdc
10336
+++ selftest/knownfail_mit_kdc
10337
@@ -579,9 +579,13 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
10338
 # Kpasswd tests
10339
 #
10340
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10341
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10342
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10343
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10344
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10345
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10346
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10347
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10348
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10349
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10350
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
10351
-- 
10352
2.25.1
10353
10354
10355
From cf749fac346ef59c91a9ea87f5e7ddec2e5649c7 Mon Sep 17 00:00:00 2001
10356
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10357
Date: Wed, 18 May 2022 16:49:43 +1200
10358
Subject: [PATCH 75/99] CVE-2022-2031 s4:kpasswd: Return a kpasswd error code
10359
 in KRB-ERROR
10360
10361
If we attempt to return an error code outside of Heimdal's allowed range
10362
[KRB5KDC_ERR_NONE, KRB5_ERR_RCSID), it will be replaced with a GENERIC
10363
error, and the error text will be set to the meaningless result of
10364
krb5_get_error_message(). Avoid this by ensuring the error code is in
10365
the correct range.
10366
10367
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10368
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
10369
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
10370
10371
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10372
Reviewed-by: Andreas Schneider <asn@samba.org>
10373
---
10374
 selftest/knownfail_heimdal_kdc | 2 --
10375
 selftest/knownfail_mit_kdc     | 4 ----
10376
 source4/kdc/kpasswd-service.c  | 2 +-
10377
 3 files changed, 1 insertion(+), 7 deletions(-)
10378
10379
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
10380
index 40e24f3155b..3b494baa658 100644
10381
--- selftest/knownfail_heimdal_kdc
10382
+++ selftest/knownfail_heimdal_kdc
10383
@@ -276,9 +276,7 @@
10384
 #
10385
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
10386
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10387
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10388
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10389
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10390
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10391
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10392
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10393
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
10394
index 633bf79e8e0..f64291e776d 100644
10395
--- selftest/knownfail_mit_kdc
10396
+++ selftest/knownfail_mit_kdc
10397
@@ -579,13 +579,9 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
10398
 # Kpasswd tests
10399
 #
10400
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10401
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_empty.ad_dc
10402
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10403
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10404
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_seq_number.ad_dc
10405
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10406
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10407
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10408
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10409
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10410
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
10411
diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c
10412
index a3c57a67dd1..b4706de1ad7 100644
10413
--- source4/kdc/kpasswd-service.c
10414
+++ source4/kdc/kpasswd-service.c
10415
@@ -312,7 +312,7 @@ reply:
10416
 		}
10417
 
10418
 		code = smb_krb5_mk_error(kdc->smb_krb5_context->krb5_context,
10419
-					 error_code,
10420
+					 KRB5KDC_ERR_NONE + error_code,
10421
 					 NULL, /* e_text */
10422
 					 &k_dec_data,
10423
 					 NULL, /* client */
10424
-- 
10425
2.25.1
10426
10427
10428
From 198256e2184897300e1cea4343437c3b7b6f74ad Mon Sep 17 00:00:00 2001
10429
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10430
Date: Wed, 18 May 2022 16:06:31 +1200
10431
Subject: [PATCH 76/99] CVE-2022-2031 gensec_krb5: Add helper function to check
10432
 if client sent an initial ticket
10433
10434
This will be used in the kpasswd service to ensure that the client has
10435
an initial ticket to kadmin/changepw, and not a service ticket.
10436
10437
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10438
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
10439
10440
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10441
Reviewed-by: Andreas Schneider <asn@samba.org>
10442
---
10443
 source4/auth/gensec/gensec_krb5.c          | 20 +-----
10444
 source4/auth/gensec/gensec_krb5_helpers.c  | 72 ++++++++++++++++++++++
10445
 source4/auth/gensec/gensec_krb5_helpers.h  | 32 ++++++++++
10446
 source4/auth/gensec/gensec_krb5_internal.h | 47 ++++++++++++++
10447
 source4/auth/gensec/wscript_build          |  4 ++
10448
 5 files changed, 157 insertions(+), 18 deletions(-)
10449
 create mode 100644 source4/auth/gensec/gensec_krb5_helpers.c
10450
 create mode 100644 source4/auth/gensec/gensec_krb5_helpers.h
10451
 create mode 100644 source4/auth/gensec/gensec_krb5_internal.h
10452
10453
diff --git source4/auth/gensec/gensec_krb5.c source4/auth/gensec/gensec_krb5.c
10454
index 7d87b3ac6b9..104e4639c44 100644
10455
--- source4/auth/gensec/gensec_krb5.c
10456
+++ source4/auth/gensec/gensec_krb5.c
10457
@@ -44,27 +44,11 @@
10458
 #include "../lib/util/asn1.h"
10459
 #include "auth/kerberos/pac_utils.h"
10460
 #include "gensec_krb5.h"
10461
+#include "gensec_krb5_internal.h"
10462
+#include "gensec_krb5_helpers.h"
10463
 
10464
 _PUBLIC_ NTSTATUS gensec_krb5_init(TALLOC_CTX *);
10465
 
10466
-enum GENSEC_KRB5_STATE {
10467
-	GENSEC_KRB5_SERVER_START,
10468
-	GENSEC_KRB5_CLIENT_START,
10469
-	GENSEC_KRB5_CLIENT_MUTUAL_AUTH,
10470
-	GENSEC_KRB5_DONE
10471
-};
10472
-
10473
-struct gensec_krb5_state {
10474
-	enum GENSEC_KRB5_STATE state_position;
10475
-	struct smb_krb5_context *smb_krb5_context;
10476
-	krb5_auth_context auth_context;
10477
-	krb5_data enc_ticket;
10478
-	krb5_keyblock *keyblock;
10479
-	krb5_ticket *ticket;
10480
-	bool gssapi;
10481
-	krb5_flags ap_req_options;
10482
-};
10483
-
10484
 static int gensec_krb5_destroy(struct gensec_krb5_state *gensec_krb5_state)
10485
 {
10486
 	if (!gensec_krb5_state->smb_krb5_context) {
10487
diff --git source4/auth/gensec/gensec_krb5_helpers.c source4/auth/gensec/gensec_krb5_helpers.c
10488
new file mode 100644
10489
index 00000000000..21f2f1e884e
10490
--- /dev/null
10491
+++ source4/auth/gensec/gensec_krb5_helpers.c
10492
@@ -0,0 +1,72 @@
10493
+/*
10494
+   Unix SMB/CIFS implementation.
10495
+
10496
+   Kerberos backend for GENSEC
10497
+
10498
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
10499
+   Copyright (C) Andrew Tridgell 2001
10500
+   Copyright (C) Luke Howard 2002-2003
10501
+   Copyright (C) Stefan Metzmacher 2004-2005
10502
+
10503
+   This program is free software; you can redistribute it and/or modify
10504
+   it under the terms of the GNU General Public License as published by
10505
+   the Free Software Foundation; either version 3 of the License, or
10506
+   (at your option) any later version.
10507
+
10508
+   This program is distributed in the hope that it will be useful,
10509
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
10510
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10511
+   GNU General Public License for more details.
10512
+
10513
+
10514
+   You should have received a copy of the GNU General Public License
10515
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
10516
+*/
10517
+
10518
+#include "includes.h"
10519
+#include "auth/auth.h"
10520
+#include "auth/gensec/gensec.h"
10521
+#include "auth/gensec/gensec_internal.h"
10522
+#include "gensec_krb5_internal.h"
10523
+#include "gensec_krb5_helpers.h"
10524
+#include "system/kerberos.h"
10525
+#include "auth/kerberos/kerberos.h"
10526
+
10527
+static struct gensec_krb5_state *get_private_state(const struct gensec_security *gensec_security)
10528
+{
10529
+	struct gensec_krb5_state *gensec_krb5_state = NULL;
10530
+
10531
+	if (strcmp(gensec_security->ops->name, "krb5") != 0) {
10532
+		/* We require that the krb5 mechanism is being used. */
10533
+		return NULL;
10534
+	}
10535
+
10536
+	gensec_krb5_state = talloc_get_type(gensec_security->private_data,
10537
+					    struct gensec_krb5_state);
10538
+	return gensec_krb5_state;
10539
+}
10540
+
10541
+/*
10542
+ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of
10543
+ * error.
10544
+ */
10545
+int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security)
10546
+{
10547
+	struct gensec_krb5_state *gensec_krb5_state = NULL;
10548
+
10549
+	gensec_krb5_state = get_private_state(gensec_security);
10550
+	if (gensec_krb5_state == NULL) {
10551
+		return -1;
10552
+	}
10553
+
10554
+	if (gensec_krb5_state->ticket == NULL) {
10555
+		/* We don't have a ticket */
10556
+		return -1;
10557
+	}
10558
+
10559
+#ifdef SAMBA4_USES_HEIMDAL
10560
+	return gensec_krb5_state->ticket->ticket.flags.initial;
10561
+#else /* MIT KERBEROS */
10562
+	return (gensec_krb5_state->ticket->enc_part2->flags & TKT_FLG_INITIAL) ? 1 : 0;
10563
+#endif /* SAMBA4_USES_HEIMDAL */
10564
+}
10565
diff --git source4/auth/gensec/gensec_krb5_helpers.h source4/auth/gensec/gensec_krb5_helpers.h
10566
new file mode 100644
10567
index 00000000000..d7b694dad0c
10568
--- /dev/null
10569
+++ source4/auth/gensec/gensec_krb5_helpers.h
10570
@@ -0,0 +1,32 @@
10571
+/*
10572
+   Unix SMB/CIFS implementation.
10573
+
10574
+   Kerberos backend for GENSEC
10575
+
10576
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
10577
+   Copyright (C) Andrew Tridgell 2001
10578
+   Copyright (C) Luke Howard 2002-2003
10579
+   Copyright (C) Stefan Metzmacher 2004-2005
10580
+
10581
+   This program is free software; you can redistribute it and/or modify
10582
+   it under the terms of the GNU General Public License as published by
10583
+   the Free Software Foundation; either version 3 of the License, or
10584
+   (at your option) any later version.
10585
+
10586
+   This program is distributed in the hope that it will be useful,
10587
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
10588
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10589
+   GNU General Public License for more details.
10590
+
10591
+
10592
+   You should have received a copy of the GNU General Public License
10593
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
10594
+*/
10595
+
10596
+struct gensec_security;
10597
+
10598
+/*
10599
+ * Returns 1 if our ticket has the initial flag set, 0 if not, and -1 in case of
10600
+ * error.
10601
+ */
10602
+int gensec_krb5_initial_ticket(const struct gensec_security *gensec_security);
10603
diff --git source4/auth/gensec/gensec_krb5_internal.h source4/auth/gensec/gensec_krb5_internal.h
10604
new file mode 100644
10605
index 00000000000..0bb796f1b2a
10606
--- /dev/null
10607
+++ source4/auth/gensec/gensec_krb5_internal.h
10608
@@ -0,0 +1,47 @@
10609
+/*
10610
+   Unix SMB/CIFS implementation.
10611
+
10612
+   Kerberos backend for GENSEC
10613
+
10614
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
10615
+   Copyright (C) Andrew Tridgell 2001
10616
+   Copyright (C) Luke Howard 2002-2003
10617
+   Copyright (C) Stefan Metzmacher 2004-2005
10618
+
10619
+   This program is free software; you can redistribute it and/or modify
10620
+   it under the terms of the GNU General Public License as published by
10621
+   the Free Software Foundation; either version 3 of the License, or
10622
+   (at your option) any later version.
10623
+
10624
+   This program is distributed in the hope that it will be useful,
10625
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
10626
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
10627
+   GNU General Public License for more details.
10628
+
10629
+
10630
+   You should have received a copy of the GNU General Public License
10631
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
10632
+*/
10633
+
10634
+#include "includes.h"
10635
+#include "auth/gensec/gensec.h"
10636
+#include "system/kerberos.h"
10637
+#include "auth/kerberos/kerberos.h"
10638
+
10639
+enum GENSEC_KRB5_STATE {
10640
+	GENSEC_KRB5_SERVER_START,
10641
+	GENSEC_KRB5_CLIENT_START,
10642
+	GENSEC_KRB5_CLIENT_MUTUAL_AUTH,
10643
+	GENSEC_KRB5_DONE
10644
+};
10645
+
10646
+struct gensec_krb5_state {
10647
+	enum GENSEC_KRB5_STATE state_position;
10648
+	struct smb_krb5_context *smb_krb5_context;
10649
+	krb5_auth_context auth_context;
10650
+	krb5_data enc_ticket;
10651
+	krb5_keyblock *keyblock;
10652
+	krb5_ticket *ticket;
10653
+	bool gssapi;
10654
+	krb5_flags ap_req_options;
10655
+};
10656
diff --git source4/auth/gensec/wscript_build source4/auth/gensec/wscript_build
10657
index d14a50ff273..20271f1665b 100644
10658
--- source4/auth/gensec/wscript_build
10659
+++ source4/auth/gensec/wscript_build
10660
@@ -18,6 +18,10 @@ bld.SAMBA_MODULE('gensec_krb5',
10661
         enabled=bld.AD_DC_BUILD_IS_ENABLED()
10662
 	)
10663
 
10664
+bld.SAMBA_SUBSYSTEM('gensec_krb5_helpers',
10665
+    source='gensec_krb5_helpers.c',
10666
+    deps='gensec_krb5',
10667
+    enabled=bld.AD_DC_BUILD_IS_ENABLED())
10668
 
10669
 bld.SAMBA_MODULE('gensec_gssapi',
10670
 	source='gensec_gssapi.c',
10671
-- 
10672
2.25.1
10673
10674
10675
From 6c4fd575d706b2695090941ad7947b30abdb9071 Mon Sep 17 00:00:00 2001
10676
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10677
Date: Wed, 18 May 2022 16:52:41 +1200
10678
Subject: [PATCH 77/99] CVE-2022-2031 s4:kpasswd: Require an initial ticket
10679
10680
Ensure that for password changes the client uses an AS-REQ to get the
10681
ticket to kpasswd, and not a TGS-REQ.
10682
10683
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10684
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
10685
10686
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10687
Reviewed-by: Andreas Schneider <asn@samba.org>
10688
10689
[jsutton@samba.org Removed MIT KDC 1.20-specific knownfails]
10690
---
10691
 selftest/knownfail_heimdal_kdc        |  1 -
10692
 selftest/knownfail_mit_kdc            |  1 -
10693
 source4/kdc/kpasswd-service-heimdal.c | 17 +++++++++++++++++
10694
 source4/kdc/kpasswd-service-mit.c     | 17 +++++++++++++++++
10695
 source4/kdc/wscript_build             |  1 +
10696
 5 files changed, 35 insertions(+), 2 deletions(-)
10697
10698
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
10699
index 3b494baa658..5cd8615f6a9 100644
10700
--- selftest/knownfail_heimdal_kdc
10701
+++ selftest/knownfail_heimdal_kdc
10702
@@ -277,7 +277,6 @@
10703
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
10704
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10705
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
10706
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10707
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10708
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10709
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
10710
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
10711
index f64291e776d..46b0f1fa9ed 100644
10712
--- selftest/knownfail_mit_kdc
10713
+++ selftest/knownfail_mit_kdc
10714
@@ -580,7 +580,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
10715
 #
10716
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
10717
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
10718
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_non_initial.ad_dc
10719
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
10720
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
10721
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
10722
diff --git source4/kdc/kpasswd-service-heimdal.c source4/kdc/kpasswd-service-heimdal.c
10723
index c804852c3a7..1a6c2b60d03 100644
10724
--- source4/kdc/kpasswd-service-heimdal.c
10725
+++ source4/kdc/kpasswd-service-heimdal.c
10726
@@ -24,6 +24,7 @@
10727
 #include "param/param.h"
10728
 #include "auth/auth.h"
10729
 #include "auth/gensec/gensec.h"
10730
+#include "gensec_krb5_helpers.h"
10731
 #include "kdc/kdc-server.h"
10732
 #include "kdc/kpasswd_glue.h"
10733
 #include "kdc/kpasswd-service.h"
10734
@@ -31,6 +32,7 @@
10735
 
10736
 static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
10737
 					       TALLOC_CTX *mem_ctx,
10738
+					       const struct gensec_security *gensec_security,
10739
 					       struct auth_session_info *session_info,
10740
 					       DATA_BLOB *password,
10741
 					       DATA_BLOB *kpasswd_reply,
10742
@@ -42,6 +44,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
10743
 	const char *reject_string = NULL;
10744
 	struct samr_DomInfo1 *dominfo;
10745
 	bool ok;
10746
+	int ret;
10747
+
10748
+	/*
10749
+	 * We're doing a password change (rather than a password set), so check
10750
+	 * that we were given an initial ticket.
10751
+	 */
10752
+	ret = gensec_krb5_initial_ticket(gensec_security);
10753
+	if (ret != 1) {
10754
+		*error_string = "Expected an initial ticket";
10755
+		return KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
10756
+	}
10757
 
10758
 	status = samdb_kpasswd_change_password(mem_ctx,
10759
 					       kdc->task->lp_ctx,
10760
@@ -81,6 +94,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
10761
 
10762
 static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
10763
 					    TALLOC_CTX *mem_ctx,
10764
+					    const struct gensec_security *gensec_security,
10765
 					    struct auth_session_info *session_info,
10766
 					    DATA_BLOB *decoded_data,
10767
 					    DATA_BLOB *kpasswd_reply,
10768
@@ -173,6 +187,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
10769
 		free_ChangePasswdDataMS(&chpw);
10770
 		return kpasswd_change_password(kdc,
10771
 					       mem_ctx,
10772
+					       gensec_security,
10773
 					       session_info,
10774
 					       &password,
10775
 					       kpasswd_reply,
10776
@@ -272,6 +287,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
10777
 
10778
 		return kpasswd_change_password(kdc,
10779
 					       mem_ctx,
10780
+					       gensec_security,
10781
 					       session_info,
10782
 					       &password,
10783
 					       kpasswd_reply,
10784
@@ -280,6 +296,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
10785
 	case KRB5_KPASSWD_VERS_SETPW: {
10786
 		return kpasswd_set_password(kdc,
10787
 					    mem_ctx,
10788
+					    gensec_security,
10789
 					    session_info,
10790
 					    decoded_data,
10791
 					    kpasswd_reply,
10792
diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c
10793
index 9c4d2801669..de4c6f3f622 100644
10794
--- source4/kdc/kpasswd-service-mit.c
10795
+++ source4/kdc/kpasswd-service-mit.c
10796
@@ -24,6 +24,7 @@
10797
 #include "param/param.h"
10798
 #include "auth/auth.h"
10799
 #include "auth/gensec/gensec.h"
10800
+#include "gensec_krb5_helpers.h"
10801
 #include "kdc/kdc-server.h"
10802
 #include "kdc/kpasswd_glue.h"
10803
 #include "kdc/kpasswd-service.h"
10804
@@ -84,6 +85,7 @@ out:
10805
 
10806
 static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
10807
 					       TALLOC_CTX *mem_ctx,
10808
+					       const struct gensec_security *gensec_security,
10809
 					       struct auth_session_info *session_info,
10810
 					       DATA_BLOB *password,
10811
 					       DATA_BLOB *kpasswd_reply,
10812
@@ -95,6 +97,17 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
10813
 	const char *reject_string = NULL;
10814
 	struct samr_DomInfo1 *dominfo;
10815
 	bool ok;
10816
+	int ret;
10817
+
10818
+	/*
10819
+	 * We're doing a password change (rather than a password set), so check
10820
+	 * that we were given an initial ticket.
10821
+	 */
10822
+	ret = gensec_krb5_initial_ticket(gensec_security);
10823
+	if (ret != 1) {
10824
+		*error_string = "Expected an initial ticket";
10825
+		return KRB5_KPASSWD_INITIAL_FLAG_NEEDED;
10826
+	}
10827
 
10828
 	status = samdb_kpasswd_change_password(mem_ctx,
10829
 					       kdc->task->lp_ctx,
10830
@@ -134,6 +147,7 @@ static krb5_error_code kpasswd_change_password(struct kdc_server *kdc,
10831
 
10832
 static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
10833
 					    TALLOC_CTX *mem_ctx,
10834
+					    const struct gensec_security *gensec_security,
10835
 					    struct auth_session_info *session_info,
10836
 					    DATA_BLOB *decoded_data,
10837
 					    DATA_BLOB *kpasswd_reply,
10838
@@ -250,6 +264,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
10839
 
10840
 		return kpasswd_change_password(kdc,
10841
 					       mem_ctx,
10842
+					       gensec_security,
10843
 					       session_info,
10844
 					       &password,
10845
 					       kpasswd_reply,
10846
@@ -350,6 +365,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
10847
 
10848
 		return kpasswd_change_password(kdc,
10849
 					       mem_ctx,
10850
+					       gensec_security,
10851
 					       session_info,
10852
 					       &password,
10853
 					       kpasswd_reply,
10854
@@ -358,6 +374,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
10855
 	case RFC3244_VERSION: {
10856
 		return kpasswd_set_password(kdc,
10857
 					    mem_ctx,
10858
+					    gensec_security,
10859
 					    session_info,
10860
 					    decoded_data,
10861
 					    kpasswd_reply,
10862
diff --git source4/kdc/wscript_build source4/kdc/wscript_build
10863
index 0edca94e75f..13ba3947cf6 100644
10864
--- source4/kdc/wscript_build
10865
+++ source4/kdc/wscript_build
10866
@@ -88,6 +88,7 @@ bld.SAMBA_SUBSYSTEM('KPASSWD-SERVICE',
10867
                          krb5samba
10868
                          samba_server_gensec
10869
                          KPASSWD_GLUE
10870
+                         gensec_krb5_helpers
10871
                          ''')
10872
 
10873
 bld.SAMBA_SUBSYSTEM('KDC-GLUE',
10874
-- 
10875
2.25.1
10876
10877
10878
From 69e742e6208bd471eb509795bd753a0c98392bf6 Mon Sep 17 00:00:00 2001
10879
From: Joseph Sutton <josephsutton@catalyst.net.nz>
10880
Date: Wed, 18 May 2022 17:11:49 +1200
10881
Subject: [PATCH 78/99] s4:kpasswd: Restructure code for clarity
10882
10883
View with 'git show -b'.
10884
10885
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10886
Reviewed-by: Andreas Schneider <asn@samba.org>
10887
---
10888
 source4/kdc/kpasswd-service-heimdal.c | 46 +++++++++++++--------------
10889
 1 file changed, 22 insertions(+), 24 deletions(-)
10890
10891
diff --git source4/kdc/kpasswd-service-heimdal.c source4/kdc/kpasswd-service-heimdal.c
10892
index 1a6c2b60d03..a0352d1ad35 100644
10893
--- source4/kdc/kpasswd-service-heimdal.c
10894
+++ source4/kdc/kpasswd-service-heimdal.c
10895
@@ -160,30 +160,7 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
10896
 		return 0;
10897
 	}
10898
 
10899
-	if (chpw.targname != NULL && chpw.targrealm != NULL) {
10900
-		code = krb5_build_principal_ext(context,
10901
-					       &target_principal,
10902
-					       strlen(*chpw.targrealm),
10903
-					       *chpw.targrealm,
10904
-					       0);
10905
-		if (code != 0) {
10906
-			free_ChangePasswdDataMS(&chpw);
10907
-			return kpasswd_make_error_reply(mem_ctx,
10908
-							KRB5_KPASSWD_MALFORMED,
10909
-							"Failed to parse principal",
10910
-							kpasswd_reply);
10911
-		}
10912
-		code = copy_PrincipalName(chpw.targname,
10913
-					  &target_principal->name);
10914
-		if (code != 0) {
10915
-			free_ChangePasswdDataMS(&chpw);
10916
-			krb5_free_principal(context, target_principal);
10917
-			return kpasswd_make_error_reply(mem_ctx,
10918
-							KRB5_KPASSWD_MALFORMED,
10919
-							"Failed to parse principal",
10920
-							kpasswd_reply);
10921
-		}
10922
-	} else {
10923
+	if (chpw.targname == NULL || chpw.targrealm == NULL) {
10924
 		free_ChangePasswdDataMS(&chpw);
10925
 		return kpasswd_change_password(kdc,
10926
 					       mem_ctx,
10927
@@ -193,7 +170,28 @@ static krb5_error_code kpasswd_set_password(struct kdc_server *kdc,
10928
 					       kpasswd_reply,
10929
 					       error_string);
10930
 	}
10931
+	code = krb5_build_principal_ext(context,
10932
+					&target_principal,
10933
+					strlen(*chpw.targrealm),
10934
+					*chpw.targrealm,
10935
+					0);
10936
+	if (code != 0) {
10937
+		free_ChangePasswdDataMS(&chpw);
10938
+		return kpasswd_make_error_reply(mem_ctx,
10939
+						KRB5_KPASSWD_MALFORMED,
10940
+						"Failed to parse principal",
10941
+						kpasswd_reply);
10942
+	}
10943
+	code = copy_PrincipalName(chpw.targname,
10944
+				  &target_principal->name);
10945
 	free_ChangePasswdDataMS(&chpw);
10946
+	if (code != 0) {
10947
+		krb5_free_principal(context, target_principal);
10948
+		return kpasswd_make_error_reply(mem_ctx,
10949
+						KRB5_KPASSWD_MALFORMED,
10950
+						"Failed to parse principal",
10951
+						kpasswd_reply);
10952
+	}
10953
 
10954
 	if (target_principal->name.name_string.len >= 2) {
10955
 		is_service_principal = true;
10956
-- 
10957
2.25.1
10958
10959
10960
From b5adf7cc6d740c8f4f7b5888f106de24a1181da7 Mon Sep 17 00:00:00 2001
10961
From: Andreas Schneider <asn@samba.org>
10962
Date: Tue, 24 May 2022 10:17:00 +0200
10963
Subject: [PATCH 79/99] CVE-2022-2031 testprogs: Fix auth with smbclient and
10964
 krb5 ccache
10965
10966
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
10967
10968
Signed-off-by: Andreas Schneider <asn@samba.org>
10969
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
10970
10971
[jsutton@samba.org Fixed conflict and renamed --use-krb5-ccache to
10972
 --krb5-ccache]
10973
---
10974
 testprogs/blackbox/test_kpasswd_heimdal.sh | 4 ++--
10975
 1 file changed, 2 insertions(+), 2 deletions(-)
10976
10977
diff --git testprogs/blackbox/test_kpasswd_heimdal.sh testprogs/blackbox/test_kpasswd_heimdal.sh
10978
index 7351ce022d1..1e895daa162 100755
10979
--- testprogs/blackbox/test_kpasswd_heimdal.sh
10980
+++ testprogs/blackbox/test_kpasswd_heimdal.sh
10981
@@ -72,7 +72,7 @@ testit "kinit with user password" \
10982
 	do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1`
10983
 
10984
 test_smbclient "Test login with user kerberos ccache" \
10985
-	"ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1`
10986
+	"ls" "$SMB_UNC" --krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1`
10987
 
10988
 testit "change user password with 'samba-tool user password' (unforced)" \
10989
 	$VALGRIND $PYTHON $samba_tool user password -W$DOMAIN -U$TEST_USERNAME%$TEST_PASSWORD -k no --newpassword=$TEST_PASSWORD_NEW || failed=`expr $failed + 1`
10990
@@ -85,7 +85,7 @@ testit "kinit with user password" \
10991
 	do_kinit $TEST_PRINCIPAL $TEST_PASSWORD || failed=`expr $failed + 1`
10992
 
10993
 test_smbclient "Test login with user kerberos ccache" \
10994
-	"ls" "$SMB_UNC" -k yes || failed=`expr $failed + 1`
10995
+	"ls" "$SMB_UNC" --krb5-ccache=${KRB5CCNAME} || failed=`expr $failed + 1`
10996
 
10997
 ###########################################################
10998
 ### check that a short password is rejected
10999
-- 
11000
2.25.1
11001
11002
11003
From 91a1b0955a053f73e6d531f0f12eaa604aca79d7 Mon Sep 17 00:00:00 2001
11004
From: Andreas Schneider <asn@samba.org>
11005
Date: Thu, 19 May 2022 16:35:28 +0200
11006
Subject: [PATCH 80/99] CVE-2022-2031 testprogs: Add kadmin/changepw
11007
 canonicalization test with MIT kpasswd
11008
11009
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11010
11011
Signed-off-by: Andreas Schneider <asn@samba.org>
11012
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11013
---
11014
 selftest/knownfail.d/kadmin_changepw       |  1 +
11015
 testprogs/blackbox/test_kpasswd_heimdal.sh | 35 +++++++++++++++++++++-
11016
 2 files changed, 35 insertions(+), 1 deletion(-)
11017
 create mode 100644 selftest/knownfail.d/kadmin_changepw
11018
11019
diff --git selftest/knownfail.d/kadmin_changepw selftest/knownfail.d/kadmin_changepw
11020
new file mode 100644
11021
index 00000000000..97c14793ea5
11022
--- /dev/null
11023
+++ selftest/knownfail.d/kadmin_changepw
11024
@@ -0,0 +1 @@
11025
+^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password
11026
diff --git testprogs/blackbox/test_kpasswd_heimdal.sh testprogs/blackbox/test_kpasswd_heimdal.sh
11027
index 1e895daa162..059b7a8e4d1 100755
11028
--- testprogs/blackbox/test_kpasswd_heimdal.sh
11029
+++ testprogs/blackbox/test_kpasswd_heimdal.sh
11030
@@ -7,7 +7,7 @@
11031
 
11032
 if [ $# -lt 6 ]; then
11033
 cat <<EOF
11034
-Usage: test_passwords.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX SMBCLIENT
11035
+Usage: test_kpasswd_heimdal.sh SERVER USERNAME PASSWORD REALM DOMAIN PREFIX SMBCLIENT
11036
 EOF
11037
 exit 1;
11038
 fi
11039
@@ -27,6 +27,8 @@ smbclient="$samba_bindir/smbclient"
11040
 samba_kinit=$samba_bindir/samba4kinit
11041
 samba_kpasswd=$samba_bindir/samba4kpasswd
11042
 
11043
+mit_kpasswd="$(command -v kpasswd)"
11044
+
11045
 samba_tool="$samba_bindir/samba-tool"
11046
 net_tool="$samba_bindir/net"
11047
 texpect="$samba_bindir/texpect"
11048
@@ -142,6 +144,37 @@ testit "kpasswd change user password" \
11049
 TEST_PASSWORD=$TEST_PASSWORD_NEW
11050
 TEST_PASSWORD_NEW="testPaSS@03%"
11051
 
11052
+###########################################################
11053
+### CVE-2022-XXXXX
11054
+###########################################################
11055
+
11056
+if [ -n "${mit_kpasswd}" ]; then
11057
+	cat > "${PREFIX}/tmpkpasswdscript" <<EOF
11058
+expect Password for ${TEST_PRINCIPAL}
11059
+password ${TEST_PASSWORD}\n
11060
+expect Enter new password
11061
+send ${TEST_PASSWORD_NEW}\n
11062
+expect Enter it again
11063
+send ${TEST_PASSWORD_NEW}\n
11064
+expect Password changed.
11065
+EOF
11066
+
11067
+	SAVE_KRB5_CONFIG="${KRB5_CONFIG}"
11068
+	KRB5_CONFIG="${PREFIX}/tmpkrb5.conf"
11069
+	export KRB5_CONFIG
11070
+	sed -e 's/\[libdefaults\]/[libdefaults]\n canonicalize = yes/' \
11071
+		"${SAVE_KRB5_CONFIG}" > "${KRB5_CONFIG}"
11072
+	testit "MIT kpasswd change user password" \
11073
+		"${texpect}" "${PREFIX}/tmpkpasswdscript" "${mit_kpasswd}" \
11074
+		"${TEST_PRINCIPAL}" ||
11075
+		failed=$((failed + 1))
11076
+	KRB5_CONFIG="${SAVE_KRB5_CONFIG}"
11077
+	export KRB5_CONFIG
11078
+fi
11079
+
11080
+TEST_PASSWORD="${TEST_PASSWORD_NEW}"
11081
+TEST_PASSWORD_NEW="testPaSS@03force%"
11082
+
11083
 ###########################################################
11084
 ### Force password change at login
11085
 ###########################################################
11086
-- 
11087
2.25.1
11088
11089
11090
From 36d94ffb9c99f3e515024424020e3e03e98f34f5 Mon Sep 17 00:00:00 2001
11091
From: Andreas Schneider <asn@samba.org>
11092
Date: Tue, 24 May 2022 09:54:18 +0200
11093
Subject: [PATCH 81/99] CVE-2022-2031 s4:kdc: Implement is_kadmin_changepw()
11094
 helper function
11095
11096
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11097
11098
Signed-off-by: Andreas Schneider <asn@samba.org>
11099
Reviewed-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11100
11101
[jsutton@samba.org Adapted entry to entry_ex->entry]
11102
---
11103
 source4/kdc/db-glue.c | 16 +++++++++++-----
11104
 1 file changed, 11 insertions(+), 5 deletions(-)
11105
11106
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
11107
index 5752ffb821c..45159e6e64d 100644
11108
--- source4/kdc/db-glue.c
11109
+++ source4/kdc/db-glue.c
11110
@@ -816,6 +816,14 @@ static int principal_comp_strcmp(krb5_context context,
11111
 					 component, string, false);
11112
 }
11113
 
11114
+static bool is_kadmin_changepw(krb5_context context,
11115
+			       krb5_const_principal principal)
11116
+{
11117
+	return krb5_princ_size(context, principal) == 2 &&
11118
+		(principal_comp_strcmp(context, principal, 0, "kadmin") == 0) &&
11119
+		(principal_comp_strcmp(context, principal, 1, "changepw") == 0);
11120
+}
11121
+
11122
 /*
11123
  * Construct an hdb_entry from a directory entry.
11124
  */
11125
@@ -1110,11 +1118,9 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
11126
 		 * 'change password', as otherwise we could get into
11127
 		 * trouble, and not enforce the password expirty.
11128
 		 * Instead, only do it when request is for the kpasswd service */
11129
-		if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER
11130
-		    && krb5_princ_size(context, principal) == 2
11131
-		    && (principal_comp_strcmp(context, principal, 0, "kadmin") == 0)
11132
-		    && (principal_comp_strcmp(context, principal, 1, "changepw") == 0)
11133
-		    && lpcfg_is_my_domain_or_realm(lp_ctx, realm)) {
11134
+		if (ent_type == SAMBA_KDC_ENT_TYPE_SERVER &&
11135
+		    is_kadmin_changepw(context, principal) &&
11136
+		    lpcfg_is_my_domain_or_realm(lp_ctx, realm)) {
11137
 			entry_ex->entry.flags.change_pw = 1;
11138
 		}
11139
 
11140
-- 
11141
2.25.1
11142
11143
11144
From f68877af829bf73da8e965c9458a9846d1757038 Mon Sep 17 00:00:00 2001
11145
From: Joseph Sutton <josephsutton@catalyst.net.nz>
11146
Date: Wed, 18 May 2022 16:56:01 +1200
11147
Subject: [PATCH 82/99] CVE-2022-2031 s4:kdc: Split out a
11148
 samba_kdc_get_entry_principal() function
11149
11150
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11151
11152
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11153
Reviewed-by: Andreas Schneider <asn@samba.org>
11154
11155
[jsutton@samba.org Adapted entry to entry_ex->entry]
11156
11157
[jsutton@samba.org Fixed conflicts caused by superfluous whitespace]
11158
---
11159
 source4/kdc/db-glue.c | 192 +++++++++++++++++++++++-------------------
11160
 1 file changed, 107 insertions(+), 85 deletions(-)
11161
11162
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
11163
index 45159e6e64d..ac0c206b5c1 100644
11164
--- source4/kdc/db-glue.c
11165
+++ source4/kdc/db-glue.c
11166
@@ -824,6 +824,101 @@ static bool is_kadmin_changepw(krb5_context context,
11167
 		(principal_comp_strcmp(context, principal, 1, "changepw") == 0);
11168
 }
11169
 
11170
+static krb5_error_code samba_kdc_get_entry_principal(
11171
+		krb5_context context,
11172
+		struct samba_kdc_db_context *kdc_db_ctx,
11173
+		const char *samAccountName,
11174
+		enum samba_kdc_ent_type ent_type,
11175
+		unsigned flags,
11176
+		krb5_const_principal in_princ,
11177
+		krb5_principal *out_princ)
11178
+{
11179
+	struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
11180
+	krb5_error_code ret = 0;
11181
+
11182
+	/*
11183
+	 * If we are set to canonicalize, we get back the fixed UPPER
11184
+	 * case realm, and the real username (ie matching LDAP
11185
+	 * samAccountName)
11186
+	 *
11187
+	 * Otherwise, if we are set to enterprise, we
11188
+	 * get back the whole principal as-sent
11189
+	 *
11190
+	 * Finally, if we are not set to canonicalize, we get back the
11191
+	 * fixed UPPER case realm, but the as-sent username
11192
+	 */
11193
+
11194
+	if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
11195
+		if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) {
11196
+			/*
11197
+			 * When requested to do so, ensure that the
11198
+			 * both realm values in the principal are set
11199
+			 * to the upper case, canonical realm
11200
+			 */
11201
+			ret = smb_krb5_make_principal(context, out_princ,
11202
+						      lpcfg_realm(lp_ctx), "krbtgt",
11203
+						      lpcfg_realm(lp_ctx), NULL);
11204
+			if (ret) {
11205
+				return ret;
11206
+			}
11207
+			smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST);
11208
+		} else {
11209
+			ret = krb5_copy_principal(context, in_princ, out_princ);
11210
+			if (ret) {
11211
+				return ret;
11212
+			}
11213
+			/*
11214
+			 * this appears to be required regardless of
11215
+			 * the canonicalize flag from the client
11216
+			 */
11217
+			ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx));
11218
+			if (ret) {
11219
+				return ret;
11220
+			}
11221
+		}
11222
+
11223
+	} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) {
11224
+		ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL);
11225
+		if (ret) {
11226
+			return ret;
11227
+		}
11228
+	} else if ((flags & SDB_F_FORCE_CANON) ||
11229
+		   ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) {
11230
+		/*
11231
+		 * SDB_F_CANON maps from the canonicalize flag in the
11232
+		 * packet, and has a different meaning between AS-REQ
11233
+		 * and TGS-REQ.  We only change the principal in the AS-REQ case
11234
+		 *
11235
+		 * The SDB_F_FORCE_CANON if for new MIT KDC code that wants
11236
+		 * the canonical name in all lookups, and takes care to
11237
+		 * canonicalize only when appropriate.
11238
+		 */
11239
+		ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL);
11240
+		if (ret) {
11241
+			return ret;
11242
+		}
11243
+	} else {
11244
+		ret = krb5_copy_principal(context, in_princ, out_princ);
11245
+		if (ret) {
11246
+			return ret;
11247
+		}
11248
+
11249
+		/* While we have copied the client principal, tests
11250
+		 * show that Win2k3 returns the 'corrected' realm, not
11251
+		 * the client-specified realm.  This code attempts to
11252
+		 * replace the client principal's realm with the one
11253
+		 * we determine from our records */
11254
+
11255
+		/* this has to be with malloc() */
11256
+		ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx));
11257
+		if (ret) {
11258
+			return ret;
11259
+		}
11260
+	}
11261
+
11262
+	return 0;
11263
+}
11264
+
11265
 /*
11266
  * Construct an hdb_entry from a directory entry.
11267
  */
11268
@@ -913,93 +1008,8 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
11269
 		userAccountControl |= msDS_User_Account_Control_Computed;
11270
 	}
11271
 
11272
-	/* 
11273
-	 * If we are set to canonicalize, we get back the fixed UPPER
11274
-	 * case realm, and the real username (ie matching LDAP
11275
-	 * samAccountName) 
11276
-	 *
11277
-	 * Otherwise, if we are set to enterprise, we
11278
-	 * get back the whole principal as-sent 
11279
-	 *
11280
-	 * Finally, if we are not set to canonicalize, we get back the
11281
-	 * fixed UPPER case realm, but the as-sent username
11282
-	 */
11283
-
11284
 	if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
11285
 		p->is_krbtgt = true;
11286
-
11287
-		if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) {
11288
-			/*
11289
-			 * When requested to do so, ensure that the
11290
-			 * both realm values in the principal are set
11291
-			 * to the upper case, canonical realm
11292
-			 */
11293
-			ret = smb_krb5_make_principal(context, &entry_ex->entry.principal,
11294
-						      lpcfg_realm(lp_ctx), "krbtgt",
11295
-						      lpcfg_realm(lp_ctx), NULL);
11296
-			if (ret) {
11297
-				krb5_clear_error_message(context);
11298
-				goto out;
11299
-			}
11300
-			smb_krb5_principal_set_type(context, entry_ex->entry.principal, KRB5_NT_SRV_INST);
11301
-		} else {
11302
-			ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal);
11303
-			if (ret) {
11304
-				krb5_clear_error_message(context);
11305
-				goto out;
11306
-			}
11307
-			/*
11308
-			 * this appears to be required regardless of
11309
-			 * the canonicalize flag from the client
11310
-			 */
11311
-			ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx));
11312
-			if (ret) {
11313
-				krb5_clear_error_message(context);
11314
-				goto out;
11315
-			}
11316
-		}
11317
-
11318
-	} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && principal == NULL) {
11319
-		ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
11320
-		if (ret) {
11321
-			krb5_clear_error_message(context);
11322
-			goto out;
11323
-		}
11324
-	} else if ((flags & SDB_F_FORCE_CANON) ||
11325
-		   ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) {
11326
-		/*
11327
-		 * SDB_F_CANON maps from the canonicalize flag in the
11328
-		 * packet, and has a different meaning between AS-REQ
11329
-		 * and TGS-REQ.  We only change the principal in the AS-REQ case
11330
-		 *
11331
-		 * The SDB_F_FORCE_CANON if for new MIT KDC code that wants
11332
-		 * the canonical name in all lookups, and takes care to
11333
-		 * canonicalize only when appropriate.
11334
-		 */
11335
-		ret = smb_krb5_make_principal(context, &entry_ex->entry.principal, lpcfg_realm(lp_ctx), samAccountName, NULL);
11336
-		if (ret) {
11337
-			krb5_clear_error_message(context);
11338
-			goto out;
11339
-		}
11340
-	} else {
11341
-		ret = krb5_copy_principal(context, principal, &entry_ex->entry.principal);
11342
-		if (ret) {
11343
-			krb5_clear_error_message(context);
11344
-			goto out;
11345
-		}
11346
-
11347
-		/* While we have copied the client principal, tests
11348
-		 * show that Win2k3 returns the 'corrected' realm, not
11349
-		 * the client-specified realm.  This code attempts to
11350
-		 * replace the client principal's realm with the one
11351
-		 * we determine from our records */
11352
-
11353
-		/* this has to be with malloc() */
11354
-		ret = smb_krb5_principal_set_realm(context, entry_ex->entry.principal, lpcfg_realm(lp_ctx));
11355
-		if (ret) {
11356
-			krb5_clear_error_message(context);
11357
-			goto out;
11358
-		}
11359
 	}
11360
 
11361
 	/* First try and figure out the flags based on the userAccountControl */
11362
@@ -1185,6 +1195,18 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
11363
 		}
11364
 	}
11365
 
11366
+	ret = samba_kdc_get_entry_principal(context,
11367
+					    kdc_db_ctx,
11368
+					    samAccountName,
11369
+					    ent_type,
11370
+					    flags,
11371
+					    principal,
11372
+					    &entry_ex->entry.principal);
11373
+	if (ret != 0) {
11374
+		krb5_clear_error_message(context);
11375
+		goto out;
11376
+	}
11377
+
11378
 	entry_ex->entry.valid_start = NULL;
11379
 
11380
 	entry_ex->entry.max_life = malloc(sizeof(*entry_ex->entry.max_life));
11381
-- 
11382
2.25.1
11383
11384
11385
From fa4742e1b9dea0b9c379f00666478bd41c021634 Mon Sep 17 00:00:00 2001
11386
From: Joseph Sutton <josephsutton@catalyst.net.nz>
11387
Date: Wed, 25 May 2022 17:19:58 +1200
11388
Subject: [PATCH 83/99] CVE-2022-2031 s4:kdc: Refactor
11389
 samba_kdc_get_entry_principal()
11390
11391
This eliminates some duplicate branches.
11392
11393
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11394
11395
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11396
Pair-Programmed-With: Andreas Schneider <asn@samba.org>
11397
Reviewed-by: Andreas Schneider <asn@samba.org>
11398
---
11399
 source4/kdc/db-glue.c | 116 ++++++++++++++++++++----------------------
11400
 1 file changed, 55 insertions(+), 61 deletions(-)
11401
11402
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
11403
index ac0c206b5c1..385c118a073 100644
11404
--- source4/kdc/db-glue.c
11405
+++ source4/kdc/db-glue.c
11406
@@ -834,7 +834,8 @@ static krb5_error_code samba_kdc_get_entry_principal(
11407
 		krb5_principal *out_princ)
11408
 {
11409
 	struct loadparm_context *lp_ctx = kdc_db_ctx->lp_ctx;
11410
-	krb5_error_code ret = 0;
11411
+	krb5_error_code code = 0;
11412
+	bool canon = flags & (SDB_F_CANON|SDB_F_FORCE_CANON);
11413
 
11414
 	/*
11415
 	 * If we are set to canonicalize, we get back the fixed UPPER
11416
@@ -848,75 +849,68 @@ static krb5_error_code samba_kdc_get_entry_principal(
11417
 	 * fixed UPPER case realm, but the as-sent username
11418
 	 */
11419
 
11420
-	if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT) {
11421
-		if (flags & (SDB_F_CANON|SDB_F_FORCE_CANON)) {
11422
-			/*
11423
-			 * When requested to do so, ensure that the
11424
-			 * both realm values in the principal are set
11425
-			 * to the upper case, canonical realm
11426
-			 */
11427
-			ret = smb_krb5_make_principal(context, out_princ,
11428
-						      lpcfg_realm(lp_ctx), "krbtgt",
11429
-						      lpcfg_realm(lp_ctx), NULL);
11430
-			if (ret) {
11431
-				return ret;
11432
-			}
11433
-			smb_krb5_principal_set_type(context, *out_princ, KRB5_NT_SRV_INST);
11434
-		} else {
11435
-			ret = krb5_copy_principal(context, in_princ, out_princ);
11436
-			if (ret) {
11437
-				return ret;
11438
-			}
11439
-			/*
11440
-			 * this appears to be required regardless of
11441
-			 * the canonicalize flag from the client
11442
-			 */
11443
-			ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx));
11444
-			if (ret) {
11445
-				return ret;
11446
-			}
11447
-		}
11448
+	if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) {
11449
+		/*
11450
+		 * When requested to do so, ensure that the
11451
+		 * both realm values in the principal are set
11452
+		 * to the upper case, canonical realm
11453
+		 */
11454
+		code = smb_krb5_make_principal(context,
11455
+					       out_princ,
11456
+					       lpcfg_realm(lp_ctx),
11457
+					       "krbtgt",
11458
+					       lpcfg_realm(lp_ctx),
11459
+					       NULL);
11460
+		if (code != 0) {
11461
+			return code;
11462
+		}
11463
+		smb_krb5_principal_set_type(context,
11464
+					    *out_princ,
11465
+					    KRB5_NT_SRV_INST);
11466
 
11467
-	} else if (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL) {
11468
-		ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL);
11469
-		if (ret) {
11470
-			return ret;
11471
-		}
11472
-	} else if ((flags & SDB_F_FORCE_CANON) ||
11473
-		   ((flags & SDB_F_CANON) && (flags & SDB_F_FOR_AS_REQ))) {
11474
+		return 0;
11475
+	}
11476
+
11477
+	if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) ||
11478
+	    (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) {
11479
 		/*
11480
 		 * SDB_F_CANON maps from the canonicalize flag in the
11481
 		 * packet, and has a different meaning between AS-REQ
11482
-		 * and TGS-REQ.  We only change the principal in the AS-REQ case
11483
+		 * and TGS-REQ.  We only change the principal in the
11484
+		 * AS-REQ case.
11485
 		 *
11486
-		 * The SDB_F_FORCE_CANON if for new MIT KDC code that wants
11487
-		 * the canonical name in all lookups, and takes care to
11488
-		 * canonicalize only when appropriate.
11489
+		 * The SDB_F_FORCE_CANON if for new MIT KDC code that
11490
+		 * wants the canonical name in all lookups, and takes
11491
+		 * care to canonicalize only when appropriate.
11492
 		 */
11493
-		ret = smb_krb5_make_principal(context, out_princ, lpcfg_realm(lp_ctx), samAccountName, NULL);
11494
-		if (ret) {
11495
-			return ret;
11496
-		}
11497
-	} else {
11498
-		ret = krb5_copy_principal(context, in_princ, out_princ);
11499
-		if (ret) {
11500
-			return ret;
11501
-		}
11502
-
11503
-		/* While we have copied the client principal, tests
11504
-		 * show that Win2k3 returns the 'corrected' realm, not
11505
-		 * the client-specified realm.  This code attempts to
11506
-		 * replace the client principal's realm with the one
11507
-		 * we determine from our records */
11508
+		code = smb_krb5_make_principal(context,
11509
+					      out_princ,
11510
+					      lpcfg_realm(lp_ctx),
11511
+					      samAccountName,
11512
+					      NULL);
11513
+		return code;
11514
+	}
11515
 
11516
-		/* this has to be with malloc() */
11517
-		ret = smb_krb5_principal_set_realm(context, *out_princ, lpcfg_realm(lp_ctx));
11518
-		if (ret) {
11519
-			return ret;
11520
-		}
11521
+	/*
11522
+	 * For a krbtgt entry, this appears to be required regardless of the
11523
+	 * canonicalize flag from the client.
11524
+	 */
11525
+	code = krb5_copy_principal(context, in_princ, out_princ);
11526
+	if (code != 0) {
11527
+		return code;
11528
 	}
11529
 
11530
-	return 0;
11531
+	/*
11532
+	 * While we have copied the client principal, tests show that Win2k3
11533
+	 * returns the 'corrected' realm, not the client-specified realm.  This
11534
+	 * code attempts to replace the client principal's realm with the one
11535
+	 * we determine from our records
11536
+	 */
11537
+	code = smb_krb5_principal_set_realm(context,
11538
+					    *out_princ,
11539
+					    lpcfg_realm(lp_ctx));
11540
+
11541
+	return code;
11542
 }
11543
 
11544
 /*
11545
-- 
11546
2.25.1
11547
11548
11549
From 3cab62893668742781551dae6505558e47cf08b5 Mon Sep 17 00:00:00 2001
11550
From: Joseph Sutton <josephsutton@catalyst.net.nz>
11551
Date: Wed, 18 May 2022 16:56:01 +1200
11552
Subject: [PATCH 84/99] CVE-2022-2031 s4:kdc: Fix canonicalisation of
11553
 kadmin/changepw principal
11554
11555
Since this principal goes through the samba_kdc_fetch_server() path,
11556
setting the canonicalisation flag would cause the principal to be
11557
replaced with the sAMAccountName; this meant requests to
11558
kadmin/changepw@REALM would result in a ticket to krbtgt@REALM. Now we
11559
properly handle canonicalisation for the kadmin/changepw principal.
11560
11561
View with 'git show -b'.
11562
11563
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11564
11565
Pair-Programmed-With: Andreas Schneider <asn@samba.org>
11566
Signed-off-by: Andreas Schneider <asn@samba.org>
11567
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11568
Reviewed-by: Andreas Schneider <asn@samba.org>
11569
11570
[jsutton@samba.org Adapted entry to entry_ex->entry; removed MIT KDC
11571
 1.20-specific knownfails]
11572
---
11573
 selftest/knownfail.d/kadmin_changepw |  1 -
11574
 selftest/knownfail_heimdal_kdc       |  2 -
11575
 source4/kdc/db-glue.c                | 84 +++++++++++++++-------------
11576
 3 files changed, 46 insertions(+), 41 deletions(-)
11577
 delete mode 100644 selftest/knownfail.d/kadmin_changepw
11578
11579
diff --git selftest/knownfail.d/kadmin_changepw selftest/knownfail.d/kadmin_changepw
11580
deleted file mode 100644
11581
index 97c14793ea5..00000000000
11582
--- selftest/knownfail.d/kadmin_changepw
11583
+++ /dev/null
11584
@@ -1 +0,0 @@
11585
-^samba4.blackbox.kpasswd.MIT kpasswd.change.user.password
11586
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
11587
index 5cd8615f6a9..49ab29f115d 100644
11588
--- selftest/knownfail_heimdal_kdc
11589
+++ selftest/knownfail_heimdal_kdc
11590
@@ -274,8 +274,6 @@
11591
 #
11592
 # Kpasswd tests
11593
 #
11594
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize.ad_dc
11595
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
11596
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
11597
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
11598
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
11599
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
11600
index 385c118a073..d2d7136608e 100644
11601
--- source4/kdc/db-glue.c
11602
+++ source4/kdc/db-glue.c
11603
@@ -830,6 +830,7 @@ static krb5_error_code samba_kdc_get_entry_principal(
11604
 		const char *samAccountName,
11605
 		enum samba_kdc_ent_type ent_type,
11606
 		unsigned flags,
11607
+		bool is_kadmin_changepw,
11608
 		krb5_const_principal in_princ,
11609
 		krb5_principal *out_princ)
11610
 {
11611
@@ -849,46 +850,52 @@ static krb5_error_code samba_kdc_get_entry_principal(
11612
 	 * fixed UPPER case realm, but the as-sent username
11613
 	 */
11614
 
11615
-	if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) {
11616
-		/*
11617
-		 * When requested to do so, ensure that the
11618
-		 * both realm values in the principal are set
11619
-		 * to the upper case, canonical realm
11620
-		 */
11621
-		code = smb_krb5_make_principal(context,
11622
-					       out_princ,
11623
-					       lpcfg_realm(lp_ctx),
11624
-					       "krbtgt",
11625
-					       lpcfg_realm(lp_ctx),
11626
-					       NULL);
11627
-		if (code != 0) {
11628
-			return code;
11629
-		}
11630
-		smb_krb5_principal_set_type(context,
11631
-					    *out_princ,
11632
-					    KRB5_NT_SRV_INST);
11633
+	/*
11634
+	 * We need to ensure that the kadmin/changepw principal isn't able to
11635
+	 * issue krbtgt tickets, even if canonicalization is turned on.
11636
+	 */
11637
+	if (!is_kadmin_changepw) {
11638
+		if (ent_type == SAMBA_KDC_ENT_TYPE_KRBTGT && canon) {
11639
+			/*
11640
+			 * When requested to do so, ensure that the
11641
+			 * both realm values in the principal are set
11642
+			 * to the upper case, canonical realm
11643
+			 */
11644
+			code = smb_krb5_make_principal(context,
11645
+						       out_princ,
11646
+						       lpcfg_realm(lp_ctx),
11647
+						       "krbtgt",
11648
+						       lpcfg_realm(lp_ctx),
11649
+						       NULL);
11650
+			if (code != 0) {
11651
+				return code;
11652
+			}
11653
+			smb_krb5_principal_set_type(context,
11654
+						    *out_princ,
11655
+						    KRB5_NT_SRV_INST);
11656
 
11657
-		return 0;
11658
-	}
11659
+			return 0;
11660
+		}
11661
 
11662
-	if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) ||
11663
-	    (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) {
11664
-		/*
11665
-		 * SDB_F_CANON maps from the canonicalize flag in the
11666
-		 * packet, and has a different meaning between AS-REQ
11667
-		 * and TGS-REQ.  We only change the principal in the
11668
-		 * AS-REQ case.
11669
-		 *
11670
-		 * The SDB_F_FORCE_CANON if for new MIT KDC code that
11671
-		 * wants the canonical name in all lookups, and takes
11672
-		 * care to canonicalize only when appropriate.
11673
-		 */
11674
-		code = smb_krb5_make_principal(context,
11675
-					      out_princ,
11676
-					      lpcfg_realm(lp_ctx),
11677
-					      samAccountName,
11678
-					      NULL);
11679
-		return code;
11680
+		if ((canon && flags & (SDB_F_FORCE_CANON|SDB_F_FOR_AS_REQ)) ||
11681
+		    (ent_type == SAMBA_KDC_ENT_TYPE_ANY && in_princ == NULL)) {
11682
+			/*
11683
+			 * SDB_F_CANON maps from the canonicalize flag in the
11684
+			 * packet, and has a different meaning between AS-REQ
11685
+			 * and TGS-REQ.  We only change the principal in the
11686
+			 * AS-REQ case.
11687
+			 *
11688
+			 * The SDB_F_FORCE_CANON if for new MIT KDC code that
11689
+			 * wants the canonical name in all lookups, and takes
11690
+			 * care to canonicalize only when appropriate.
11691
+			 */
11692
+			code = smb_krb5_make_principal(context,
11693
+						      out_princ,
11694
+						      lpcfg_realm(lp_ctx),
11695
+						      samAccountName,
11696
+						      NULL);
11697
+			return code;
11698
+		}
11699
 	}
11700
 
11701
 	/*
11702
@@ -1194,6 +1201,7 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
11703
 					    samAccountName,
11704
 					    ent_type,
11705
 					    flags,
11706
+					    entry_ex->entry.flags.change_pw,
11707
 					    principal,
11708
 					    &entry_ex->entry.principal);
11709
 	if (ret != 0) {
11710
-- 
11711
2.25.1
11712
11713
11714
From 531e7b596d35785bee61f3b4289e38ece1530f94 Mon Sep 17 00:00:00 2001
11715
From: Joseph Sutton <josephsutton@catalyst.net.nz>
11716
Date: Tue, 24 May 2022 17:53:49 +1200
11717
Subject: [PATCH 85/99] CVE-2022-2031 s4:kdc: Limit kpasswd ticket lifetime to
11718
 two minutes or less
11719
11720
This matches the behaviour of Windows.
11721
11722
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11723
11724
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11725
Reviewed-by: Andreas Schneider <asn@samba.org>
11726
11727
[jsutton@samba.org Adapted entry to entry_ex->entry; included
11728
 samba_kdc.h header file]
11729
11730
[jsutton@samba.org Fixed conflicts]
11731
---
11732
 selftest/knownfail_heimdal_kdc             | 1 -
11733
 selftest/knownfail_mit_kdc                 | 1 -
11734
 source4/kdc/db-glue.c                      | 5 +++++
11735
 source4/kdc/mit-kdb/kdb_samba_principals.c | 2 +-
11736
 source4/kdc/samba_kdc.h                    | 2 ++
11737
 5 files changed, 8 insertions(+), 3 deletions(-)
11738
11739
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
11740
index 49ab29f115d..387ccea3ba7 100644
11741
--- selftest/knownfail_heimdal_kdc
11742
+++ selftest/knownfail_heimdal_kdc
11743
@@ -275,7 +275,6 @@
11744
 # Kpasswd tests
11745
 #
11746
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
11747
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
11748
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
11749
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
11750
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
11751
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
11752
index 46b0f1fa9ed..c2a31b4a140 100644
11753
--- selftest/knownfail_mit_kdc
11754
+++ selftest/knownfail_mit_kdc
11755
@@ -580,7 +580,6 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
11756
 #
11757
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
11758
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
11759
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_lifetime.ad_dc
11760
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
11761
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
11762
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
11763
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
11764
index d2d7136608e..073ec83c8cf 100644
11765
--- source4/kdc/db-glue.c
11766
+++ source4/kdc/db-glue.c
11767
@@ -1226,6 +1226,11 @@ static krb5_error_code samba_kdc_message2entry(krb5_context context,
11768
 					        kdc_db_ctx->policy.usr_tkt_lifetime);
11769
 	}
11770
 
11771
+	if (entry_ex->entry.flags.change_pw) {
11772
+		/* Limit lifetime of kpasswd tickets to two minutes or less. */
11773
+		*entry_ex->entry.max_life = MIN(*entry_ex->entry.max_life, CHANGEPW_LIFETIME);
11774
+	}
11775
+
11776
 	entry_ex->entry.max_renew = malloc(sizeof(*entry_ex->entry.max_life));
11777
 	if (entry_ex->entry.max_renew == NULL) {
11778
 		ret = ENOMEM;
11779
diff --git source4/kdc/mit-kdb/kdb_samba_principals.c source4/kdc/mit-kdb/kdb_samba_principals.c
11780
index cc67c2392be..2059ffa855e 100644
11781
--- source4/kdc/mit-kdb/kdb_samba_principals.c
11782
+++ source4/kdc/mit-kdb/kdb_samba_principals.c
11783
@@ -27,11 +27,11 @@
11784
 #include <profile.h>
11785
 #include <kdb.h>
11786
 
11787
+#include "kdc/samba_kdc.h"
11788
 #include "kdc/mit_samba.h"
11789
 #include "kdb_samba.h"
11790
 
11791
 #define ADMIN_LIFETIME 60*60*3 /* 3 hours */
11792
-#define CHANGEPW_LIFETIME 60*5 /* 5 minutes */
11793
 
11794
 krb5_error_code ks_get_principal(krb5_context context,
11795
 				 krb5_const_principal principal,
11796
diff --git source4/kdc/samba_kdc.h source4/kdc/samba_kdc.h
11797
index e228a82ce6a..8010d7c35ed 100644
11798
--- source4/kdc/samba_kdc.h
11799
+++ source4/kdc/samba_kdc.h
11800
@@ -62,4 +62,6 @@ struct samba_kdc_entry {
11801
 
11802
 extern struct hdb_method hdb_samba4_interface;
11803
 
11804
+#define CHANGEPW_LIFETIME 60*2 /* 2 minutes */
11805
+
11806
 #endif /* _SAMBA_KDC_H_ */
11807
-- 
11808
2.25.1
11809
11810
11811
From abdac4241dd08dd90a08db877edd799f3833c2b4 Mon Sep 17 00:00:00 2001
11812
From: Joseph Sutton <josephsutton@catalyst.net.nz>
11813
Date: Mon, 30 May 2022 19:18:17 +1200
11814
Subject: [PATCH 86/99] CVE-2022-2031 s4:kdc: Reject tickets during the last
11815
 two minutes of their life
11816
11817
For Heimdal, this now matches the behaviour of Windows. The object of
11818
this requirement is to ensure we don't allow kpasswd tickets, not having
11819
a lifetime of more than two minutes, to be passed off as TGTs.
11820
11821
An existing requirement for TGTs to contain a REQUESTER_SID PAC buffer
11822
suffices to prevent kpasswd ticket misuse, so this is just an additional
11823
precaution on top.
11824
11825
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11826
11827
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11828
Reviewed-by: Andreas Schneider <asn@samba.org>
11829
11830
[jsutton@samba.org As we don't have access to the ticket or the request
11831
 in the plugin, rewrote check directly in Heimdal KDC]
11832
---
11833
 selftest/knownfail_heimdal_kdc |  1 -
11834
 source4/heimdal/kdc/krb5tgs.c  | 19 ++++++++++++++++++-
11835
 2 files changed, 18 insertions(+), 2 deletions(-)
11836
11837
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
11838
index 387ccea3ba7..afb9bcf1209 100644
11839
--- selftest/knownfail_heimdal_kdc
11840
+++ selftest/knownfail_heimdal_kdc
11841
@@ -275,7 +275,6 @@
11842
 # Kpasswd tests
11843
 #
11844
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
11845
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
11846
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
11847
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
11848
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
11849
diff --git source4/heimdal/kdc/krb5tgs.c source4/heimdal/kdc/krb5tgs.c
11850
index 38dba8493ae..15be136496f 100644
11851
--- source4/heimdal/kdc/krb5tgs.c
11852
+++ source4/heimdal/kdc/krb5tgs.c
11853
@@ -33,6 +33,9 @@
11854
 
11855
 #include "kdc_locl.h"
11856
 
11857
+/* Awful hack to get access to 'struct samba_kdc_entry'. */
11858
+#include "../../kdc/samba_kdc.h"
11859
+
11860
 /*
11861
  * return the realm of a krbtgt-ticket or NULL
11862
  */
11863
@@ -130,6 +133,7 @@ check_PAC(krb5_context context,
11864
 static krb5_error_code
11865
 check_tgs_flags(krb5_context context,
11866
 		krb5_kdc_configuration *config,
11867
+		const hdb_entry_ex *krbtgt_in,
11868
 		KDC_REQ_BODY *b, const EncTicketPart *tgt, EncTicketPart *et)
11869
 {
11870
     KDCOptions f = b->kdc_options;
11871
@@ -244,6 +248,17 @@ check_tgs_flags(krb5_context context,
11872
 	    et->endtime = min(*et->renew_till, et->endtime);
11873
     }
11874
 
11875
+    if (tgt->endtime - kdc_time <= CHANGEPW_LIFETIME) {
11876
+	/* Check that the ticket has not arrived across a trust. */
11877
+	const struct samba_kdc_entry *skdc_entry = krbtgt_in->ctx;
11878
+	if (!skdc_entry->is_trust) {
11879
+	    /* This may be a kpasswd ticket rather than a TGT, so don't accept it. */
11880
+	    kdc_log(context, config, 0,
11881
+		    "Ticket is not a ticket-granting ticket");
11882
+	    return KRB5KRB_AP_ERR_TKT_EXPIRED;
11883
+	}
11884
+    }
11885
+
11886
 #if 0
11887
     /* checks for excess flags */
11888
     if(f.request_anonymous && !config->allow_anonymous){
11889
@@ -510,6 +525,7 @@ tgs_make_reply(krb5_context context,
11890
 	       hdb_entry_ex *client,
11891
 	       krb5_principal client_principal,
11892
                const char *tgt_realm,
11893
+	       const hdb_entry_ex *krbtgt_in,
11894
 	       hdb_entry_ex *krbtgt,
11895
 	       krb5_pac mspac,
11896
 	       uint16_t rodc_id,
11897
@@ -538,7 +554,7 @@ tgs_make_reply(krb5_context context,
11898
     ALLOC(et.starttime);
11899
     *et.starttime = kdc_time;
11900
 
11901
-    ret = check_tgs_flags(context, config, b, tgt, &et);
11902
+    ret = check_tgs_flags(context, config, krbtgt_in, b, tgt, &et);
11903
     if(ret)
11904
 	goto out;
11905
 
11906
@@ -2129,6 +2145,7 @@ server_lookup:
11907
 			 client,
11908
 			 cp,
11909
 			 tgt_realm,
11910
+			 krbtgt,
11911
 			 krbtgt_out,
11912
 			 mspac,
11913
 			 rodc_id,
11914
-- 
11915
2.25.1
11916
11917
11918
From 389851bcf399f9511e2cb797350c37ce91aa5849 Mon Sep 17 00:00:00 2001
11919
From: Joseph Sutton <josephsutton@catalyst.net.nz>
11920
Date: Tue, 14 Jun 2022 15:23:55 +1200
11921
Subject: [PATCH 87/99] CVE-2022-2031 tests/krb5: Test truncated forms of
11922
 server principals
11923
11924
We should not be able to use krb@REALM instead of krbtgt@REALM.
11925
11926
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
11927
11928
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
11929
Reviewed-by: Andreas Schneider <asn@samba.org>
11930
11931
[jsutton@samba.org Fixed conflicts due to having older version of
11932
 _run_as_req_enc_timestamp()]
11933
---
11934
 python/samba/tests/krb5/as_req_tests.py | 40 ++++++++++++++++++++++---
11935
 selftest/knownfail_heimdal_kdc          |  4 +++
11936
 selftest/knownfail_mit_kdc              |  4 +++
11937
 3 files changed, 44 insertions(+), 4 deletions(-)
11938
11939
diff --git python/samba/tests/krb5/as_req_tests.py python/samba/tests/krb5/as_req_tests.py
11940
index 315720f85d6..054a49b64aa 100755
11941
--- python/samba/tests/krb5/as_req_tests.py
11942
+++ python/samba/tests/krb5/as_req_tests.py
11943
@@ -27,6 +27,7 @@ from samba.tests.krb5.kdc_base_test import KDCBaseTest
11944
 import samba.tests.krb5.kcrypto as kcrypto
11945
 import samba.tests.krb5.rfc4120_pyasn1 as krb5_asn1
11946
 from samba.tests.krb5.rfc4120_constants import (
11947
+    KDC_ERR_S_PRINCIPAL_UNKNOWN,
11948
     KDC_ERR_ETYPE_NOSUPP,
11949
     KDC_ERR_PREAUTH_REQUIRED,
11950
     KU_PA_ENC_TIMESTAMP,
11951
@@ -40,7 +41,8 @@ global_hexdump = False
11952
 
11953
 
11954
 class AsReqBaseTest(KDCBaseTest):
11955
-    def _run_as_req_enc_timestamp(self, client_creds):
11956
+    def _run_as_req_enc_timestamp(self, client_creds, sname=None,
11957
+                                  expected_error=None):
11958
         client_account = client_creds.get_username()
11959
         client_as_etypes = self.get_default_enctypes()
11960
         client_kvno = client_creds.get_kvno()
11961
@@ -50,8 +52,9 @@ class AsReqBaseTest(KDCBaseTest):
11962
 
11963
         cname = self.PrincipalName_create(name_type=NT_PRINCIPAL,
11964
                                           names=[client_account])
11965
-        sname = self.PrincipalName_create(name_type=NT_SRV_INST,
11966
-                                          names=[krbtgt_account, realm])
11967
+        if sname is None:
11968
+            sname = self.PrincipalName_create(name_type=NT_SRV_INST,
11969
+                                              names=[krbtgt_account, realm])
11970
 
11971
         expected_crealm = realm
11972
         expected_cname = cname
11973
@@ -63,7 +66,10 @@ class AsReqBaseTest(KDCBaseTest):
11974
 
11975
         initial_etypes = client_as_etypes
11976
         initial_kdc_options = krb5_asn1.KDCOptions('forwardable')
11977
-        initial_error_mode = KDC_ERR_PREAUTH_REQUIRED
11978
+        if expected_error is not None:
11979
+            initial_error_mode = expected_error
11980
+        else:
11981
+            initial_error_mode = KDC_ERR_PREAUTH_REQUIRED
11982
 
11983
         rep, kdc_exchange_dict = self._test_as_exchange(cname,
11984
                                                         realm,
11985
@@ -80,6 +86,10 @@ class AsReqBaseTest(KDCBaseTest):
11986
                                                         None,
11987
                                                         initial_kdc_options,
11988
                                                         pac_request=True)
11989
+
11990
+        if expected_error is not None:
11991
+            return None
11992
+
11993
         etype_info2 = kdc_exchange_dict['preauth_etype_info2']
11994
         self.assertIsNotNone(etype_info2)
11995
 
11996
@@ -209,6 +219,28 @@ class AsReqKerberosTests(AsReqBaseTest):
11997
         client_creds = self.get_mach_creds()
11998
         self._run_as_req_enc_timestamp(client_creds)
11999
 
12000
+    # Ensure we can't use truncated well-known principals such as krb@REALM
12001
+    # instead of krbtgt@REALM.
12002
+    def test_krbtgt_wrong_principal(self):
12003
+        client_creds = self.get_client_creds()
12004
+
12005
+        krbtgt_creds = self.get_krbtgt_creds()
12006
+
12007
+        krbtgt_account = krbtgt_creds.get_username()
12008
+        realm = krbtgt_creds.get_realm()
12009
+
12010
+        # Truncate the name of the krbtgt principal.
12011
+        krbtgt_account = krbtgt_account[:3]
12012
+
12013
+        wrong_krbtgt_princ = self.PrincipalName_create(
12014
+            name_type=NT_SRV_INST,
12015
+            names=[krbtgt_account, realm])
12016
+
12017
+        self._run_as_req_enc_timestamp(
12018
+            client_creds,
12019
+            sname=wrong_krbtgt_princ,
12020
+            expected_error=KDC_ERR_S_PRINCIPAL_UNKNOWN)
12021
+
12022
 
12023
 if __name__ == "__main__":
12024
     global_asn1_print = False
12025
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
12026
index afb9bcf1209..dbfff5784e6 100644
12027
--- selftest/knownfail_heimdal_kdc
12028
+++ selftest/knownfail_heimdal_kdc
12029
@@ -278,3 +278,7 @@
12030
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
12031
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
12032
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
12033
+#
12034
+# AS-REQ tests
12035
+#
12036
+^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\(
12037
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
12038
index c2a31b4a140..0f90ea10299 100644
12039
--- selftest/knownfail_mit_kdc
12040
+++ selftest/knownfail_mit_kdc
12041
@@ -583,3 +583,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
12042
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
12043
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
12044
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
12045
+#
12046
+# AS-REQ tests
12047
+#
12048
+^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\(
12049
-- 
12050
2.25.1
12051
12052
12053
From d40593be83144713cfc43e4eb1c7bc2d925a0da0 Mon Sep 17 00:00:00 2001
12054
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12055
Date: Wed, 25 May 2022 20:00:55 +1200
12056
Subject: [PATCH 88/99] CVE-2022-2031 s4:kdc: Don't use strncmp to compare
12057
 principal components
12058
12059
We would only compare the first 'n' characters, where 'n' is the length
12060
of the principal component string, so 'k@REALM' would erroneously be
12061
considered equal to 'krbtgt@REALM'.
12062
12063
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
12064
12065
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12066
Reviewed-by: Andreas Schneider <asn@samba.org>
12067
---
12068
 selftest/knownfail_heimdal_kdc |  4 ----
12069
 selftest/knownfail_mit_kdc     |  4 ----
12070
 source4/kdc/db-glue.c          | 27 ++++++++++++++++++++++-----
12071
 3 files changed, 22 insertions(+), 13 deletions(-)
12072
12073
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
12074
index dbfff5784e6..afb9bcf1209 100644
12075
--- selftest/knownfail_heimdal_kdc
12076
+++ selftest/knownfail_heimdal_kdc
12077
@@ -278,7 +278,3 @@
12078
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
12079
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
12080
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
12081
-#
12082
-# AS-REQ tests
12083
-#
12084
-^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\(
12085
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
12086
index 0f90ea10299..c2a31b4a140 100644
12087
--- selftest/knownfail_mit_kdc
12088
+++ selftest/knownfail_mit_kdc
12089
@@ -583,7 +583,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
12090
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
12091
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
12092
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
12093
-#
12094
-# AS-REQ tests
12095
-#
12096
-^samba.tests.krb5.as_req_tests.samba.tests.krb5.as_req_tests.AsReqKerberosTests.test_krbtgt_wrong_principal\(
12097
diff --git source4/kdc/db-glue.c source4/kdc/db-glue.c
12098
index 073ec83c8cf..cfa2097acbd 100644
12099
--- source4/kdc/db-glue.c
12100
+++ source4/kdc/db-glue.c
12101
@@ -769,15 +769,19 @@ static int principal_comp_strcmp_int(krb5_context context,
12102
 				     bool do_strcasecmp)
12103
 {
12104
 	const char *p;
12105
-	size_t len;
12106
 
12107
 #if defined(HAVE_KRB5_PRINCIPAL_GET_COMP_STRING)
12108
 	p = krb5_principal_get_comp_string(context, principal, component);
12109
 	if (p == NULL) {
12110
 		return -1;
12111
 	}
12112
-	len = strlen(p);
12113
+	if (do_strcasecmp) {
12114
+		return strcasecmp(p, string);
12115
+	} else {
12116
+		return strcmp(p, string);
12117
+	}
12118
 #else
12119
+	size_t len;
12120
 	krb5_data *d;
12121
 	if (component >= krb5_princ_size(context, principal)) {
12122
 		return -1;
12123
@@ -789,13 +793,26 @@ static int principal_comp_strcmp_int(krb5_context context,
12124
 	}
12125
 
12126
 	p = d->data;
12127
-	len = d->length;
12128
-#endif
12129
+
12130
+	len = strlen(string);
12131
+
12132
+	/*
12133
+	 * We explicitly return -1 or 1. Subtracting of the two lengths might
12134
+	 * give the wrong result if the result overflows or loses data when
12135
+	 * narrowed to int.
12136
+	 */
12137
+	if (d->length < len) {
12138
+		return -1;
12139
+	} else if (d->length > len) {
12140
+		return 1;
12141
+	}
12142
+
12143
 	if (do_strcasecmp) {
12144
 		return strncasecmp(p, string, len);
12145
 	} else {
12146
-		return strncmp(p, string, len);
12147
+		return memcmp(p, string, len);
12148
 	}
12149
+#endif
12150
 }
12151
 
12152
 static int principal_comp_strcasecmp(krb5_context context,
12153
-- 
12154
2.25.1
12155
12156
12157
From 42ba919c06c24c42ef123304de0c2ca8c689591a Mon Sep 17 00:00:00 2001
12158
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12159
Date: Thu, 26 May 2022 16:36:30 +1200
12160
Subject: [PATCH 89/99] CVE-2022-32744 s4:kdc: Rename keytab_name ->
12161
 kpasswd_keytab_name
12162
12163
This makes explicitly clear the purpose of this keytab.
12164
12165
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
12166
12167
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12168
Reviewed-by: Andreas Schneider <asn@samba.org>
12169
12170
[jsutton@samba.org Fixed conflicts due to lacking HDBGET support]
12171
---
12172
 source4/kdc/kdc-heimdal.c     | 4 ++--
12173
 source4/kdc/kdc-server.h      | 2 +-
12174
 source4/kdc/kdc-service-mit.c | 4 ++--
12175
 source4/kdc/kpasswd-service.c | 2 +-
12176
 4 files changed, 6 insertions(+), 6 deletions(-)
12177
12178
diff --git source4/kdc/kdc-heimdal.c source4/kdc/kdc-heimdal.c
12179
index ba74df4f2ec..a4c845b62f8 100644
12180
--- source4/kdc/kdc-heimdal.c
12181
+++ source4/kdc/kdc-heimdal.c
12182
@@ -444,8 +444,8 @@ static void kdc_post_fork(struct task_server *task, struct process_details *pd)
12183
 		return;
12184
 	}
12185
 
12186
-	kdc->keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx);
12187
-	if (kdc->keytab_name == NULL) {
12188
+	kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "HDB:samba4&%p", kdc->base_ctx);
12189
+	if (kdc->kpasswd_keytab_name == NULL) {
12190
 		task_server_terminate(task,
12191
 				      "kdc: Failed to set keytab name",
12192
 				      true);
12193
diff --git source4/kdc/kdc-server.h source4/kdc/kdc-server.h
12194
index fd883c2e4b4..89b30f122f5 100644
12195
--- source4/kdc/kdc-server.h
12196
+++ source4/kdc/kdc-server.h
12197
@@ -40,7 +40,7 @@ struct kdc_server {
12198
 	struct ldb_context *samdb;
12199
 	bool am_rodc;
12200
 	uint32_t proxy_timeout;
12201
-	const char *keytab_name;
12202
+	const char *kpasswd_keytab_name;
12203
 	void *private_data;
12204
 };
12205
 
12206
diff --git source4/kdc/kdc-service-mit.c source4/kdc/kdc-service-mit.c
12207
index 5d4180aa7cc..22663b6ecc8 100644
12208
--- source4/kdc/kdc-service-mit.c
12209
+++ source4/kdc/kdc-service-mit.c
12210
@@ -291,8 +291,8 @@ NTSTATUS mitkdc_task_init(struct task_server *task)
12211
 		return NT_STATUS_INTERNAL_ERROR;
12212
 	}
12213
 
12214
-	kdc->keytab_name = talloc_asprintf(kdc, "KDB:");
12215
-	if (kdc->keytab_name == NULL) {
12216
+	kdc->kpasswd_keytab_name = talloc_asprintf(kdc, "KDB:");
12217
+	if (kdc->kpasswd_keytab_name == NULL) {
12218
 		task_server_terminate(task,
12219
 				      "KDC: Out of memory",
12220
 				      true);
12221
diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c
12222
index b4706de1ad7..0d2acd8d9e8 100644
12223
--- source4/kdc/kpasswd-service.c
12224
+++ source4/kdc/kpasswd-service.c
12225
@@ -167,7 +167,7 @@ kdc_code kpasswd_process(struct kdc_server *kdc,
12226
 
12227
 	rv = cli_credentials_set_keytab_name(server_credentials,
12228
 					     kdc->task->lp_ctx,
12229
-					     kdc->keytab_name,
12230
+					     kdc->kpasswd_keytab_name,
12231
 					     CRED_SPECIFIED);
12232
 	if (rv != 0) {
12233
 		DBG_ERR("Failed to set credentials keytab name\n");
12234
-- 
12235
2.25.1
12236
12237
12238
From 997f50c66471071efb8e02d8efbe4bf5d932e7ee Mon Sep 17 00:00:00 2001
12239
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12240
Date: Wed, 8 Jun 2022 13:53:29 +1200
12241
Subject: [PATCH 90/99] s4:kdc: Remove kadmin mode from HDB plugin
12242
12243
It appears we no longer require it.
12244
12245
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12246
Reviewed-by: Andreas Schneider <asn@samba.org>
12247
---
12248
 source4/kdc/hdb-samba4-plugin.c | 35 +++++++--------------------------
12249
 1 file changed, 7 insertions(+), 28 deletions(-)
12250
12251
diff --git source4/kdc/hdb-samba4-plugin.c source4/kdc/hdb-samba4-plugin.c
12252
index 6f76124995d..4b90a766f76 100644
12253
--- source4/kdc/hdb-samba4-plugin.c
12254
+++ source4/kdc/hdb-samba4-plugin.c
12255
@@ -21,40 +21,20 @@
12256
 
12257
 #include "includes.h"
12258
 #include "kdc/kdc-glue.h"
12259
-#include "kdc/db-glue.h"
12260
-#include "lib/util/samba_util.h"
12261
 #include "lib/param/param.h"
12262
-#include "source4/lib/events/events.h"
12263
 
12264
 static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db, const char *arg)
12265
 {
12266
 	NTSTATUS nt_status;
12267
-	void *ptr;
12268
-	struct samba_kdc_base_context *base_ctx;
12269
-	
12270
-	if (sscanf(arg, "&%p", &ptr) == 1) {
12271
-		base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context);
12272
-	} else if (arg[0] == '\0' || file_exist(arg)) {
12273
-		/* This mode for use in kadmin, rather than in Samba */
12274
-		
12275
-		setup_logging("hdb_samba4", DEBUG_DEFAULT_STDERR);
12276
-
12277
-		base_ctx = talloc_zero(NULL, struct samba_kdc_base_context);
12278
-		if (!base_ctx) {
12279
-			return ENOMEM;
12280
-		}
12281
-
12282
-		base_ctx->ev_ctx = s4_event_context_init(base_ctx);
12283
-		base_ctx->lp_ctx = loadparm_init_global(false);
12284
-		if (arg[0]) {
12285
-			lpcfg_load(base_ctx->lp_ctx, arg);
12286
-		} else {
12287
-			lpcfg_load_default(base_ctx->lp_ctx);
12288
-		}
12289
-	} else {
12290
+	void *ptr = NULL;
12291
+	struct samba_kdc_base_context *base_ctx = NULL;
12292
+
12293
+	if (sscanf(arg, "&%p", &ptr) != 1) {
12294
 		return EINVAL;
12295
 	}
12296
 
12297
+	base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context);
12298
+
12299
 	/* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */
12300
 	nt_status = hdb_samba4_create_kdc(base_ctx, context, db);
12301
 
12302
@@ -90,8 +70,7 @@ static void hdb_samba4_fini(void *ctx)
12303
 
12304
 /* Only used in the hdb-backed keytab code
12305
  * for a keytab of 'samba4&<address>' or samba4, to find
12306
- * kpasswd's key in the main DB, and to
12307
- * copy all the keys into a file (libnet_keytab_export)
12308
+ * kpasswd's key in the main DB
12309
  *
12310
  * The <address> is the string form of a pointer to a talloced struct hdb_samba_context
12311
  */
12312
-- 
12313
2.25.1
12314
12315
12316
From c0c4b7a4bd229bd36d586faec6249baaba8e7adc Mon Sep 17 00:00:00 2001
12317
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12318
Date: Thu, 26 May 2022 16:39:20 +1200
12319
Subject: [PATCH 91/99] CVE-2022-32744 s4:kdc: Modify HDB plugin to only look
12320
 up kpasswd principal
12321
12322
This plugin is now only used by the kpasswd service. Thus, ensuring we
12323
only look up the kadmin/changepw principal means we can't be fooled into
12324
accepting tickets for other service principals. We make sure not to
12325
specify a specific kvno, to ensure that we do not accept RODC-issued
12326
tickets.
12327
12328
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
12329
12330
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12331
Reviewed-by: Andreas Schneider <asn@samba.org>
12332
12333
[jsutton@samba.org Fixed knownfail conflicts]
12334
12335
[jsutton@samba.org Renamed entry to entry_ex; fixed knownfail conflicts;
12336
 retained knownfail for test_kpasswd_from_rodc which now causes the KDC
12337
 to panic]
12338
---
12339
 selftest/knownfail_heimdal_kdc  |  3 --
12340
 source4/kdc/hdb-samba4-plugin.c |  2 +-
12341
 source4/kdc/hdb-samba4.c        | 66 +++++++++++++++++++++++++++++++++
12342
 source4/kdc/kdc-glue.h          |  3 ++
12343
 4 files changed, 70 insertions(+), 4 deletions(-)
12344
12345
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
12346
index afb9bcf1209..0d93253f999 100644
12347
--- selftest/knownfail_heimdal_kdc
12348
+++ selftest/knownfail_heimdal_kdc
12349
@@ -275,6 +275,3 @@
12350
 # Kpasswd tests
12351
 #
12352
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
12353
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key.ad_dc
12354
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
12355
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
12356
diff --git source4/kdc/hdb-samba4-plugin.c source4/kdc/hdb-samba4-plugin.c
12357
index 4b90a766f76..dba25e825de 100644
12358
--- source4/kdc/hdb-samba4-plugin.c
12359
+++ source4/kdc/hdb-samba4-plugin.c
12360
@@ -36,7 +36,7 @@ static krb5_error_code hdb_samba4_create(krb5_context context, struct HDB **db,
12361
 	base_ctx = talloc_get_type_abort(ptr, struct samba_kdc_base_context);
12362
 
12363
 	/* The global kdc_mem_ctx and kdc_lp_ctx, Disgusting, ugly hack, but it means one less private hook */
12364
-	nt_status = hdb_samba4_create_kdc(base_ctx, context, db);
12365
+	nt_status = hdb_samba4_kpasswd_create_kdc(base_ctx, context, db);
12366
 
12367
 	if (NT_STATUS_IS_OK(nt_status)) {
12368
 		return 0;
12369
diff --git source4/kdc/hdb-samba4.c source4/kdc/hdb-samba4.c
12370
index 43e836f8360..a8aae50b5b0 100644
12371
--- source4/kdc/hdb-samba4.c
12372
+++ source4/kdc/hdb-samba4.c
12373
@@ -136,6 +136,47 @@ static krb5_error_code hdb_samba4_fetch_kvno(krb5_context context, HDB *db,
12374
 	return code;
12375
 }
12376
 
12377
+static krb5_error_code hdb_samba4_kpasswd_fetch_kvno(krb5_context context, HDB *db,
12378
+						     krb5_const_principal _principal,
12379
+						     unsigned flags,
12380
+						     krb5_kvno _kvno,
12381
+						     hdb_entry_ex *entry_ex)
12382
+{
12383
+	struct samba_kdc_db_context *kdc_db_ctx = NULL;
12384
+	krb5_error_code ret;
12385
+	krb5_principal kpasswd_principal = NULL;
12386
+
12387
+	kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
12388
+					   struct samba_kdc_db_context);
12389
+
12390
+	ret = smb_krb5_make_principal(context, &kpasswd_principal,
12391
+				      lpcfg_realm(kdc_db_ctx->lp_ctx),
12392
+				      "kadmin", "changepw",
12393
+				      NULL);
12394
+	if (ret) {
12395
+		return ret;
12396
+	}
12397
+	smb_krb5_principal_set_type(context, kpasswd_principal, KRB5_NT_SRV_INST);
12398
+
12399
+	/*
12400
+	 * For the kpasswd service, always ensure we get the latest kvno. This
12401
+	 * also means we (correctly) refuse RODC-issued tickets.
12402
+	 */
12403
+	flags &= ~HDB_F_KVNO_SPECIFIED;
12404
+
12405
+	/* Don't bother looking up a client or krbtgt. */
12406
+	flags &= ~(SDB_F_GET_CLIENT|SDB_F_GET_KRBTGT);
12407
+
12408
+	ret = hdb_samba4_fetch_kvno(context, db,
12409
+				    kpasswd_principal,
12410
+				    flags,
12411
+				    0,
12412
+				    entry_ex);
12413
+
12414
+	krb5_free_principal(context, kpasswd_principal);
12415
+	return ret;
12416
+}
12417
+
12418
 static krb5_error_code hdb_samba4_firstkey(krb5_context context, HDB *db, unsigned flags,
12419
 					hdb_entry_ex *entry)
12420
 {
12421
@@ -194,6 +235,14 @@ static krb5_error_code hdb_samba4_nextkey(krb5_context context, HDB *db, unsigne
12422
 	return ret;
12423
 }
12424
 
12425
+static krb5_error_code hdb_samba4_nextkey_panic(krb5_context context, HDB *db,
12426
+						unsigned flags,
12427
+						hdb_entry_ex *entry)
12428
+{
12429
+	DBG_ERR("Attempt to iterate kpasswd keytab => PANIC\n");
12430
+	smb_panic("hdb_samba4_nextkey_panic: Attempt to iterate kpasswd keytab");
12431
+}
12432
+
12433
 static krb5_error_code hdb_samba4_destroy(krb5_context context, HDB *db)
12434
 {
12435
 	talloc_free(db);
12436
@@ -522,3 +571,20 @@ NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
12437
 
12438
 	return NT_STATUS_OK;
12439
 }
12440
+
12441
+NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx,
12442
+				       krb5_context context, struct HDB **db)
12443
+{
12444
+	NTSTATUS nt_status;
12445
+
12446
+	nt_status = hdb_samba4_create_kdc(base_ctx, context, db);
12447
+	if (!NT_STATUS_IS_OK(nt_status)) {
12448
+		return nt_status;
12449
+	}
12450
+
12451
+	(*db)->hdb_fetch_kvno = hdb_samba4_kpasswd_fetch_kvno;
12452
+	(*db)->hdb_firstkey = hdb_samba4_nextkey_panic;
12453
+	(*db)->hdb_nextkey = hdb_samba4_nextkey_panic;
12454
+
12455
+	return NT_STATUS_OK;
12456
+}
12457
diff --git source4/kdc/kdc-glue.h source4/kdc/kdc-glue.h
12458
index c083b8c6429..ff8684e1666 100644
12459
--- source4/kdc/kdc-glue.h
12460
+++ source4/kdc/kdc-glue.h
12461
@@ -45,6 +45,9 @@ kdc_code kpasswdd_process(struct kdc_server *kdc,
12462
 NTSTATUS hdb_samba4_create_kdc(struct samba_kdc_base_context *base_ctx,
12463
 			       krb5_context context, struct HDB **db);
12464
 
12465
+NTSTATUS hdb_samba4_kpasswd_create_kdc(struct samba_kdc_base_context *base_ctx,
12466
+				       krb5_context context, struct HDB **db);
12467
+
12468
 /* from kdc-glue.c */
12469
 int kdc_check_pac(krb5_context krb5_context,
12470
 		  DATA_BLOB server_sig,
12471
-- 
12472
2.25.1
12473
12474
12475
From 340181bc1100fa31c63af88214a3d8328b944fe9 Mon Sep 17 00:00:00 2001
12476
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12477
Date: Mon, 30 May 2022 19:16:02 +1200
12478
Subject: [PATCH 92/99] CVE-2022-32744 s4:kpasswd: Ensure we pass the kpasswd
12479
 server principal into krb5_rd_req_ctx()
12480
12481
To ensure that, when decrypting the kpasswd ticket, we look up the
12482
correct principal and don't trust the sname from the ticket, we should
12483
pass the principal name of the kpasswd service into krb5_rd_req_ctx().
12484
However, gensec_krb5_update_internal() will pass in NULL unless the
12485
principal in our credentials is CRED_SPECIFIED.
12486
12487
At present, our principal will be considered obtained as CRED_SMB_CONF
12488
(from the cli_credentials_set_conf() a few lines up), so we explicitly
12489
set the realm again, but this time as CRED_SPECIFIED. Now the value of
12490
server_in_keytab that we provide to smb_krb5_rd_req_decoded() will not
12491
be NULL.
12492
12493
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15074
12494
12495
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12496
Reviewed-by: Andreas Schneider <asn@samba.org>
12497
12498
[jsutton@samba.org Removed knownfail as KDC no longer panics]
12499
---
12500
 selftest/knownfail_heimdal_kdc |  4 ----
12501
 selftest/knownfail_mit_kdc     |  2 --
12502
 source4/kdc/kpasswd-service.c  | 30 ++++++++++++++++++++++++++++++
12503
 3 files changed, 30 insertions(+), 6 deletions(-)
12504
12505
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
12506
index 0d93253f999..424a8b81c38 100644
12507
--- selftest/knownfail_heimdal_kdc
12508
+++ selftest/knownfail_heimdal_kdc
12509
@@ -271,7 +271,3 @@
12510
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
12511
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
12512
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
12513
-#
12514
-# Kpasswd tests
12515
-#
12516
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_from_rodc.ad_dc
12517
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
12518
index c2a31b4a140..0d2f5bab6d2 100644
12519
--- selftest/knownfail_mit_kdc
12520
+++ selftest/knownfail_mit_kdc
12521
@@ -581,5 +581,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
12522
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
12523
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
12524
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
12525
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_server.ad_dc
12526
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_wrong_key_service.ad_dc
12527
diff --git source4/kdc/kpasswd-service.c source4/kdc/kpasswd-service.c
12528
index 0d2acd8d9e8..b6400be0c49 100644
12529
--- source4/kdc/kpasswd-service.c
12530
+++ source4/kdc/kpasswd-service.c
12531
@@ -29,6 +29,7 @@
12532
 #include "kdc/kdc-server.h"
12533
 #include "kdc/kpasswd-service.h"
12534
 #include "kdc/kpasswd-helper.h"
12535
+#include "param/param.h"
12536
 
12537
 #define HEADER_LEN 6
12538
 #ifndef RFC3244_VERSION
12539
@@ -158,6 +159,20 @@ kdc_code kpasswd_process(struct kdc_server *kdc,
12540
 
12541
 	cli_credentials_set_conf(server_credentials, kdc->task->lp_ctx);
12542
 
12543
+	/*
12544
+	 * After calling cli_credentials_set_conf(), explicitly set the realm
12545
+	 * with CRED_SPECIFIED. We need to do this so the result of
12546
+	 * principal_from_credentials() called from the gensec layer is
12547
+	 * CRED_SPECIFIED rather than CRED_SMB_CONF, avoiding a fallback to
12548
+	 * match-by-key (very undesirable in this case).
12549
+	 */
12550
+	ok = cli_credentials_set_realm(server_credentials,
12551
+				       lpcfg_realm(kdc->task->lp_ctx),
12552
+				       CRED_SPECIFIED);
12553
+	if (!ok) {
12554
+		goto done;
12555
+	}
12556
+
12557
 	ok = cli_credentials_set_username(server_credentials,
12558
 					  "kadmin/changepw",
12559
 					  CRED_SPECIFIED);
12560
@@ -165,6 +180,21 @@ kdc_code kpasswd_process(struct kdc_server *kdc,
12561
 		goto done;
12562
 	}
12563
 
12564
+	/* Check that the server principal is indeed CRED_SPECIFIED. */
12565
+	{
12566
+		char *principal = NULL;
12567
+		enum credentials_obtained obtained;
12568
+
12569
+		principal = cli_credentials_get_principal_and_obtained(server_credentials,
12570
+								       tmp_ctx,
12571
+								       &obtained);
12572
+		if (obtained < CRED_SPECIFIED) {
12573
+			goto done;
12574
+		}
12575
+
12576
+		TALLOC_FREE(principal);
12577
+	}
12578
+
12579
 	rv = cli_credentials_set_keytab_name(server_credentials,
12580
 					     kdc->task->lp_ctx,
12581
 					     kdc->kpasswd_keytab_name,
12582
-- 
12583
2.25.1
12584
12585
12586
From 95afbc2da9b541fb8f2eebdcd411f5873d1675ac Mon Sep 17 00:00:00 2001
12587
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12588
Date: Fri, 10 Jun 2022 19:17:11 +1200
12589
Subject: [PATCH 93/99] CVE-2022-2031 tests/krb5: Add test that we cannot
12590
 provide a TGT to kpasswd
12591
12592
The kpasswd service should require a kpasswd service ticket, and
12593
disallow TGTs.
12594
12595
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
12596
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
12597
12598
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12599
Reviewed-by: Andreas Schneider <asn@samba.org>
12600
12601
[jsutton@samba.org Fixed knownfail conflicts]
12602
12603
[jsutton@samba.org Fixed knownfail conflicts]
12604
---
12605
 python/samba/tests/krb5/kpasswd_tests.py | 28 ++++++++++++++++++++++++
12606
 selftest/knownfail_heimdal_kdc           |  4 ++++
12607
 selftest/knownfail_mit_kdc               |  4 ++++
12608
 3 files changed, 36 insertions(+)
12609
12610
diff --git python/samba/tests/krb5/kpasswd_tests.py python/samba/tests/krb5/kpasswd_tests.py
12611
index 3a6c7d818dc..0db857f7bbd 100755
12612
--- python/samba/tests/krb5/kpasswd_tests.py
12613
+++ python/samba/tests/krb5/kpasswd_tests.py
12614
@@ -31,6 +31,7 @@ from samba.tests.krb5.rfc4120_constants import (
12615
     KDC_ERR_TGT_REVOKED,
12616
     KDC_ERR_TKT_EXPIRED,
12617
     KPASSWD_ACCESSDENIED,
12618
+    KPASSWD_AUTHERROR,
12619
     KPASSWD_HARDERROR,
12620
     KPASSWD_INITIAL_FLAG_NEEDED,
12621
     KPASSWD_MALFORMED,
12622
@@ -779,6 +780,33 @@ class KpasswdTests(KDCBaseTest):
12623
         self._make_tgs_request(creds, service_creds, ticket,
12624
                                expect_error=False)
12625
 
12626
+    # Show that we cannot provide a TGT to kpasswd to change the password.
12627
+    def test_kpasswd_tgt(self):
12628
+        # Create an account for testing, and get a TGT.
12629
+        creds = self._get_creds()
12630
+        tgt = self.get_tgt(creds)
12631
+
12632
+        # Change the sname of the ticket to match that of kadmin/changepw.
12633
+        tgt.set_sname(self.get_kpasswd_sname())
12634
+
12635
+        expected_code = KPASSWD_AUTHERROR
12636
+        expected_msg = b'A TGT may not be used as a ticket to kpasswd'
12637
+
12638
+        # Set the password.
12639
+        new_password = generate_random_password(32, 32)
12640
+        self.kpasswd_exchange(tgt,
12641
+                              new_password,
12642
+                              expected_code,
12643
+                              expected_msg,
12644
+                              mode=self.KpasswdMode.SET)
12645
+
12646
+        # Change the password.
12647
+        self.kpasswd_exchange(tgt,
12648
+                              new_password,
12649
+                              expected_code,
12650
+                              expected_msg,
12651
+                              mode=self.KpasswdMode.CHANGE)
12652
+
12653
     # Test that kpasswd rejects requests with a service ticket.
12654
     def test_kpasswd_non_initial(self):
12655
         # Create an account for testing, and get a TGT.
12656
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
12657
index 424a8b81c38..42beccaed58 100644
12658
--- selftest/knownfail_heimdal_kdc
12659
+++ selftest/knownfail_heimdal_kdc
12660
@@ -271,3 +271,7 @@
12661
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
12662
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
12663
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
12664
+#
12665
+# Kpasswd tests
12666
+#
12667
+^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc
12668
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
12669
index 0d2f5bab6d2..9fc34e5d8db 100644
12670
--- selftest/knownfail_mit_kdc
12671
+++ selftest/knownfail_mit_kdc
12672
@@ -581,3 +581,7 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
12673
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
12674
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
12675
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
12676
+#
12677
+# Kpasswd tests
12678
+#
12679
+samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc
12680
-- 
12681
2.25.1
12682
12683
12684
From 4b61092459b403b2945daa9082052366f3508b69 Mon Sep 17 00:00:00 2001
12685
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12686
Date: Fri, 10 Jun 2022 19:18:07 +1200
12687
Subject: [PATCH 94/99] CVE-2022-2031 auth: Add ticket type field to
12688
 auth_user_info_dc and auth_session_info
12689
12690
This field may be used to convey whether we were provided with a TGT or
12691
a non-TGT. We ensure both structures are zeroed out to avoid incorrect
12692
results being produced by an uninitialised field.
12693
12694
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
12695
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
12696
12697
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12698
Reviewed-by: Andreas Schneider <asn@samba.org>
12699
---
12700
 auth/auth_sam_reply.c              |  2 +-
12701
 auth/auth_util.c                   |  2 +-
12702
 librpc/idl/auth.idl                | 23 +++++++++++++++++++++++
12703
 source4/auth/ntlm/auth_developer.c |  2 +-
12704
 source4/auth/sam.c                 |  2 +-
12705
 source4/auth/session.c             |  2 ++
12706
 source4/auth/system_session.c      |  6 +++---
12707
 7 files changed, 32 insertions(+), 7 deletions(-)
12708
12709
diff --git auth/auth_sam_reply.c auth/auth_sam_reply.c
12710
index b5b6362dc93..2e27e5715d1 100644
12711
--- auth/auth_sam_reply.c
12712
+++ auth/auth_sam_reply.c
12713
@@ -416,7 +416,7 @@ NTSTATUS make_user_info_dc_netlogon_validation(TALLOC_CTX *mem_ctx,
12714
 		return NT_STATUS_INVALID_LEVEL;
12715
 	}
12716
 
12717
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
12718
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
12719
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
12720
 
12721
 	/*
12722
diff --git auth/auth_util.c auth/auth_util.c
12723
index fe01babd107..ec9094d0f15 100644
12724
--- auth/auth_util.c
12725
+++ auth/auth_util.c
12726
@@ -44,7 +44,7 @@ struct auth_session_info *copy_session_info(TALLOC_CTX *mem_ctx,
12727
 		return NULL;
12728
 	}
12729
 
12730
-	dst = talloc(mem_ctx, struct auth_session_info);
12731
+	dst = talloc_zero(mem_ctx, struct auth_session_info);
12732
 	if (dst == NULL) {
12733
 		DBG_ERR("talloc failed\n");
12734
 		TALLOC_FREE(frame);
12735
diff --git librpc/idl/auth.idl librpc/idl/auth.idl
12736
index 1092935b971..f7658cdde28 100644
12737
--- librpc/idl/auth.idl
12738
+++ librpc/idl/auth.idl
12739
@@ -75,6 +75,26 @@ interface auth
12740
 		[unique,charset(UTF8),string] char *sanitized_username;
12741
 	} auth_user_info_unix;
12742
 
12743
+	/*
12744
+	 * If the user was authenticated with a Kerberos ticket, this indicates
12745
+	 * the type of the ticket; TGT, or non-TGT (i.e. service ticket). If
12746
+	 * unset, the type is unknown. This indicator is useful for the KDC and
12747
+	 * the kpasswd service, which share the same account and keys. By
12748
+	 * ensuring it is provided with the appopriate ticket type, each service
12749
+	 * avoids accepting a ticket meant for the other.
12750
+	 *
12751
+	 * The heuristic used to determine the type is the presence or absence
12752
+	 * of a REQUESTER_SID buffer in the PAC; we use its presence to assume
12753
+	 * we have a TGT. This heuristic will fail for older Samba versions and
12754
+	 * Windows prior to Nov. 2021 updates, which lack support for this
12755
+	 * buffer.
12756
+	 */
12757
+	typedef enum {
12758
+		TICKET_TYPE_UNKNOWN = 0,
12759
+		TICKET_TYPE_TGT = 1,
12760
+		TICKET_TYPE_NON_TGT = 2
12761
+	} ticket_type;
12762
+
12763
 	/* This is the interim product of the auth subsystem, before
12764
 	 * privileges and local groups are handled */
12765
 	typedef [public] struct {
12766
@@ -83,6 +103,7 @@ interface auth
12767
 		auth_user_info *info;
12768
 		[noprint] DATA_BLOB user_session_key;
12769
 		[noprint] DATA_BLOB lm_session_key;
12770
+		ticket_type ticket_type;
12771
 	} auth_user_info_dc;
12772
 
12773
 	typedef [public] struct {
12774
@@ -112,6 +133,8 @@ interface auth
12775
 		 * We generate this in auth_generate_session_info()
12776
 		 */
12777
 	        GUID unique_session_token;
12778
+
12779
+		ticket_type ticket_type;
12780
 	} auth_session_info;
12781
 
12782
 	typedef [public] struct {
12783
diff --git source4/auth/ntlm/auth_developer.c source4/auth/ntlm/auth_developer.c
12784
index 1823989c68d..6e92252d5c5 100644
12785
--- source4/auth/ntlm/auth_developer.c
12786
+++ source4/auth/ntlm/auth_developer.c
12787
@@ -76,7 +76,7 @@ static NTSTATUS name_to_ntstatus_check_password(struct auth_method_context *ctx,
12788
 	}
12789
 	NT_STATUS_NOT_OK_RETURN(nt_status);
12790
 
12791
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
12792
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
12793
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
12794
 
12795
 	/* This returns a pointer to a struct dom_sid, which is the
12796
diff --git source4/auth/sam.c source4/auth/sam.c
12797
index 8b233bab3ad..7c609655fcb 100644
12798
--- source4/auth/sam.c
12799
+++ source4/auth/sam.c
12800
@@ -363,7 +363,7 @@ _PUBLIC_ NTSTATUS authsam_make_user_info_dc(TALLOC_CTX *mem_ctx,
12801
 	TALLOC_CTX *tmp_ctx;
12802
 	struct ldb_message_element *el;
12803
 
12804
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
12805
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
12806
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
12807
 
12808
 	tmp_ctx = talloc_new(user_info_dc);
12809
diff --git source4/auth/session.c source4/auth/session.c
12810
index 8e44dcd24f1..d6e936dd1f1 100644
12811
--- source4/auth/session.c
12812
+++ source4/auth/session.c
12813
@@ -222,6 +222,8 @@ _PUBLIC_ NTSTATUS auth_generate_session_info(TALLOC_CTX *mem_ctx,
12814
 
12815
 	session_info->credentials = NULL;
12816
 
12817
+	session_info->ticket_type = user_info_dc->ticket_type;
12818
+
12819
 	talloc_steal(mem_ctx, session_info);
12820
 	*_session_info = session_info;
12821
 	talloc_free(tmp_ctx);
12822
diff --git source4/auth/system_session.c source4/auth/system_session.c
12823
index 85b8f1c4edb..2518d654e8b 100644
12824
--- source4/auth/system_session.c
12825
+++ source4/auth/system_session.c
12826
@@ -115,7 +115,7 @@ NTSTATUS auth_system_user_info_dc(TALLOC_CTX *mem_ctx, const char *netbios_name,
12827
 	struct auth_user_info_dc *user_info_dc;
12828
 	struct auth_user_info *info;
12829
 
12830
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
12831
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
12832
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
12833
 
12834
 	/* This returns a pointer to a struct dom_sid, which is the
12835
@@ -191,7 +191,7 @@ static NTSTATUS auth_domain_admin_user_info_dc(TALLOC_CTX *mem_ctx,
12836
 	struct auth_user_info_dc *user_info_dc;
12837
 	struct auth_user_info *info;
12838
 
12839
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
12840
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
12841
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
12842
 
12843
 	user_info_dc->num_sids = 7;
12844
@@ -356,7 +356,7 @@ _PUBLIC_ NTSTATUS auth_anonymous_user_info_dc(TALLOC_CTX *mem_ctx,
12845
 {
12846
 	struct auth_user_info_dc *user_info_dc;
12847
 	struct auth_user_info *info;
12848
-	user_info_dc = talloc(mem_ctx, struct auth_user_info_dc);
12849
+	user_info_dc = talloc_zero(mem_ctx, struct auth_user_info_dc);
12850
 	NT_STATUS_HAVE_NO_MEMORY(user_info_dc);
12851
 
12852
 	/* This returns a pointer to a struct dom_sid, which is the
12853
-- 
12854
2.25.1
12855
12856
12857
From 89c6e36938c27b572573b06d1b35db210bfda99b Mon Sep 17 00:00:00 2001
12858
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12859
Date: Fri, 10 Jun 2022 19:18:35 +1200
12860
Subject: [PATCH 95/99] CVE-2022-2031 s4:auth: Use PAC to determine whether
12861
 ticket is a TGT
12862
12863
We use the presence or absence of a REQUESTER_SID PAC buffer to
12864
determine whether the ticket is a TGT. We will later use this to reject
12865
TGTs where a service ticket is expected.
12866
12867
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
12868
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
12869
12870
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12871
Reviewed-by: Andreas Schneider <asn@samba.org>
12872
---
12873
 source4/auth/kerberos/kerberos_pac.c | 44 ++++++++++++++++++++++++++++
12874
 1 file changed, 44 insertions(+)
12875
12876
diff --git source4/auth/kerberos/kerberos_pac.c source4/auth/kerberos/kerberos_pac.c
12877
index 54ef4d61b02..bd0ae20e007 100644
12878
--- source4/auth/kerberos/kerberos_pac.c
12879
+++ source4/auth/kerberos/kerberos_pac.c
12880
@@ -282,6 +282,28 @@
12881
 	return ret;
12882
 }
12883
 
12884
+static krb5_error_code kerberos_pac_buffer_present(krb5_context context,
12885
+						   const krb5_pac pac,
12886
+						   uint32_t type)
12887
+{
12888
+#ifdef SAMBA4_USES_HEIMDAL
12889
+	return krb5_pac_get_buffer(context, pac, type, NULL);
12890
+#else /* MIT */
12891
+	krb5_error_code ret;
12892
+	krb5_data data;
12893
+
12894
+	/*
12895
+	 * MIT won't let us pass NULL for the data parameter, so we are forced
12896
+	 * to allocate a new buffer and then immediately free it.
12897
+	 */
12898
+	ret = krb5_pac_get_buffer(context, pac, type, &data);
12899
+	if (ret == 0) {
12900
+		krb5_free_data_contents(context, &data);
12901
+	}
12902
+	return ret;
12903
+#endif /* SAMBA4_USES_HEIMDAL */
12904
+}
12905
+
12906
 krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx,
12907
 					     krb5_pac pac,
12908
 					     krb5_context context,
12909
@@ -414,6 +436,28 @@ krb5_error_code kerberos_pac_to_user_info_dc(TALLOC_CTX *mem_ctx,
12910
 			return EINVAL;
12911
 		}
12912
 	}
12913
+
12914
+	/*
12915
+	 * Based on the presence of a REQUESTER_SID PAC buffer, ascertain
12916
+	 * whether the ticket is a TGT. This helps the KDC and kpasswd service
12917
+	 * ensure they do not accept tickets meant for the other.
12918
+	 *
12919
+	 * This heuristic will fail for older Samba versions and Windows prior
12920
+	 * to Nov. 2021 updates, which lack support for the REQUESTER_SID PAC
12921
+	 * buffer.
12922
+	 */
12923
+	ret = kerberos_pac_buffer_present(context, pac, PAC_TYPE_REQUESTER_SID);
12924
+	if (ret == ENOENT) {
12925
+		/* This probably isn't a TGT. */
12926
+		user_info_dc_out->ticket_type = TICKET_TYPE_NON_TGT;
12927
+	} else if (ret != 0) {
12928
+		talloc_free(tmp_ctx);
12929
+		return ret;
12930
+	} else {
12931
+		/* This probably is a TGT. */
12932
+		user_info_dc_out->ticket_type = TICKET_TYPE_TGT;
12933
+	}
12934
+
12935
 	*user_info_dc = user_info_dc_out;
12936
 
12937
 	return 0;
12938
-- 
12939
2.25.1
12940
12941
12942
From d5af460403d3949ba266f5c74f051247cd7ce752 Mon Sep 17 00:00:00 2001
12943
From: Joseph Sutton <josephsutton@catalyst.net.nz>
12944
Date: Fri, 10 Jun 2022 19:18:53 +1200
12945
Subject: [PATCH 96/99] CVE-2022-2031 s4:kpasswd: Do not accept TGTs as kpasswd
12946
 tickets
12947
12948
If TGTs can be used as kpasswd tickets, the two-minute lifetime of a
12949
authentic kpasswd ticket may be bypassed. Furthermore, kpasswd tickets
12950
are not supposed to be cached, but using this flaw, a stolen credentials
12951
cache containing a TGT may be used to change that account's password,
12952
and thus is made more valuable to an attacker.
12953
12954
Since all TGTs should be issued with a REQUESTER_SID PAC buffer, and
12955
service tickets without it, we assert the absence of this buffer to
12956
ensure we're not accepting a TGT.
12957
12958
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
12959
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15049
12960
12961
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
12962
Reviewed-by: Andreas Schneider <asn@samba.org>
12963
12964
[jsutton@samba.org Fixed knownfail conflicts]
12965
12966
[jsutton@samba.org Fixed knownfail conflicts]
12967
---
12968
 selftest/knownfail_heimdal_kdc        |  4 ----
12969
 selftest/knownfail_mit_kdc            |  4 ----
12970
 source4/kdc/kpasswd-helper.c          | 20 ++++++++++++++++++++
12971
 source4/kdc/kpasswd-helper.h          |  2 ++
12972
 source4/kdc/kpasswd-service-heimdal.c | 13 +++++++++++++
12973
 source4/kdc/kpasswd-service-mit.c     | 13 +++++++++++++
12974
 6 files changed, 48 insertions(+), 8 deletions(-)
12975
12976
diff --git selftest/knownfail_heimdal_kdc selftest/knownfail_heimdal_kdc
12977
index 42beccaed58..424a8b81c38 100644
12978
--- selftest/knownfail_heimdal_kdc
12979
+++ selftest/knownfail_heimdal_kdc
12980
@@ -271,7 +271,3 @@
12981
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_service_ticket
12982
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_existing
12983
 ^samba.tests.krb5.kdc_tgs_tests.samba.tests.krb5.kdc_tgs_tests.KdcTgsTests.test_fast_sid_mismatch_nonexisting
12984
-#
12985
-# Kpasswd tests
12986
-#
12987
-^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc
12988
diff --git selftest/knownfail_mit_kdc selftest/knownfail_mit_kdc
12989
index 9fc34e5d8db..0d2f5bab6d2 100644
12990
--- selftest/knownfail_mit_kdc
12991
+++ selftest/knownfail_mit_kdc
12992
@@ -581,7 +581,3 @@ samba.tests.krb5.as_canonicalization_tests.samba.tests.krb5.as_canonicalization_
12993
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_canonicalize_realm_case.ad_dc
12994
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_no_canonicalize_realm_case.ad_dc
12995
 ^samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_ticket_requester_sid_tgs.ad_dc
12996
-#
12997
-# Kpasswd tests
12998
-#
12999
-samba.tests.krb5.kpasswd_tests.samba.tests.krb5.kpasswd_tests.KpasswdTests.test_kpasswd_tgt.ad_dc
13000
diff --git source4/kdc/kpasswd-helper.c source4/kdc/kpasswd-helper.c
13001
index 55a2f5b3bf6..2ffdb79aea5 100644
13002
--- source4/kdc/kpasswd-helper.c
13003
+++ source4/kdc/kpasswd-helper.c
13004
@@ -241,3 +241,23 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx,
13005
 
13006
 	return status;
13007
 }
13008
+
13009
+krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info,
13010
+				      const char **error_string)
13011
+{
13012
+	switch(session_info->ticket_type) {
13013
+	case TICKET_TYPE_TGT:
13014
+		/* TGTs are disallowed here. */
13015
+		*error_string = "A TGT may not be used as a ticket to kpasswd";
13016
+		return KRB5_KPASSWD_AUTHERROR;
13017
+	case TICKET_TYPE_NON_TGT:
13018
+		/* Non-TGTs are permitted, and expected. */
13019
+		break;
13020
+	default:
13021
+		/* In case we forgot to set the type. */
13022
+		*error_string = "Failed to ascertain that ticket to kpasswd is not a TGT";
13023
+		return KRB5_KPASSWD_HARDERROR;
13024
+	}
13025
+
13026
+	return 0;
13027
+}
13028
diff --git source4/kdc/kpasswd-helper.h source4/kdc/kpasswd-helper.h
13029
index 8fad81e0a5d..94a6e2acfdd 100644
13030
--- source4/kdc/kpasswd-helper.h
13031
+++ source4/kdc/kpasswd-helper.h
13032
@@ -43,4 +43,6 @@ NTSTATUS kpasswd_samdb_set_password(TALLOC_CTX *mem_ctx,
13033
 				    enum samPwdChangeReason *reject_reason,
13034
 				    struct samr_DomInfo1 **dominfo);
13035
 
13036
+krb5_error_code kpasswd_check_non_tgt(struct auth_session_info *session_info,
13037
+				      const char **error_string);
13038
 #endif /* _KPASSWD_HELPER_H */
13039
diff --git source4/kdc/kpasswd-service-heimdal.c source4/kdc/kpasswd-service-heimdal.c
13040
index a0352d1ad35..4d009b9eb24 100644
13041
--- source4/kdc/kpasswd-service-heimdal.c
13042
+++ source4/kdc/kpasswd-service-heimdal.c
13043
@@ -253,6 +253,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
13044
 {
13045
 	struct auth_session_info *session_info;
13046
 	NTSTATUS status;
13047
+	krb5_error_code code;
13048
 
13049
 	status = gensec_session_info(gensec_security,
13050
 				     mem_ctx,
13051
@@ -264,6 +265,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
13052
 		return KRB5_KPASSWD_HARDERROR;
13053
 	}
13054
 
13055
+	/*
13056
+	 * Since the kpasswd service shares its keys with the krbtgt, we might
13057
+	 * have received a TGT rather than a kpasswd ticket. We need to check
13058
+	 * the ticket type to ensure that TGTs cannot be misused in this manner.
13059
+	 */
13060
+	code = kpasswd_check_non_tgt(session_info,
13061
+				     error_string);
13062
+	if (code != 0) {
13063
+		DBG_WARNING("%s\n", *error_string);
13064
+		return code;
13065
+	}
13066
+
13067
 	switch(verno) {
13068
 	case KRB5_KPASSWD_VERS_CHANGEPW: {
13069
 		DATA_BLOB password = data_blob_null;
13070
diff --git source4/kdc/kpasswd-service-mit.c source4/kdc/kpasswd-service-mit.c
13071
index de4c6f3f622..6b051567b6e 100644
13072
--- source4/kdc/kpasswd-service-mit.c
13073
+++ source4/kdc/kpasswd-service-mit.c
13074
@@ -332,6 +332,7 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
13075
 {
13076
 	struct auth_session_info *session_info;
13077
 	NTSTATUS status;
13078
+	krb5_error_code code;
13079
 
13080
 	status = gensec_session_info(gensec_security,
13081
 				     mem_ctx,
13082
@@ -344,6 +345,18 @@ krb5_error_code kpasswd_handle_request(struct kdc_server *kdc,
13083
 		return KRB5_KPASSWD_HARDERROR;
13084
 	}
13085
 
13086
+	/*
13087
+	 * Since the kpasswd service shares its keys with the krbtgt, we might
13088
+	 * have received a TGT rather than a kpasswd ticket. We need to check
13089
+	 * the ticket type to ensure that TGTs cannot be misused in this manner.
13090
+	 */
13091
+	code = kpasswd_check_non_tgt(session_info,
13092
+				     error_string);
13093
+	if (code != 0) {
13094
+		DBG_WARNING("%s\n", *error_string);
13095
+		return code;
13096
+	}
13097
+
13098
 	switch(verno) {
13099
 	case 1: {
13100
 		DATA_BLOB password;
13101
-- 
13102
2.25.1
13103
13104
13105
From a6231af1f1c03cd81614332f867916e1748e03a8 Mon Sep 17 00:00:00 2001
13106
From: Joseph Sutton <josephsutton@catalyst.net.nz>
13107
Date: Thu, 23 Jun 2022 13:59:11 +1200
13108
Subject: [PATCH 97/99] CVE-2022-2031 testprogs: Add test for short-lived
13109
 ticket across an incoming trust
13110
13111
We ensure that the KDC does not reject a TGS-REQ with our short-lived
13112
TGT over an incoming trust.
13113
13114
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15047
13115
13116
Signed-off-by: Joseph Sutton <josephsutton@catalyst.net.nz>
13117
13118
[jsutton@samba.org Changed --use-krb5-ccache to -k yes to match
13119
 surrounding usage]
13120
---
13121
 testprogs/blackbox/test_kinit_trusts_heimdal.sh | 6 +++++-
13122
 1 file changed, 5 insertions(+), 1 deletion(-)
13123
13124
diff --git testprogs/blackbox/test_kinit_trusts_heimdal.sh testprogs/blackbox/test_kinit_trusts_heimdal.sh
13125
index bf0b81a0473..621434eac35 100755
13126
--- testprogs/blackbox/test_kinit_trusts_heimdal.sh
13127
+++ testprogs/blackbox/test_kinit_trusts_heimdal.sh
13128
@@ -54,6 +54,10 @@ testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppa
13129
 test_smbclient "Test login with user kerberos ccache" 'ls' "$unc" -k yes || failed=`expr $failed + 1`
13130
 rm -rf $KRB5CCNAME_PATH
13131
 
13132
+testit "kinit with password and two minute lifetime" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac --server=krbtgt/$REALM@$TRUST_REALM --lifetime=2m $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1`
13133
+test_smbclient "Test login with user kerberos ccache and two minute lifetime" 'ls' "$unc" -k yes || failed=`expr $failed + 1`
13134
+rm -rf $KRB5CCNAME_PATH
13135
+
13136
 # Test with smbclient4
13137
 smbclient="$samba4bindir/smbclient4"
13138
 testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM   || failed=`expr $failed + 1`
13139
@@ -94,5 +98,5 @@ testit "wbinfo check outgoing trust pw" $VALGRIND $wbinfo --check-secret --domai
13140
 
13141
 test_smbclient "Test user login with the changed outgoing secret" 'ls' "$unc" -k yes -U$USERNAME@$REALM%$PASSWORD || failed=`expr $failed + 1`
13142
 
13143
-rm -f $PREFIX/tmpccache tmpccfile tmppassfile tmpuserpassfile tmpuserccache
13144
+rm -f $PREFIX/tmpccache $PREFIX/tmppassfile
13145
 exit $failed
13146
-- 
13147
2.25.1
13148
13149
13150
From f6e1750c4fc966c29c2e0663d3c04e87057fa0c3 Mon Sep 17 00:00:00 2001
13151
From: Jeremy Allison <jra@samba.org>
13152
Date: Tue, 7 Jun 2022 09:40:45 -0700
13153
Subject: [PATCH 98/99] CVE-2022-32742: s4: torture: Add raw.write.bad-write
13154
 test.
13155
13156
Reproduces the test code in:
13157
13158
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085
13159
13160
Add knownfail.
13161
13162
Signed-off-by: Jeremy Allison <jra@samba.org>
13163
Reviewed-by: David Disseldorp <ddiss@samba.org>
13164
---
13165
 selftest/knownfail.d/bad-write |  2 +
13166
 source4/torture/raw/write.c    | 89 ++++++++++++++++++++++++++++++++++
13167
 2 files changed, 91 insertions(+)
13168
 create mode 100644 selftest/knownfail.d/bad-write
13169
13170
diff --git selftest/knownfail.d/bad-write selftest/knownfail.d/bad-write
13171
new file mode 100644
13172
index 00000000000..5fc16606a13
13173
--- /dev/null
13174
+++ selftest/knownfail.d/bad-write
13175
@@ -0,0 +1,2 @@
13176
+^samba3.raw.write.bad-write\(nt4_dc_smb1\)
13177
+^samba3.raw.write.bad-write\(ad_dc_smb1\)
13178
diff --git source4/torture/raw/write.c source4/torture/raw/write.c
13179
index 0a2f50f425b..661485bb548 100644
13180
--- source4/torture/raw/write.c
13181
+++ source4/torture/raw/write.c
13182
@@ -25,6 +25,7 @@
13183
 #include "libcli/libcli.h"
13184
 #include "torture/util.h"
13185
 #include "torture/raw/proto.h"
13186
+#include "libcli/raw/raw_proto.h"
13187
 
13188
 #define CHECK_STATUS(status, correct) do { \
13189
 	if (!NT_STATUS_EQUAL(status, correct)) { \
13190
@@ -694,6 +695,93 @@ done:
13191
 	return ret;
13192
 }
13193
 
13194
+/*
13195
+  test a deliberately bad SMB1 write.
13196
+*/
13197
+static bool test_bad_write(struct torture_context *tctx,
13198
+		       struct smbcli_state *cli)
13199
+{
13200
+	bool ret = false;
13201
+	int fnum = -1;
13202
+	struct smbcli_request *req = NULL;
13203
+	const char *fname = BASEDIR "\\badwrite.txt";
13204
+	bool ok = false;
13205
+
13206
+	if (!torture_setup_dir(cli, BASEDIR)) {
13207
+		torture_fail(tctx, "failed to setup basedir");
13208
+	}
13209
+
13210
+	torture_comment(tctx, "Testing RAW_BAD_WRITE\n");
13211
+
13212
+	fnum = smbcli_open(cli->tree, fname, O_RDWR|O_CREAT, DENY_NONE);
13213
+	if (fnum == -1) {
13214
+		torture_fail_goto(tctx,
13215
+			done,
13216
+			talloc_asprintf(tctx,
13217
+				"Failed to create %s - %s\n",
13218
+				fname,
13219
+				smbcli_errstr(cli->tree)));
13220
+	}
13221
+
13222
+	req = smbcli_request_setup(cli->tree,
13223
+				   SMBwrite,
13224
+				   5,
13225
+				   0);
13226
+	if (req == NULL) {
13227
+		torture_fail_goto(tctx,
13228
+			done,
13229
+			talloc_asprintf(tctx, "talloc fail\n"));
13230
+	}
13231
+
13232
+	SSVAL(req->out.vwv, VWV(0), fnum);
13233
+	SSVAL(req->out.vwv, VWV(1), 65535); /* bad write length. */
13234
+	SIVAL(req->out.vwv, VWV(2), 0); /* offset */
13235
+	SSVAL(req->out.vwv, VWV(4), 0); /* remaining. */
13236
+
13237
+        if (!smbcli_request_send(req)) {
13238
+		torture_fail_goto(tctx,
13239
+			done,
13240
+			talloc_asprintf(tctx, "Send failed\n"));
13241
+        }
13242
+
13243
+        if (!smbcli_request_receive(req)) {
13244
+		torture_fail_goto(tctx,
13245
+			done,
13246
+			talloc_asprintf(tctx, "Reveive failed\n"));
13247
+	}
13248
+
13249
+	/*
13250
+	 * Check for expected error codes.
13251
+	 * ntvfs returns NT_STATUS_UNSUCCESSFUL.
13252
+	 */
13253
+	ok = (NT_STATUS_EQUAL(req->status, NT_STATUS_INVALID_PARAMETER) ||
13254
+	     NT_STATUS_EQUAL(req->status, NT_STATUS_UNSUCCESSFUL));
13255
+
13256
+	if (!ok) {
13257
+		torture_fail_goto(tctx,
13258
+			done,
13259
+			talloc_asprintf(tctx,
13260
+				"Should have returned "
13261
+				"NT_STATUS_INVALID_PARAMETER or "
13262
+				"NT_STATUS_UNSUCCESSFUL "
13263
+				"got %s\n",
13264
+				nt_errstr(req->status)));
13265
+        }
13266
+
13267
+	ret = true;
13268
+
13269
+done:
13270
+	if (req != NULL) {
13271
+		smbcli_request_destroy(req);
13272
+	}
13273
+	if (fnum != -1) {
13274
+		smbcli_close(cli->tree, fnum);
13275
+	}
13276
+	smb_raw_exit(cli->session);
13277
+	smbcli_deltree(cli->tree, BASEDIR);
13278
+	return ret;
13279
+}
13280
+
13281
 /*
13282
    basic testing of write calls
13283
 */
13284
@@ -705,6 +793,7 @@ struct torture_suite *torture_raw_write(TALLOC_CTX *mem_ctx)
13285
 	torture_suite_add_1smb_test(suite, "write unlock", test_writeunlock);
13286
 	torture_suite_add_1smb_test(suite, "write close", test_writeclose);
13287
 	torture_suite_add_1smb_test(suite, "writex", test_writex);
13288
+	torture_suite_add_1smb_test(suite, "bad-write", test_bad_write);
13289
 
13290
 	return suite;
13291
 }
13292
-- 
13293
2.25.1
13294
13295
13296
From 7720e0acfd7ea6a2339f3e389aa8dcedd6174095 Mon Sep 17 00:00:00 2001
13297
From: Jeremy Allison <jra@samba.org>
13298
Date: Wed, 8 Jun 2022 13:50:51 -0700
13299
Subject: [PATCH 99/99] CVE-2022-32742: s3: smbd: Harden the smbreq_bufrem()
13300
 macro.
13301
13302
Fixes the raw.write.bad-write test.
13303
13304
NB. We need the two (==0) changes in source3/smbd/reply.c
13305
as the gcc optimizer now knows that the return from
13306
smbreq_bufrem() can never be less than zero.
13307
13308
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15085
13309
13310
Remove knownfail.
13311
13312
Signed-off-by: Jeremy Allison <jra@samba.org>
13313
Reviewed-by: David Disseldorp <ddiss@samba.org>
13314
---
13315
 selftest/knownfail.d/bad-write | 2 --
13316
 source3/include/smb_macros.h   | 2 +-
13317
 source3/smbd/reply.c           | 4 ++--
13318
 3 files changed, 3 insertions(+), 5 deletions(-)
13319
 delete mode 100644 selftest/knownfail.d/bad-write
13320
13321
diff --git selftest/knownfail.d/bad-write selftest/knownfail.d/bad-write
13322
deleted file mode 100644
13323
index 5fc16606a13..00000000000
13324
--- selftest/knownfail.d/bad-write
13325
+++ /dev/null
13326
@@ -1,2 +0,0 @@
13327
-^samba3.raw.write.bad-write\(nt4_dc_smb1\)
13328
-^samba3.raw.write.bad-write\(ad_dc_smb1\)
13329
diff --git source3/include/smb_macros.h source3/include/smb_macros.h
13330
index def122727f0..de1322a503b 100644
13331
--- source3/include/smb_macros.h
13332
+++ source3/include/smb_macros.h
13333
@@ -152,7 +152,7 @@
13334
 
13335
 /* the remaining number of bytes in smb buffer 'buf' from pointer 'p'. */
13336
 #define smb_bufrem(buf, p) (smb_buflen(buf)-PTR_DIFF(p, smb_buf(buf)))
13337
-#define smbreq_bufrem(req, p) (req->buflen - PTR_DIFF(p, req->buf))
13338
+#define smbreq_bufrem(req, p) ((req)->buflen < PTR_DIFF((p), (req)->buf) ? 0 : (req)->buflen - PTR_DIFF((p), (req)->buf))
13339
 
13340
 
13341
 /* Note that chain_size must be available as an extern int to this macro. */
13342
diff --git source3/smbd/reply.c source3/smbd/reply.c
13343
index f33326564f7..b5abe588910 100644
13344
--- source3/smbd/reply.c
13345
+++ source3/smbd/reply.c
13346
@@ -342,7 +342,7 @@ size_t srvstr_get_path_req(TALLOC_CTX *mem_ctx, struct smb_request *req,
13347
 {
13348
 	ssize_t bufrem = smbreq_bufrem(req, src);
13349
 
13350
-	if (bufrem < 0) {
13351
+	if (bufrem == 0) {
13352
 		*err = NT_STATUS_INVALID_PARAMETER;
13353
 		return 0;
13354
 	}
13355
@@ -380,7 +380,7 @@ size_t srvstr_pull_req_talloc(TALLOC_CTX *ctx, struct smb_request *req,
13356
 {
13357
 	ssize_t bufrem = smbreq_bufrem(req, src);
13358
 
13359
-	if (bufrem < 0) {
13360
+	if (bufrem == 0) {
13361
 		return 0;
13362
 	}
13363
 
13364
-- 
13365
2.25.1
13366
(-)b/net/samba413/files/patch-waf-2.0.20 (+1663 lines)
Added Link Here
1
From 5fc3a71d0f54b176d3cb2e399718d0468507e797 Mon Sep 17 00:00:00 2001
2
From: David Mulder <dmulder@suse.com>
3
Date: Mon, 24 Aug 2020 13:12:46 -0600
4
Subject: [PATCH] waf: upgrade to 2.0.20
5
6
This contain an important change:
7
"Fix gccdeps.scan() returning nodes that no longer exist on disk."
8
https://gitlab.com/ita1024/waf/-/merge_requests/2293
9
10
Signed-off-by: David Mulder <dmulder@suse.com>
11
Reviewed-by: Stefan Metzmacher <metze@samba.org>
12
---
13
 buildtools/bin/waf                            |   2 +-
14
 buildtools/wafsamba/samba_utils.py            |   2 +-
15
 buildtools/wafsamba/samba_waf18.py            |   3 +-
16
 buildtools/wafsamba/wafsamba.py               |   2 +-
17
 third_party/waf/waflib/Configure.py           |  25 +-
18
 third_party/waf/waflib/Context.py             |  18 +-
19
 third_party/waf/waflib/Options.py             |  31 +-
20
 third_party/waf/waflib/Scripting.py           |   6 +-
21
 third_party/waf/waflib/Tools/c_aliases.py     |   4 +-
22
 third_party/waf/waflib/Tools/c_config.py      |  22 +-
23
 third_party/waf/waflib/Tools/c_tests.py       |  15 +-
24
 third_party/waf/waflib/Tools/compiler_c.py    |   2 +-
25
 third_party/waf/waflib/Tools/compiler_cxx.py  |   2 +-
26
 third_party/waf/waflib/Tools/fc.py            |   4 +-
27
 third_party/waf/waflib/Tools/irixcc.py        |  14 +-
28
 third_party/waf/waflib/Tools/javaw.py         |   2 +-
29
 third_party/waf/waflib/Tools/python.py        |   2 +-
30
 third_party/waf/waflib/Tools/qt5.py           |   6 +-
31
 third_party/waf/waflib/Utils.py               |   2 +-
32
 .../extras/clang_compilation_database.py      | 172 ++++--
33
 third_party/waf/waflib/extras/doxygen.py      |   1 +
34
 third_party/waf/waflib/extras/gccdeps.py      |  15 +-
35
 third_party/waf/waflib/extras/javatest.py     | 135 ++++-
36
 third_party/waf/waflib/extras/msvc_pdb.py     |  46 ++
37
 third_party/waf/waflib/extras/pytest.py       |  17 +-
38
 third_party/waf/waflib/extras/wafcache.py     | 524 ++++++++++++++++++
39
 26 files changed, 942 insertions(+), 132 deletions(-)
40
 create mode 100644 third_party/waf/waflib/extras/msvc_pdb.py
41
 create mode 100644 third_party/waf/waflib/extras/wafcache.py
42
43
diff --git buildtools/bin/waf buildtools/bin/waf
44
index 11ce8e7480a..feabe25d131 100755
45
--- buildtools/bin/waf
46
+++ buildtools/bin/waf
47
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
48
 
49
 import os, sys, inspect
50
 
51
-VERSION="2.0.18"
52
+VERSION="2.0.20"
53
 REVISION="x"
54
 GIT="x"
55
 INSTALL="x"
56
diff --git buildtools/wafsamba/samba_utils.py buildtools/wafsamba/samba_utils.py
57
index 4afee249d33..0587f525aff 100644
58
--- buildtools/wafsamba/samba_utils.py
59
+++ buildtools/wafsamba/samba_utils.py
60
@@ -459,7 +459,7 @@ def RECURSE(ctx, directory):
61
         return
62
     visited_dirs.add(key)
63
     relpath = os.path.relpath(abspath, ctx.path.abspath())
64
-    if ctxclass in ['tmp', 'OptionsContext', 'ConfigurationContext', 'BuildContext']:
65
+    if ctxclass in ['tmp', 'OptionsContext', 'ConfigurationContext', 'BuildContext', 'ClangDbContext']:
66
         return ctx.recurse(relpath)
67
     if 'waflib.extras.compat15' in sys.modules:
68
         return ctx.recurse(relpath)
69
diff --git buildtools/wafsamba/samba_waf18.py buildtools/wafsamba/samba_waf18.py
70
index c0bb6bfcf55..ecf3891f175 100644
71
--- buildtools/wafsamba/samba_waf18.py
72
+++ buildtools/wafsamba/samba_waf18.py
73
@@ -5,6 +5,7 @@ from waflib import Build, Configure, Node, Utils, Options, Logs, TaskGen
74
 from waflib import ConfigSet
75
 from waflib.TaskGen import feature, after
76
 from waflib.Configure import conf, ConfigurationContext
77
+from waflib.extras import clang_compilation_database
78
 
79
 from waflib.Tools.flex import decide_ext
80
 
81
@@ -37,7 +38,7 @@ TaskGen.declare_chain(
82
 )
83
 
84
 
85
-for y in (Build.BuildContext, Build.CleanContext, Build.InstallContext, Build.UninstallContext, Build.ListContext):
86
+for y in (Build.BuildContext, Build.CleanContext, Build.InstallContext, Build.UninstallContext, Build.ListContext, clang_compilation_database.ClangDbContext):
87
     class tmp(y):
88
         variant = 'default'
89
 
90
diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py
91
index 7827d374654..9f6ee4f5c7f 100644
92
--- buildtools/wafsamba/wafsamba.py
93
+++ buildtools/wafsamba/wafsamba.py
94
@@ -38,7 +38,7 @@ LIB_PATH="shared"
95
 
96
 os.environ['PYTHONUNBUFFERED'] = '1'
97
 
98
-if Context.HEXVERSION not in (0x2001200,):
99
+if Context.HEXVERSION not in (0x2001400,):
100
     Logs.error('''
101
 Please use the version of waf that comes with Samba, not
102
 a system installed version. See http://wiki.samba.org/index.php/Waf
103
diff --git third_party/waf/waflib/Configure.py third_party/waf/waflib/Configure.py
104
index 5762eb66954..e7333948489 100644
105
--- third_party/waf/waflib/Configure.py
106
+++ third_party/waf/waflib/Configure.py
107
@@ -508,23 +508,27 @@ def find_binary(self, filenames, exts, paths):
108
 @conf
109
 def run_build(self, *k, **kw):
110
 	"""
111
-	Create a temporary build context to execute a build. A reference to that build
112
-	context is kept on self.test_bld for debugging purposes, and you should not rely
113
-	on it too much (read the note on the cache below).
114
-	The parameters given in the arguments to this function are passed as arguments for
115
-	a single task generator created in the build. Only three parameters are obligatory:
116
+	Create a temporary build context to execute a build. A temporary reference to that build
117
+	context is kept on self.test_bld for debugging purposes.
118
+	The arguments to this function are passed to a single task generator for that build.
119
+	Only three parameters are mandatory:
120
 
121
 	:param features: features to pass to a task generator created in the build
122
 	:type features: list of string
123
 	:param compile_filename: file to create for the compilation (default: *test.c*)
124
 	:type compile_filename: string
125
-	:param code: code to write in the filename to compile
126
+	:param code: input file contents
127
 	:type code: string
128
 
129
-	Though this function returns *0* by default, the build may set an attribute named *retval* on the
130
+	Though this function returns *0* by default, the build may bind attribute named *retval* on the
131
 	build context object to return a particular value. See :py:func:`waflib.Tools.c_config.test_exec_fun` for example.
132
 
133
-	This function also features a cache which can be enabled by the following option::
134
+	The temporary builds creates a temporary folder; the name of that folder is calculated
135
+	by hashing input arguments to this function, with the exception of :py:class:`waflib.ConfigSet.ConfigSet`
136
+	objects which are used for both reading and writing values.
137
+
138
+	This function also features a cache which is disabled by default; that cache relies
139
+	on the hash value calculated as indicated above::
140
 
141
 		def options(opt):
142
 			opt.add_option('--confcache', dest='confcache', default=0,
143
@@ -538,7 +542,10 @@ def run_build(self, *k, **kw):
144
 	buf = []
145
 	for key in sorted(kw.keys()):
146
 		v = kw[key]
147
-		if hasattr(v, '__call__'):
148
+		if isinstance(v, ConfigSet.ConfigSet):
149
+			# values are being written to, so they are excluded from contributing to the hash
150
+			continue
151
+		elif hasattr(v, '__call__'):
152
 			buf.append(Utils.h_fun(v))
153
 		else:
154
 			buf.append(str(v))
155
diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py
156
index e3305fa3341..3f1b4fa48ab 100644
157
--- third_party/waf/waflib/Context.py
158
+++ third_party/waf/waflib/Context.py
159
@@ -6,20 +6,30 @@
160
 Classes and functions enabling the command system
161
 """
162
 
163
-import os, re, imp, sys
164
+import os, re, sys
165
 from waflib import Utils, Errors, Logs
166
 import waflib.Node
167
 
168
+if sys.hexversion > 0x3040000:
169
+	import types
170
+	class imp(object):
171
+		new_module = lambda x: types.ModuleType(x)
172
+else:
173
+	import imp
174
+
175
 # the following 3 constants are updated on each new release (do not touch)
176
-HEXVERSION=0x2001200
177
+HEXVERSION=0x2001400
178
 """Constant updated on new releases"""
179
 
180
-WAFVERSION="2.0.18"
181
+WAFVERSION="2.0.20"
182
 """Constant updated on new releases"""
183
 
184
-WAFREVISION="314689b8994259a84f0de0aaef74d7ce91f541ad"
185
+WAFREVISION="668769470956da8c5b60817cb8884cd7d0f87cd4"
186
 """Git revision when the waf version is updated"""
187
 
188
+WAFNAME="waf"
189
+"""Application name displayed on --help"""
190
+
191
 ABI = 20
192
 """Version of the build data cache file format (used in :py:const:`waflib.Context.DBFILE`)"""
193
 
194
diff --git third_party/waf/waflib/Options.py third_party/waf/waflib/Options.py
195
index ad802d4b905..d4104917c82 100644
196
--- third_party/waf/waflib/Options.py
197
+++ third_party/waf/waflib/Options.py
198
@@ -44,7 +44,7 @@ class opt_parser(optparse.OptionParser):
199
 	"""
200
 	def __init__(self, ctx, allow_unknown=False):
201
 		optparse.OptionParser.__init__(self, conflict_handler='resolve', add_help_option=False,
202
-			version='waf %s (%s)' % (Context.WAFVERSION, Context.WAFREVISION))
203
+			version='%s %s (%s)' % (Context.WAFNAME, Context.WAFVERSION, Context.WAFREVISION))
204
 		self.formatter.width = Logs.get_term_cols()
205
 		self.ctx = ctx
206
 		self.allow_unknown = allow_unknown
207
@@ -62,6 +62,21 @@ class opt_parser(optparse.OptionParser):
208
 				else:
209
 					self.error(str(e))
210
 
211
+	def _process_long_opt(self, rargs, values):
212
+		# --custom-option=-ftxyz is interpreted as -f -t... see #2280
213
+		if self.allow_unknown:
214
+			back = [] + rargs
215
+			try:
216
+				optparse.OptionParser._process_long_opt(self, rargs, values)
217
+			except optparse.BadOptionError:
218
+				while rargs:
219
+					rargs.pop()
220
+				rargs.extend(back)
221
+				rargs.pop(0)
222
+				raise
223
+		else:
224
+			optparse.OptionParser._process_long_opt(self, rargs, values)
225
+
226
 	def print_usage(self, file=None):
227
 		return self.print_help(file)
228
 
229
@@ -96,11 +111,11 @@ class opt_parser(optparse.OptionParser):
230
 		lst.sort()
231
 		ret = '\n'.join(lst)
232
 
233
-		return '''waf [commands] [options]
234
+		return '''%s [commands] [options]
235
 
236
-Main commands (example: ./waf build -j4)
237
+Main commands (example: ./%s build -j4)
238
 %s
239
-''' % ret
240
+''' % (Context.WAFNAME, Context.WAFNAME, ret)
241
 
242
 
243
 class OptionsContext(Context.Context):
244
@@ -141,9 +156,9 @@ class OptionsContext(Context.Context):
245
 		gr.add_option('-o', '--out', action='store', default='', help='build dir for the project', dest='out')
246
 		gr.add_option('-t', '--top', action='store', default='', help='src dir for the project', dest='top')
247
 
248
-		gr.add_option('--no-lock-in-run', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_run')
249
-		gr.add_option('--no-lock-in-out', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_out')
250
-		gr.add_option('--no-lock-in-top', action='store_true', default='', help=optparse.SUPPRESS_HELP, dest='no_lock_in_top')
251
+		gr.add_option('--no-lock-in-run', action='store_true', default=os.environ.get('NO_LOCK_IN_RUN', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_run')
252
+		gr.add_option('--no-lock-in-out', action='store_true', default=os.environ.get('NO_LOCK_IN_OUT', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_out')
253
+		gr.add_option('--no-lock-in-top', action='store_true', default=os.environ.get('NO_LOCK_IN_TOP', ''), help=optparse.SUPPRESS_HELP, dest='no_lock_in_top')
254
 
255
 		default_prefix = getattr(Context.g_module, 'default_prefix', os.environ.get('PREFIX'))
256
 		if not default_prefix:
257
@@ -282,6 +297,8 @@ class OptionsContext(Context.Context):
258
 			elif arg != 'options':
259
 				commands.append(arg)
260
 
261
+		if options.jobs < 1:
262
+			options.jobs = 1
263
 		for name in 'top out destdir prefix bindir libdir'.split():
264
 			# those paths are usually expanded from Context.launch_dir
265
 			if getattr(options, name, None):
266
diff --git third_party/waf/waflib/Scripting.py third_party/waf/waflib/Scripting.py
267
index 68dccf29ce0..da83a2166a1 100644
268
--- third_party/waf/waflib/Scripting.py
269
+++ third_party/waf/waflib/Scripting.py
270
@@ -306,7 +306,7 @@ def distclean(ctx):
271
 
272
 	# remove a build folder, if any
273
 	cur = '.'
274
-	if ctx.options.no_lock_in_top:
275
+	if os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top:
276
 		cur = ctx.options.out
277
 
278
 	try:
279
@@ -333,9 +333,9 @@ def distclean(ctx):
280
 			remove_and_log(env.out_dir, shutil.rmtree)
281
 
282
 		env_dirs = [env.out_dir]
283
-		if not ctx.options.no_lock_in_top:
284
+		if not (os.environ.get('NO_LOCK_IN_TOP') or ctx.options.no_lock_in_top):
285
 			env_dirs.append(env.top_dir)
286
-		if not ctx.options.no_lock_in_run:
287
+		if not (os.environ.get('NO_LOCK_IN_RUN') or ctx.options.no_lock_in_run):
288
 			env_dirs.append(env.run_dir)
289
 		for k in env_dirs:
290
 			p = os.path.join(k, Options.lockfile)
291
diff --git third_party/waf/waflib/Tools/c_aliases.py third_party/waf/waflib/Tools/c_aliases.py
292
index 985e048bdb7..928cfe29caa 100644
293
--- third_party/waf/waflib/Tools/c_aliases.py
294
+++ third_party/waf/waflib/Tools/c_aliases.py
295
@@ -38,7 +38,7 @@ def sniff_features(**kw):
296
 	:return: the list of features for a task generator processing the source files
297
 	:rtype: list of string
298
 	"""
299
-	exts = get_extensions(kw['source'])
300
+	exts = get_extensions(kw.get('source', []))
301
 	typ = kw['typ']
302
 	feats = []
303
 
304
@@ -72,7 +72,7 @@ def sniff_features(**kw):
305
 				feats.append(x + typ)
306
 				will_link = True
307
 		if not will_link and not kw.get('features', []):
308
-			raise Errors.WafError('Cannot link from %r, try passing eg: features="c cprogram"?' % kw)
309
+			raise Errors.WafError('Unable to determine how to link %r, try adding eg: features="c cshlib"?' % kw)
310
 	return feats
311
 
312
 def set_features(kw, typ):
313
diff --git third_party/waf/waflib/Tools/c_config.py third_party/waf/waflib/Tools/c_config.py
314
index 80580cc9fcb..98187fac2e2 100644
315
--- third_party/waf/waflib/Tools/c_config.py
316
+++ third_party/waf/waflib/Tools/c_config.py
317
@@ -86,6 +86,10 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No
318
 	:type uselib_store: string
319
 	:param env: config set or conf.env by default
320
 	:type env: :py:class:`waflib.ConfigSet.ConfigSet`
321
+	:param force_static: force usage of static libraries
322
+	:type force_static: bool default False
323
+	:param posix: usage of POSIX mode for shlex lexical analiysis library
324
+	:type posix: bool default True
325
 	"""
326
 
327
 	assert(isinstance(line, str))
328
@@ -103,6 +107,8 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No
329
 	lex.commenters = ''
330
 	lst = list(lex)
331
 
332
+	so_re = re.compile(r"\.so(?:\.[0-9]+)*$")
333
+
334
 	# append_unique is not always possible
335
 	# for example, apple flags may require both -arch i386 and -arch ppc
336
 	uselib = uselib_store
337
@@ -144,7 +150,7 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No
338
 		elif x.startswith('-std='):
339
 			prefix = 'CXXFLAGS' if '++' in x else 'CFLAGS'
340
 			app(prefix, x)
341
-		elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie'):
342
+		elif x.startswith('+') or x in ('-pthread', '-fPIC', '-fpic', '-fPIE', '-fpie', '-flto', '-fno-lto'):
343
 			app('CFLAGS', x)
344
 			app('CXXFLAGS', x)
345
 			app('LINKFLAGS', x)
346
@@ -180,7 +186,7 @@ def parse_flags(self, line, uselib_store, env=None, force_static=False, posix=No
347
 			app('CFLAGS', tmp)
348
 			app('CXXFLAGS', tmp)
349
 			app('LINKFLAGS', tmp)
350
-		elif x.endswith(('.a', '.so', '.dylib', '.lib')):
351
+		elif x.endswith(('.a', '.dylib', '.lib')) or so_re.search(x):
352
 			appu('LINKFLAGS', x) # not cool, #762
353
 		else:
354
 			self.to_log('Unhandled flag %r' % x)
355
@@ -246,6 +252,8 @@ def exec_cfg(self, kw):
356
 	* if modversion is given, then return the module version
357
 	* else, execute the *-config* program with the *args* and *variables* given, and set the flags on the *conf.env.FLAGS_name* variable
358
 
359
+	:param path: the **-config program to use**
360
+	:type path: list of string
361
 	:param atleast_pkgconfig_version: minimum pkg-config version to use (disable other tests)
362
 	:type atleast_pkgconfig_version: string
363
 	:param package: package name, for example *gtk+-2.0*
364
@@ -260,6 +268,12 @@ def exec_cfg(self, kw):
365
 	:type variables: list of string
366
 	:param define_variable: additional variables to define (also in conf.env.PKG_CONFIG_DEFINES)
367
 	:type define_variable: dict(string: string)
368
+	:param pkg_config_path: paths where pkg-config should search for .pc config files (overrides env.PKG_CONFIG_PATH if exists)
369
+	:type pkg_config_path: string, list of directories separated by colon
370
+	:param force_static: force usage of static libraries
371
+	:type force_static: bool default False
372
+	:param posix: usage of POSIX mode for shlex lexical analiysis library
373
+	:type posix: bool default True
374
 	"""
375
 
376
 	path = Utils.to_list(kw['path'])
377
@@ -334,6 +348,7 @@ def check_cfg(self, *k, **kw):
378
 	"""
379
 	Checks for configuration flags using a **-config**-like program (pkg-config, sdl-config, etc).
380
 	This wraps internal calls to :py:func:`waflib.Tools.c_config.validate_cfg` and :py:func:`waflib.Tools.c_config.exec_cfg`
381
+	so check exec_cfg parameters descriptions for more details on kw passed
382
 
383
 	A few examples::
384
 
385
@@ -1267,10 +1282,11 @@ def multicheck(self, *k, **kw):
386
 	tasks = []
387
 
388
 	id_to_task = {}
389
-	for dct in k:
390
+	for counter, dct in enumerate(k):
391
 		x = Task.classes['cfgtask'](bld=bld, env=None)
392
 		tasks.append(x)
393
 		x.args = dct
394
+		x.args['multicheck_counter'] = counter
395
 		x.bld = bld
396
 		x.conf = self
397
 		x.args = dct
398
diff --git third_party/waf/waflib/Tools/c_tests.py third_party/waf/waflib/Tools/c_tests.py
399
index 7a4094f2450..bdd186c6bc4 100644
400
--- third_party/waf/waflib/Tools/c_tests.py
401
+++ third_party/waf/waflib/Tools/c_tests.py
402
@@ -180,9 +180,15 @@ def check_large_file(self, **kw):
403
 ########################################################################################
404
 
405
 ENDIAN_FRAGMENT = '''
406
+#ifdef _MSC_VER
407
+#define testshlib_EXPORT __declspec(dllexport)
408
+#else
409
+#define testshlib_EXPORT
410
+#endif
411
+
412
 short int ascii_mm[] = { 0x4249, 0x4765, 0x6E44, 0x6961, 0x6E53, 0x7953, 0 };
413
 short int ascii_ii[] = { 0x694C, 0x5454, 0x656C, 0x6E45, 0x6944, 0x6E61, 0 };
414
-int use_ascii (int i) {
415
+int testshlib_EXPORT use_ascii (int i) {
416
 	return ascii_mm[i] + ascii_ii[i];
417
 }
418
 short int ebcdic_ii[] = { 0x89D3, 0xE3E3, 0x8593, 0x95C5, 0x89C4, 0x9581, 0 };
419
@@ -208,12 +214,12 @@ class grep_for_endianness(Task.Task):
420
 			return -1
421
 
422
 @feature('grep_for_endianness')
423
-@after_method('process_source')
424
+@after_method('apply_link')
425
 def grep_for_endianness_fun(self):
426
 	"""
427
 	Used by the endianness configuration test
428
 	"""
429
-	self.create_task('grep_for_endianness', self.compiled_tasks[0].outputs[0])
430
+	self.create_task('grep_for_endianness', self.link_task.outputs[0])
431
 
432
 @conf
433
 def check_endianness(self):
434
@@ -223,7 +229,8 @@ def check_endianness(self):
435
 	tmp = []
436
 	def check_msg(self):
437
 		return tmp[0]
438
-	self.check(fragment=ENDIAN_FRAGMENT, features='c grep_for_endianness',
439
+
440
+	self.check(fragment=ENDIAN_FRAGMENT, features='c cshlib grep_for_endianness',
441
 		msg='Checking for endianness', define='ENDIANNESS', tmp=tmp,
442
 		okmsg=check_msg, confcache=None)
443
 	return tmp[0]
444
diff --git third_party/waf/waflib/Tools/compiler_c.py third_party/waf/waflib/Tools/compiler_c.py
445
index 2dba3f82704..931dc57efec 100644
446
--- third_party/waf/waflib/Tools/compiler_c.py
447
+++ third_party/waf/waflib/Tools/compiler_c.py
448
@@ -37,7 +37,7 @@ from waflib.Logs import debug
449
 
450
 c_compiler = {
451
 'win32':  ['msvc', 'gcc', 'clang'],
452
-'cygwin': ['gcc'],
453
+'cygwin': ['gcc', 'clang'],
454
 'darwin': ['clang', 'gcc'],
455
 'aix':    ['xlc', 'gcc', 'clang'],
456
 'linux':  ['gcc', 'clang', 'icc'],
457
diff --git third_party/waf/waflib/Tools/compiler_cxx.py third_party/waf/waflib/Tools/compiler_cxx.py
458
index 1af65a226dc..09fca7e4dc6 100644
459
--- third_party/waf/waflib/Tools/compiler_cxx.py
460
+++ third_party/waf/waflib/Tools/compiler_cxx.py
461
@@ -38,7 +38,7 @@ from waflib.Logs import debug
462
 
463
 cxx_compiler = {
464
 'win32':  ['msvc', 'g++', 'clang++'],
465
-'cygwin': ['g++'],
466
+'cygwin': ['g++', 'clang++'],
467
 'darwin': ['clang++', 'g++'],
468
 'aix':    ['xlc++', 'g++', 'clang++'],
469
 'linux':  ['g++', 'clang++', 'icpc'],
470
diff --git third_party/waf/waflib/Tools/fc.py third_party/waf/waflib/Tools/fc.py
471
index fd4d39c90ae..7fbd76d3650 100644
472
--- third_party/waf/waflib/Tools/fc.py
473
+++ third_party/waf/waflib/Tools/fc.py
474
@@ -13,8 +13,8 @@ from waflib.TaskGen import extension
475
 from waflib.Configure import conf
476
 
477
 ccroot.USELIB_VARS['fc'] = set(['FCFLAGS', 'DEFINES', 'INCLUDES', 'FCPPFLAGS'])
478
-ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS'])
479
-ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS'])
480
+ccroot.USELIB_VARS['fcprogram_test'] = ccroot.USELIB_VARS['fcprogram'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'LDFLAGS'])
481
+ccroot.USELIB_VARS['fcshlib'] = set(['LIB', 'STLIB', 'LIBPATH', 'STLIBPATH', 'LINKFLAGS', 'RPATH', 'LINKDEPS', 'LDFLAGS'])
482
 ccroot.USELIB_VARS['fcstlib'] = set(['ARFLAGS', 'LINKDEPS'])
483
 
484
 @extension('.f','.F','.f90','.F90','.for','.FOR','.f95','.F95','.f03','.F03','.f08','.F08')
485
diff --git third_party/waf/waflib/Tools/irixcc.py third_party/waf/waflib/Tools/irixcc.py
486
index c3ae1ac915c..0335c13cb61 100644
487
--- third_party/waf/waflib/Tools/irixcc.py
488
+++ third_party/waf/waflib/Tools/irixcc.py
489
@@ -13,22 +13,11 @@ from waflib.Configure import conf
490
 @conf
491
 def find_irixcc(conf):
492
 	v = conf.env
493
-	cc = None
494
-	if v.CC:
495
-		cc = v.CC
496
-	elif 'CC' in conf.environ:
497
-		cc = conf.environ['CC']
498
-	if not cc:
499
-		cc = conf.find_program('cc', var='CC')
500
-	if not cc:
501
-		conf.fatal('irixcc was not found')
502
-
503
+	cc = conf.find_program('cc', var='CC')
504
 	try:
505
 		conf.cmd_and_log(cc + ['-version'])
506
 	except Errors.WafError:
507
 		conf.fatal('%r -version could not be executed' % cc)
508
-
509
-	v.CC = cc
510
 	v.CC_NAME = 'irix'
511
 
512
 @conf
513
@@ -57,7 +46,6 @@ def irixcc_common_flags(conf):
514
 
515
 def configure(conf):
516
 	conf.find_irixcc()
517
-	conf.find_cpp()
518
 	conf.find_ar()
519
 	conf.irixcc_common_flags()
520
 	conf.cc_load_tools()
521
diff --git third_party/waf/waflib/Tools/javaw.py third_party/waf/waflib/Tools/javaw.py
522
index ceb08c28c87..b7f5dd1f87f 100644
523
--- third_party/waf/waflib/Tools/javaw.py
524
+++ third_party/waf/waflib/Tools/javaw.py
525
@@ -251,7 +251,7 @@ def use_javac_files(self):
526
 					base_node = tg.path.get_bld()
527
 
528
 				self.use_lst.append(base_node.abspath())
529
-				self.javac_task.dep_nodes.extend([x for x in base_node.ant_glob(JAR_RE, remove=False, quiet=True)])
530
+				self.javac_task.dep_nodes.extend([dx for dx in base_node.ant_glob(JAR_RE, remove=False, quiet=True)])
531
 
532
 				for tsk in tg.tasks:
533
 					self.javac_task.set_run_after(tsk)
534
diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py
535
index 7c45a76ffd2..b1c8dd01285 100644
536
--- third_party/waf/waflib/Tools/python.py
537
+++ third_party/waf/waflib/Tools/python.py
538
@@ -620,7 +620,7 @@ def configure(conf):
539
 	v.PYO = getattr(Options.options, 'pyo', 1)
540
 
541
 	try:
542
-		v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import imp;print(imp.get_tag())"]).strip()
543
+		v.PYTAG = conf.cmd_and_log(conf.env.PYTHON + ['-c', "import sys\ntry:\n print(sys.implementation.cache_tag)\nexcept AttributeError:\n import imp\n print(imp.get_tag())\n"]).strip()
544
 	except Errors.WafError:
545
 		pass
546
 
547
diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py
548
index 287c25374a4..99e021bae61 100644
549
--- third_party/waf/waflib/Tools/qt5.py
550
+++ third_party/waf/waflib/Tools/qt5.py
551
@@ -482,8 +482,8 @@ def configure(self):
552
 		self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?')
553
 
554
 	# Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC?
555
-	frag = '#include <QApplication>\nint main(int argc, char **argv) {return 0;}\n'
556
-	uses = 'QT5CORE QT5WIDGETS QT5GUI'
557
+	frag = '#include <QMap>\nint main(int argc, char **argv) {QMap<int,int> m;return m.keys().size();}\n'
558
+	uses = 'QT5CORE'
559
 	for flag in [[], '-fPIE', '-fPIC', '-std=c++11' , ['-std=c++11', '-fPIE'], ['-std=c++11', '-fPIC']]:
560
 		msg = 'See if Qt files compile '
561
 		if flag:
562
@@ -499,7 +499,7 @@ def configure(self):
563
 
564
 	# FreeBSD does not add /usr/local/lib and the pkg-config files do not provide it either :-/
565
 	if Utils.unversioned_sys_platform() == 'freebsd':
566
-		frag = '#include <QApplication>\nint main(int argc, char **argv) { QApplication app(argc, argv); return NULL != (void*) (&app);}\n'
567
+		frag = '#include <QMap>\nint main(int argc, char **argv) {QMap<int,int> m;return m.keys().size();}\n'
568
 		try:
569
 			self.check(features='qt5 cxx cxxprogram', use=uses, fragment=frag, msg='Can we link Qt programs on FreeBSD directly?')
570
 		except self.errors.ConfigurationError:
571
diff --git third_party/waf/waflib/Utils.py third_party/waf/waflib/Utils.py
572
index 7472226da58..fc64fa05154 100644
573
--- third_party/waf/waflib/Utils.py
574
+++ third_party/waf/waflib/Utils.py
575
@@ -891,7 +891,7 @@ def run_prefork_process(cmd, kwargs, cargs):
576
 	"""
577
 	Delegates process execution to a pre-forked process instance.
578
 	"""
579
-	if not 'env' in kwargs:
580
+	if not kwargs.get('env'):
581
 		kwargs['env'] = dict(os.environ)
582
 	try:
583
 		obj = base64.b64encode(cPickle.dumps([cmd, kwargs, cargs]))
584
diff --git third_party/waf/waflib/extras/clang_compilation_database.py third_party/waf/waflib/extras/clang_compilation_database.py
585
index 4d9b5e275ae..ff71f22ecfd 100644
586
--- third_party/waf/waflib/extras/clang_compilation_database.py
587
+++ third_party/waf/waflib/extras/clang_compilation_database.py
588
@@ -1,6 +1,7 @@
589
 #!/usr/bin/env python
590
 # encoding: utf-8
591
 # Christoph Koke, 2013
592
+# Alibek Omarov, 2019
593
 
594
 """
595
 Writes the c and cpp compile commands into build/compile_commands.json
596
@@ -8,14 +9,23 @@ see http://clang.llvm.org/docs/JSONCompilationDatabase.html
597
 
598
 Usage:
599
 
600
-    def configure(conf):
601
-        conf.load('compiler_cxx')
602
-        ...
603
-        conf.load('clang_compilation_database')
604
+	Load this tool in `options` to be able to generate database
605
+	by request in command-line and before build:
606
+
607
+	$ waf clangdb
608
+
609
+	def options(opt):
610
+		opt.load('clang_compilation_database')
611
+
612
+	Otherwise, load only in `configure` to generate it always before build.
613
+
614
+	def configure(conf):
615
+		conf.load('compiler_cxx')
616
+		...
617
+		conf.load('clang_compilation_database')
618
 """
619
 
620
-import sys, os, json, shlex, pipes
621
-from waflib import Logs, TaskGen, Task
622
+from waflib import Logs, TaskGen, Task, Build, Scripting
623
 
624
 Task.Task.keep_last_cmd = True
625
 
626
@@ -23,63 +33,103 @@ Task.Task.keep_last_cmd = True
627
 @TaskGen.after_method('process_use')
628
 def collect_compilation_db_tasks(self):
629
 	"Add a compilation database entry for compiled tasks"
630
-	try:
631
-		clang_db = self.bld.clang_compilation_database_tasks
632
-	except AttributeError:
633
-		clang_db = self.bld.clang_compilation_database_tasks = []
634
-		self.bld.add_post_fun(write_compilation_database)
635
+	if not isinstance(self.bld, ClangDbContext):
636
+		return
637
 
638
 	tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y)
639
 	for task in getattr(self, 'compiled_tasks', []):
640
 		if isinstance(task, tup):
641
-			clang_db.append(task)
642
-
643
-def write_compilation_database(ctx):
644
-	"Write the clang compilation database as JSON"
645
-	database_file = ctx.bldnode.make_node('compile_commands.json')
646
-	Logs.info('Build commands will be stored in %s', database_file.path_from(ctx.path))
647
-	try:
648
-		root = json.load(database_file)
649
-	except IOError:
650
-		root = []
651
-	clang_db = dict((x['file'], x) for x in root)
652
-	for task in getattr(ctx, 'clang_compilation_database_tasks', []):
653
+			self.bld.clang_compilation_database_tasks.append(task)
654
+
655
+class ClangDbContext(Build.BuildContext):
656
+	'''generates compile_commands.json by request'''
657
+	cmd = 'clangdb'
658
+	clang_compilation_database_tasks = []
659
+
660
+	def write_compilation_database(self):
661
+		"""
662
+		Write the clang compilation database as JSON
663
+		"""
664
+		database_file = self.bldnode.make_node('compile_commands.json')
665
+		Logs.info('Build commands will be stored in %s', database_file.path_from(self.path))
666
 		try:
667
-			cmd = task.last_cmd
668
-		except AttributeError:
669
-			continue
670
-		directory = getattr(task, 'cwd', ctx.variant_dir)
671
-		f_node = task.inputs[0]
672
-		filename = os.path.relpath(f_node.abspath(), directory)
673
-		entry = {
674
-			"directory": directory,
675
-			"arguments": cmd,
676
-			"file": filename,
677
-		}
678
-		clang_db[filename] = entry
679
-	root = list(clang_db.values())
680
-	database_file.write(json.dumps(root, indent=2))
681
-
682
-# Override the runnable_status function to do a dummy/dry run when the file doesn't need to be compiled.
683
-# This will make sure compile_commands.json is always fully up to date.
684
-# Previously you could end up with a partial compile_commands.json if the build failed.
685
-for x in ('c', 'cxx'):
686
-	if x not in Task.classes:
687
-		continue
688
-
689
-	t = Task.classes[x]
690
-
691
-	def runnable_status(self):
692
-		def exec_command(cmd, **kw):
693
-			pass
694
-
695
-		run_status = self.old_runnable_status()
696
-		if run_status == Task.SKIP_ME:
697
-			setattr(self, 'old_exec_command', getattr(self, 'exec_command', None))
698
-			setattr(self, 'exec_command', exec_command)
699
-			self.run()
700
-			setattr(self, 'exec_command', getattr(self, 'old_exec_command', None))
701
-		return run_status
702
-
703
-	setattr(t, 'old_runnable_status', getattr(t, 'runnable_status', None))
704
-	setattr(t, 'runnable_status', runnable_status)
705
+			root = database_file.read_json()
706
+		except IOError:
707
+			root = []
708
+		clang_db = dict((x['file'], x) for x in root)
709
+		for task in self.clang_compilation_database_tasks:
710
+			try:
711
+				cmd = task.last_cmd
712
+			except AttributeError:
713
+				continue
714
+			f_node = task.inputs[0]
715
+			filename = f_node.path_from(task.get_cwd())
716
+			entry = {
717
+				"directory": task.get_cwd().abspath(),
718
+				"arguments": cmd,
719
+				"file": filename,
720
+			}
721
+			clang_db[filename] = entry
722
+		root = list(clang_db.values())
723
+		database_file.write_json(root)
724
+
725
+	def execute(self):
726
+		"""
727
+		Build dry run
728
+		"""
729
+		self.restore()
730
+
731
+		if not self.all_envs:
732
+			self.load_envs()
733
+
734
+		self.recurse([self.run_dir])
735
+		self.pre_build()
736
+
737
+		# we need only to generate last_cmd, so override
738
+		# exec_command temporarily
739
+		def exec_command(self, *k, **kw):
740
+			return 0
741
+
742
+		for g in self.groups:
743
+			for tg in g:
744
+				try:
745
+					f = tg.post
746
+				except AttributeError:
747
+					pass
748
+				else:
749
+					f()
750
+
751
+				if isinstance(tg, Task.Task):
752
+					lst = [tg]
753
+				else: lst = tg.tasks
754
+				for tsk in lst:
755
+					tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y)
756
+					if isinstance(tsk, tup):
757
+						old_exec = tsk.exec_command
758
+						tsk.exec_command = exec_command
759
+						tsk.run()
760
+						tsk.exec_command = old_exec
761
+
762
+		self.write_compilation_database()
763
+
764
+EXECUTE_PATCHED = False
765
+def patch_execute():
766
+	global EXECUTE_PATCHED
767
+
768
+	if EXECUTE_PATCHED:
769
+		return
770
+
771
+	def new_execute_build(self):
772
+		"""
773
+		Invoke clangdb command before build
774
+		"""
775
+		if self.cmd.startswith('build'):
776
+			Scripting.run_command('clangdb')
777
+
778
+		old_execute_build(self)
779
+
780
+	old_execute_build = getattr(Build.BuildContext, 'execute_build', None)
781
+	setattr(Build.BuildContext, 'execute_build', new_execute_build)
782
+	EXECUTE_PATCHED = True
783
+
784
+patch_execute()
785
diff --git third_party/waf/waflib/extras/doxygen.py third_party/waf/waflib/extras/doxygen.py
786
index 20cd9e1a852..de75bc2738a 100644
787
--- third_party/waf/waflib/extras/doxygen.py
788
+++ third_party/waf/waflib/extras/doxygen.py
789
@@ -69,6 +69,7 @@ def parse_doxy(txt):
790
 class doxygen(Task.Task):
791
 	vars  = ['DOXYGEN', 'DOXYFLAGS']
792
 	color = 'BLUE'
793
+	ext_in = [ '.py', '.c', '.h', '.java', '.pb.cc' ]
794
 
795
 	def runnable_status(self):
796
 		'''
797
diff --git third_party/waf/waflib/extras/gccdeps.py third_party/waf/waflib/extras/gccdeps.py
798
index bfabe72e6fd..c3a809e252a 100644
799
--- third_party/waf/waflib/extras/gccdeps.py
800
+++ third_party/waf/waflib/extras/gccdeps.py
801
@@ -27,7 +27,7 @@ if not c_preproc.go_absolute:
802
 	gccdeps_flags = ['-MMD']
803
 
804
 # Third-party tools are allowed to add extra names in here with append()
805
-supported_compilers = ['gcc', 'icc', 'clang']
806
+supported_compilers = ['gas', 'gcc', 'icc', 'clang']
807
 
808
 def scan(self):
809
 	if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS:
810
@@ -175,14 +175,14 @@ def wrap_compiled_task(classname):
811
 	derived_class.scan = scan
812
 	derived_class.sig_implicit_deps = sig_implicit_deps
813
 
814
-for k in ('c', 'cxx'):
815
+for k in ('asm', 'c', 'cxx'):
816
 	if k in Task.classes:
817
 		wrap_compiled_task(k)
818
 
819
 @before_method('process_source')
820
 @feature('force_gccdeps')
821
 def force_gccdeps(self):
822
-	self.env.ENABLE_GCCDEPS = ['c', 'cxx']
823
+	self.env.ENABLE_GCCDEPS = ['asm', 'c', 'cxx']
824
 
825
 def configure(conf):
826
 	# in case someone provides a --enable-gccdeps command-line option
827
@@ -191,6 +191,15 @@ def configure(conf):
828
 
829
 	global gccdeps_flags
830
 	flags = conf.env.GCCDEPS_FLAGS or gccdeps_flags
831
+	if conf.env.ASM_NAME in supported_compilers:
832
+		try:
833
+			conf.check(fragment='', features='asm force_gccdeps', asflags=flags, compile_filename='test.S', msg='Checking for asm flags %r' % ''.join(flags))
834
+		except Errors.ConfigurationError:
835
+			pass
836
+		else:
837
+			conf.env.append_value('ASFLAGS', flags)
838
+			conf.env.append_unique('ENABLE_GCCDEPS', 'asm')
839
+
840
 	if conf.env.CC_NAME in supported_compilers:
841
 		try:
842
 			conf.check(fragment='int main() { return 0; }', features='c force_gccdeps', cflags=flags, msg='Checking for c flags %r' % ''.join(flags))
843
diff --git third_party/waf/waflib/extras/javatest.py third_party/waf/waflib/extras/javatest.py
844
index 979b8d8242d..76d40edf250 100755
845
--- third_party/waf/waflib/extras/javatest.py
846
+++ third_party/waf/waflib/extras/javatest.py
847
@@ -1,6 +1,6 @@
848
 #! /usr/bin/env python
849
 # encoding: utf-8
850
-# Federico Pellegrin, 2017 (fedepell)
851
+# Federico Pellegrin, 2019 (fedepell)
852
 
853
 """
854
 Provides Java Unit test support using :py:class:`waflib.Tools.waf_unit_test.utest`
855
@@ -11,6 +11,10 @@ standard waf unit test environment. It has been tested with TestNG and JUnit
856
 but should be easily expandable to other frameworks given the flexibility of
857
 ut_str provided by the standard waf unit test environment.
858
 
859
+The extra takes care also of managing non-java dependencies (ie. C/C++ libraries
860
+using JNI or Python modules via JEP) and setting up the environment needed to run
861
+them.
862
+
863
 Example usage:
864
 
865
 def options(opt):
866
@@ -20,15 +24,15 @@ def configure(conf):
867
 	conf.load('java javatest')
868
 
869
 def build(bld):
870
-	
871
+
872
 	[ ... mainprog is built here ... ]
873
 
874
 	bld(features = 'javac javatest',
875
-		srcdir     = 'test/', 
876
-		outdir     = 'test', 
877
+		srcdir     = 'test/',
878
+		outdir     = 'test',
879
 		sourcepath = ['test'],
880
-		classpath  = [ 'src' ], 
881
-		basedir    = 'test', 
882
+		classpath  = [ 'src' ],
883
+		basedir    = 'test',
884
 		use = ['JAVATEST', 'mainprog'], # mainprog is the program being tested in src/
885
 		ut_str = 'java -cp ${CLASSPATH} ${JTRUNNER} ${SRC}',
886
 		jtest_source = bld.path.ant_glob('test/*.xml'),
887
@@ -53,10 +57,107 @@ The runner class presence on the system is checked for at configuration stage.
888
 """
889
 
890
 import os
891
-from waflib import Task, TaskGen, Options
892
+from waflib import Task, TaskGen, Options, Errors, Utils, Logs
893
+from waflib.Tools import ccroot
894
+
895
+JAR_RE = '**/*'
896
+
897
+def _process_use_rec(self, name):
898
+	"""
899
+	Recursively process ``use`` for task generator with name ``name``..
900
+	Used by javatest_process_use.
901
+	"""
902
+	if name in self.javatest_use_not or name in self.javatest_use_seen:
903
+		return
904
+	try:
905
+		tg = self.bld.get_tgen_by_name(name)
906
+	except Errors.WafError:
907
+		self.javatest_use_not.add(name)
908
+		return
909
+
910
+	self.javatest_use_seen.append(name)
911
+	tg.post()
912
+
913
+	for n in self.to_list(getattr(tg, 'use', [])):
914
+		_process_use_rec(self, n)
915
+
916
+@TaskGen.feature('javatest')
917
+@TaskGen.after_method('process_source', 'apply_link', 'use_javac_files')
918
+def javatest_process_use(self):
919
+	"""
920
+	Process the ``use`` attribute which contains a list of task generator names and store
921
+	paths that later is used to populate the unit test runtime environment.
922
+	"""
923
+	self.javatest_use_not = set()
924
+	self.javatest_use_seen = []
925
+	self.javatest_libpaths = [] # strings or Nodes
926
+	self.javatest_pypaths = [] # strings or Nodes
927
+	self.javatest_dep_nodes = []
928
+
929
+	names = self.to_list(getattr(self, 'use', []))
930
+	for name in names:
931
+		_process_use_rec(self, name)
932
+
933
+	def extend_unique(lst, varlst):
934
+		ext = []
935
+		for x in varlst:
936
+			if x not in lst:
937
+				ext.append(x)
938
+		lst.extend(ext)
939
+
940
+	# Collect type specific info needed to construct a valid runtime environment
941
+	# for the test.
942
+	for name in self.javatest_use_seen:
943
+		tg = self.bld.get_tgen_by_name(name)
944
+
945
+		# Python-Java embedding crosstools such as JEP
946
+		if 'py' in tg.features:
947
+			# Python dependencies are added to PYTHONPATH
948
+			pypath = getattr(tg, 'install_from', tg.path)
949
+
950
+			if 'buildcopy' in tg.features:
951
+				# Since buildcopy is used we assume that PYTHONPATH in build should be used,
952
+				# not source
953
+				extend_unique(self.javatest_pypaths, [pypath.get_bld().abspath()])
954
+
955
+				# Add buildcopy output nodes to dependencies
956
+				extend_unique(self.javatest_dep_nodes, [o for task in getattr(tg, 'tasks', []) for o in getattr(task, 'outputs', [])])
957
+			else:
958
+				# If buildcopy is not used, depend on sources instead
959
+				extend_unique(self.javatest_dep_nodes, tg.source)
960
+				extend_unique(self.javatest_pypaths, [pypath.abspath()])
961
+
962
+
963
+		if getattr(tg, 'link_task', None):
964
+			# For tasks with a link_task (C, C++, D et.c.) include their library paths:
965
+			if not isinstance(tg.link_task, ccroot.stlink_task):
966
+				extend_unique(self.javatest_dep_nodes, tg.link_task.outputs)
967
+				extend_unique(self.javatest_libpaths, tg.link_task.env.LIBPATH)
968
+
969
+				if 'pyext' in tg.features:
970
+					# If the taskgen is extending Python we also want to add the interpreter libpath.
971
+					extend_unique(self.javatest_libpaths, tg.link_task.env.LIBPATH_PYEXT)
972
+				else:
973
+					# Only add to libpath if the link task is not a Python extension
974
+					extend_unique(self.javatest_libpaths, [tg.link_task.outputs[0].parent.abspath()])
975
+
976
+		if 'javac' in tg.features or 'jar' in tg.features:
977
+			if hasattr(tg, 'jar_task'):
978
+				# For Java JAR tasks depend on generated JAR
979
+				extend_unique(self.javatest_dep_nodes, tg.jar_task.outputs)
980
+			else:
981
+				# For Java non-JAR ones we need to glob generated files (Java output files are not predictable)
982
+				if hasattr(tg, 'outdir'):
983
+					base_node = tg.outdir
984
+				else:
985
+					base_node = tg.path.get_bld()
986
+
987
+				self.javatest_dep_nodes.extend([dx for dx in base_node.ant_glob(JAR_RE, remove=False, quiet=True)])
988
+
989
+
990
 
991
 @TaskGen.feature('javatest')
992
-@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath')
993
+@TaskGen.after_method('apply_java', 'use_javac_files', 'set_classpath', 'javatest_process_use')
994
 def make_javatest(self):
995
 	"""
996
 	Creates a ``utest`` task with a populated environment for Java Unit test execution
997
@@ -65,6 +166,9 @@ def make_javatest(self):
998
 	tsk = self.create_task('utest')
999
 	tsk.set_run_after(self.javac_task)
1000
 
1001
+	# Dependencies from recursive use analysis
1002
+	tsk.dep_nodes.extend(self.javatest_dep_nodes)
1003
+
1004
 	# Put test input files as waf_unit_test relies on that for some prints and log generation
1005
 	# If jtest_source is there, this is specially useful for passing XML for TestNG
1006
 	# that contain test specification, use that as inputs, otherwise test sources
1007
@@ -97,6 +201,21 @@ def make_javatest(self):
1008
 
1009
 	if not hasattr(self, 'ut_env'):
1010
 		self.ut_env = dict(os.environ)
1011
+		def add_paths(var, lst):
1012
+			# Add list of paths to a variable, lst can contain strings or nodes
1013
+			lst = [ str(n) for n in lst ]
1014
+			Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst)
1015
+			self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '')
1016
+
1017
+		add_paths('PYTHONPATH', self.javatest_pypaths)
1018
+
1019
+		if Utils.is_win32:
1020
+			add_paths('PATH', self.javatest_libpaths)
1021
+		elif Utils.unversioned_sys_platform() == 'darwin':
1022
+			add_paths('DYLD_LIBRARY_PATH', self.javatest_libpaths)
1023
+			add_paths('LD_LIBRARY_PATH', self.javatest_libpaths)
1024
+		else:
1025
+			add_paths('LD_LIBRARY_PATH', self.javatest_libpaths)
1026
 
1027
 def configure(ctx):
1028
 	cp = ctx.env.CLASSPATH or '.'
1029
diff --git third_party/waf/waflib/extras/msvc_pdb.py third_party/waf/waflib/extras/msvc_pdb.py
1030
new file mode 100644
1031
index 00000000000..077656b4f7e
1032
--- /dev/null
1033
+++ third_party/waf/waflib/extras/msvc_pdb.py
1034
@@ -0,0 +1,46 @@
1035
+#!/usr/bin/env python
1036
+# encoding: utf-8
1037
+# Rafaël Kooi 2019
1038
+
1039
+from waflib import TaskGen
1040
+
1041
+@TaskGen.feature('c', 'cxx', 'fc')
1042
+@TaskGen.after_method('propagate_uselib_vars')
1043
+def add_pdb_per_object(self):
1044
+	"""For msvc/fortran, specify a unique compile pdb per object, to work
1045
+	around LNK4099. Flags are updated with a unique /Fd flag based on the
1046
+	task output name. This is separate from the link pdb.
1047
+	"""
1048
+	if not hasattr(self, 'compiled_tasks'):
1049
+		return
1050
+
1051
+	link_task = getattr(self, 'link_task', None)
1052
+
1053
+	for task in self.compiled_tasks:
1054
+		if task.inputs and task.inputs[0].name.lower().endswith('.rc'):
1055
+			continue
1056
+
1057
+		add_pdb = False
1058
+		for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'):
1059
+			# several languages may be used at once
1060
+			for flag in task.env[flagname]:
1061
+				if flag[1:].lower() == 'zi':
1062
+					add_pdb = True
1063
+					break
1064
+
1065
+		if add_pdb:
1066
+			node = task.outputs[0].change_ext('.pdb')
1067
+			pdb_flag = '/Fd:' + node.abspath()
1068
+
1069
+			for flagname in ('CFLAGS', 'CXXFLAGS', 'FCFLAGS'):
1070
+				buf = [pdb_flag]
1071
+				for flag in task.env[flagname]:
1072
+					if flag[1:3] == 'Fd' or flag[1:].lower() == 'fs' or flag[1:].lower() == 'mp':
1073
+						continue
1074
+					buf.append(flag)
1075
+				task.env[flagname] = buf
1076
+
1077
+			if link_task and not node in link_task.dep_nodes:
1078
+				link_task.dep_nodes.append(node)
1079
+			if not node in task.outputs:
1080
+				task.outputs.append(node)
1081
diff --git third_party/waf/waflib/extras/pytest.py third_party/waf/waflib/extras/pytest.py
1082
index 7dd5a1a087a..fc9ad1c23e4 100644
1083
--- third_party/waf/waflib/extras/pytest.py
1084
+++ third_party/waf/waflib/extras/pytest.py
1085
@@ -40,6 +40,8 @@ the following environment variables for the `pytest` test runner:
1086
 
1087
    - `pytest_libpath` attribute is used to manually specify additional linker paths.
1088
 
1089
+3. Java class search path (CLASSPATH) of any Java/Javalike dependency
1090
+
1091
 Note: `pytest` cannot automatically determine the correct `PYTHONPATH` for `pyext` taskgens
1092
       because the extension might be part of a Python package or used standalone:
1093
 
1094
@@ -119,6 +121,7 @@ def pytest_process_use(self):
1095
 	self.pytest_use_seen = []
1096
 	self.pytest_paths = [] # strings or Nodes
1097
 	self.pytest_libpaths = [] # strings or Nodes
1098
+	self.pytest_javapaths = [] # strings or Nodes
1099
 	self.pytest_dep_nodes = []
1100
 
1101
 	names = self.to_list(getattr(self, 'use', []))
1102
@@ -157,6 +160,17 @@ def pytest_process_use(self):
1103
 				extend_unique(self.pytest_dep_nodes, tg.source)
1104
 				extend_unique(self.pytest_paths, [pypath.abspath()])
1105
 
1106
+		if 'javac' in tg.features:
1107
+			# If a JAR is generated point to that, otherwise to directory
1108
+			if getattr(tg, 'jar_task', None):
1109
+				extend_unique(self.pytest_javapaths, [tg.jar_task.outputs[0].abspath()])
1110
+			else:
1111
+				extend_unique(self.pytest_javapaths, [tg.path.get_bld()])
1112
+
1113
+			# And add respective dependencies if present
1114
+			if tg.use_lst:
1115
+				extend_unique(self.pytest_javapaths, tg.use_lst)
1116
+
1117
 		if getattr(tg, 'link_task', None):
1118
 			# For tasks with a link_task (C, C++, D et.c.) include their library paths:
1119
 			if not isinstance(tg.link_task, ccroot.stlink_task):
1120
@@ -212,8 +226,9 @@ def make_pytest(self):
1121
 			Logs.debug("ut: %s: Adding paths %s=%s", self, var, lst)
1122
 			self.ut_env[var] = os.pathsep.join(lst) + os.pathsep + self.ut_env.get(var, '')
1123
 
1124
-		# Prepend dependency paths to PYTHONPATH and LD_LIBRARY_PATH
1125
+		# Prepend dependency paths to PYTHONPATH, CLASSPATH and LD_LIBRARY_PATH
1126
 		add_paths('PYTHONPATH', self.pytest_paths)
1127
+		add_paths('CLASSPATH', self.pytest_javapaths)
1128
 
1129
 		if Utils.is_win32:
1130
 			add_paths('PATH', self.pytest_libpaths)
1131
diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py
1132
new file mode 100644
1133
index 00000000000..8b9567faf14
1134
--- /dev/null
1135
+++ third_party/waf/waflib/extras/wafcache.py
1136
@@ -0,0 +1,524 @@
1137
+#! /usr/bin/env python
1138
+# encoding: utf-8
1139
+# Thomas Nagy, 2019 (ita)
1140
+
1141
+"""
1142
+Filesystem-based cache system to share and re-use build artifacts
1143
+
1144
+Cache access operations (copy to and from) are delegated to
1145
+independent pre-forked worker subprocesses.
1146
+
1147
+The following environment variables may be set:
1148
+* WAFCACHE: several possibilities:
1149
+  - File cache:
1150
+    absolute path of the waf cache (~/.cache/wafcache_user,
1151
+    where `user` represents the currently logged-in user)
1152
+  - URL to a cache server, for example:
1153
+    export WAFCACHE=http://localhost:8080/files/
1154
+    in that case, GET/POST requests are made to urls of the form
1155
+    http://localhost:8080/files/000000000/0 (cache management is then up to the server)
1156
+  - GCS or S3 bucket
1157
+    gs://my-bucket/
1158
+    s3://my-bucket/
1159
+* WAFCACHE_NO_PUSH: if set, disables pushing to the cache
1160
+* WAFCACHE_VERBOSITY: if set, displays more detailed cache operations
1161
+
1162
+File cache specific options:
1163
+  Files are copied using hard links by default; if the cache is located
1164
+  onto another partition, the system switches to file copies instead.
1165
+* WAFCACHE_TRIM_MAX_FOLDER: maximum amount of tasks to cache (1M)
1166
+* WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB)
1167
+* WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try
1168
+                                   and trim the cache (3 minutess)
1169
+Usage::
1170
+
1171
+	def build(bld):
1172
+		bld.load('wafcache')
1173
+		...
1174
+
1175
+To troubleshoot::
1176
+
1177
+	waf clean build --zones=wafcache
1178
+"""
1179
+
1180
+import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3
1181
+try:
1182
+	import subprocess32 as subprocess
1183
+except ImportError:
1184
+	import subprocess
1185
+
1186
+base_cache = os.path.expanduser('~/.cache/')
1187
+if not os.path.isdir(base_cache):
1188
+	base_cache = '/tmp/'
1189
+default_wafcache_dir = os.path.join(base_cache, 'wafcache_' + getpass.getuser())
1190
+
1191
+CACHE_DIR = os.environ.get('WAFCACHE', default_wafcache_dir)
1192
+TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000))
1193
+EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3))
1194
+EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10))
1195
+WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0
1196
+WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0
1197
+OK = "ok"
1198
+
1199
+try:
1200
+	import cPickle
1201
+except ImportError:
1202
+	import pickle as cPickle
1203
+
1204
+if __name__ != '__main__':
1205
+	from waflib import Task, Logs, Utils, Build
1206
+
1207
+def can_retrieve_cache(self):
1208
+	"""
1209
+	New method for waf Task classes
1210
+	"""
1211
+	if not self.outputs:
1212
+		return False
1213
+
1214
+	self.cached = False
1215
+
1216
+	sig = self.signature()
1217
+	ssig = Utils.to_hex(self.uid() + sig)
1218
+
1219
+	files_to = [node.abspath() for node in self.outputs]
1220
+	err = cache_command(ssig, [], files_to)
1221
+	if err.startswith(OK):
1222
+		if WAFCACHE_VERBOSITY:
1223
+			Logs.pprint('CYAN', '  Fetched %r from cache' % files_to)
1224
+		else:
1225
+			Logs.debug('wafcache: fetched %r from cache', files_to)
1226
+	else:
1227
+		if WAFCACHE_VERBOSITY:
1228
+			Logs.pprint('YELLOW', '  No cache entry %s' % files_to)
1229
+		else:
1230
+			Logs.debug('wafcache: No cache entry %s: %s', files_to, err)
1231
+		return False
1232
+
1233
+	self.cached = True
1234
+	return True
1235
+
1236
+def put_files_cache(self):
1237
+	"""
1238
+	New method for waf Task classes
1239
+	"""
1240
+	if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs:
1241
+		return
1242
+
1243
+	bld = self.generator.bld
1244
+	sig = self.signature()
1245
+	ssig = Utils.to_hex(self.uid() + sig)
1246
+
1247
+	files_from = [node.abspath() for node in self.outputs]
1248
+	err = cache_command(ssig, files_from, [])
1249
+
1250
+	if err.startswith(OK):
1251
+		if WAFCACHE_VERBOSITY:
1252
+			Logs.pprint('CYAN', '  Successfully uploaded %s to cache' % files_from)
1253
+		else:
1254
+			Logs.debug('wafcache: Successfully uploaded %r to cache', files_from)
1255
+	else:
1256
+		if WAFCACHE_VERBOSITY:
1257
+			Logs.pprint('RED', '  Error caching step results %s: %s' % (files_from, err))
1258
+		else:
1259
+			Logs.debug('wafcache: Error caching results %s: %s', files_from, err)
1260
+
1261
+	bld.task_sigs[self.uid()] = self.cache_sig
1262
+
1263
+def hash_env_vars(self, env, vars_lst):
1264
+	"""
1265
+	Reimplement BuildContext.hash_env_vars so that the resulting hash does not depend on local paths
1266
+	"""
1267
+	if not env.table:
1268
+		env = env.parent
1269
+		if not env:
1270
+			return Utils.SIG_NIL
1271
+
1272
+	idx = str(id(env)) + str(vars_lst)
1273
+	try:
1274
+		cache = self.cache_env
1275
+	except AttributeError:
1276
+		cache = self.cache_env = {}
1277
+	else:
1278
+		try:
1279
+			return self.cache_env[idx]
1280
+		except KeyError:
1281
+			pass
1282
+
1283
+	v = str([env[a] for a in vars_lst])
1284
+	v = v.replace(self.srcnode.abspath().__repr__()[:-1], '')
1285
+	m = Utils.md5()
1286
+	m.update(v.encode())
1287
+	ret = m.digest()
1288
+
1289
+	Logs.debug('envhash: %r %r', ret, v)
1290
+
1291
+	cache[idx] = ret
1292
+
1293
+	return ret
1294
+
1295
+def uid(self):
1296
+	"""
1297
+	Reimplement Task.uid() so that the signature does not depend on local paths
1298
+	"""
1299
+	try:
1300
+		return self.uid_
1301
+	except AttributeError:
1302
+		m = Utils.md5()
1303
+		src = self.generator.bld.srcnode
1304
+		up = m.update
1305
+		up(self.__class__.__name__.encode())
1306
+		for x in self.inputs + self.outputs:
1307
+			up(x.path_from(src).encode())
1308
+		self.uid_ = m.digest()
1309
+		return self.uid_
1310
+
1311
+
1312
+def make_cached(cls):
1313
+	"""
1314
+	Enable the waf cache for a given task class
1315
+	"""
1316
+	if getattr(cls, 'nocache', None) or getattr(cls, 'has_cache', False):
1317
+		return
1318
+
1319
+	m1 = getattr(cls, 'run', None)
1320
+	def run(self):
1321
+		if getattr(self, 'nocache', False):
1322
+			return m1(self)
1323
+		if self.can_retrieve_cache():
1324
+			return 0
1325
+		return m1(self)
1326
+	cls.run = run
1327
+
1328
+	m2 = getattr(cls, 'post_run', None)
1329
+	def post_run(self):
1330
+		if getattr(self, 'nocache', False):
1331
+			return m2(self)
1332
+		ret = m2(self)
1333
+		self.put_files_cache()
1334
+		if hasattr(self, 'chmod'):
1335
+			for node in self.outputs:
1336
+				os.chmod(node.abspath(), self.chmod)
1337
+		return ret
1338
+	cls.post_run = post_run
1339
+	cls.has_cache = True
1340
+
1341
+process_pool = []
1342
+def get_process():
1343
+	"""
1344
+	Returns a worker process that can process waf cache commands
1345
+	The worker process is assumed to be returned to the process pool when unused
1346
+	"""
1347
+	try:
1348
+		return process_pool.pop()
1349
+	except IndexError:
1350
+		filepath = os.path.dirname(os.path.abspath(__file__)) + os.sep + 'wafcache.py'
1351
+		cmd = [sys.executable, '-c', Utils.readf(filepath)]
1352
+		return subprocess.Popen(cmd, stdout=subprocess.PIPE, stdin=subprocess.PIPE, bufsize=0)
1353
+
1354
+def atexit_pool():
1355
+	for k in process_pool:
1356
+		try:
1357
+			os.kill(k.pid, 9)
1358
+		except OSError:
1359
+			pass
1360
+		else:
1361
+			k.wait()
1362
+atexit.register(atexit_pool)
1363
+
1364
+def build(bld):
1365
+	"""
1366
+	Called during the build process to enable file caching
1367
+	"""
1368
+	if process_pool:
1369
+		# already called once
1370
+		return
1371
+
1372
+	for x in range(bld.jobs):
1373
+		process_pool.append(get_process())
1374
+
1375
+	Task.Task.can_retrieve_cache = can_retrieve_cache
1376
+	Task.Task.put_files_cache = put_files_cache
1377
+	Task.Task.uid = uid
1378
+	Build.BuildContext.hash_env_vars = hash_env_vars
1379
+	for x in reversed(list(Task.classes.values())):
1380
+		make_cached(x)
1381
+
1382
+def cache_command(sig, files_from, files_to):
1383
+	"""
1384
+	Create a command for cache worker processes, returns a pickled
1385
+	base64-encoded tuple containing the task signature, a list of files to
1386
+	cache and a list of files files to get from cache (one of the lists
1387
+	is assumed to be empty)
1388
+	"""
1389
+	proc = get_process()
1390
+
1391
+	obj = base64.b64encode(cPickle.dumps([sig, files_from, files_to]))
1392
+	proc.stdin.write(obj)
1393
+	proc.stdin.write('\n'.encode())
1394
+	proc.stdin.flush()
1395
+	obj = proc.stdout.readline()
1396
+	if not obj:
1397
+		raise OSError('Preforked sub-process %r died' % proc.pid)
1398
+	process_pool.append(proc)
1399
+	return cPickle.loads(base64.b64decode(obj))
1400
+
1401
+try:
1402
+	copyfun = os.link
1403
+except NameError:
1404
+	copyfun = shutil.copy2
1405
+
1406
+def atomic_copy(orig, dest):
1407
+	"""
1408
+	Copy files to the cache, the operation is atomic for a given file
1409
+	"""
1410
+	global copyfun
1411
+	tmp = dest + '.tmp'
1412
+	up = os.path.dirname(dest)
1413
+	try:
1414
+		os.makedirs(up)
1415
+	except OSError:
1416
+		pass
1417
+
1418
+	try:
1419
+		copyfun(orig, tmp)
1420
+	except OSError as e:
1421
+		if e.errno == errno.EXDEV:
1422
+			copyfun = shutil.copy2
1423
+			copyfun(orig, tmp)
1424
+		else:
1425
+			raise
1426
+	os.rename(tmp, dest)
1427
+
1428
+def lru_trim():
1429
+	"""
1430
+	the cache folders take the form:
1431
+	`CACHE_DIR/0b/0b180f82246d726ece37c8ccd0fb1cde2650d7bfcf122ec1f169079a3bfc0ab9`
1432
+	they are listed in order of last access, and then removed
1433
+	until the amount of folders is within TRIM_MAX_FOLDERS and the total space
1434
+	taken by files is less than EVICT_MAX_BYTES
1435
+	"""
1436
+	lst = []
1437
+	for up in os.listdir(CACHE_DIR):
1438
+		if len(up) == 2:
1439
+			sub = os.path.join(CACHE_DIR, up)
1440
+			for hval in os.listdir(sub):
1441
+				path = os.path.join(sub, hval)
1442
+
1443
+				size = 0
1444
+				for fname in os.listdir(path):
1445
+					size += os.lstat(os.path.join(path, fname)).st_size
1446
+				lst.append((os.stat(path).st_mtime, size, path))
1447
+
1448
+	lst.sort(key=lambda x: x[0])
1449
+	lst.reverse()
1450
+
1451
+	tot = sum(x[1] for x in lst)
1452
+	while tot > EVICT_MAX_BYTES or len(lst) > TRIM_MAX_FOLDERS:
1453
+		_, tmp_size, path = lst.pop()
1454
+		tot -= tmp_size
1455
+
1456
+		tmp = path + '.tmp'
1457
+		try:
1458
+			shutil.rmtree(tmp)
1459
+		except OSError:
1460
+			pass
1461
+		try:
1462
+			os.rename(path, tmp)
1463
+		except OSError:
1464
+			sys.stderr.write('Could not rename %r to %r' % (path, tmp))
1465
+		else:
1466
+			try:
1467
+				shutil.rmtree(tmp)
1468
+			except OSError:
1469
+				sys.stderr.write('Could not remove %r' % tmp)
1470
+	sys.stderr.write("Cache trimmed: %r bytes in %r folders left\n" % (tot, len(lst)))
1471
+
1472
+
1473
+def lru_evict():
1474
+	"""
1475
+	Reduce the cache size
1476
+	"""
1477
+	lockfile = os.path.join(CACHE_DIR, 'all.lock')
1478
+	try:
1479
+		st = os.stat(lockfile)
1480
+	except EnvironmentError as e:
1481
+		if e.errno == errno.ENOENT:
1482
+			with open(lockfile, 'w') as f:
1483
+				f.write('')
1484
+			return
1485
+		else:
1486
+			raise
1487
+
1488
+	if st.st_mtime < time.time() - EVICT_INTERVAL_MINUTES * 60:
1489
+		# check every EVICT_INTERVAL_MINUTES minutes if the cache is too big
1490
+		# OCLOEXEC is unnecessary because no processes are spawned
1491
+		fd = os.open(lockfile, os.O_RDWR | os.O_CREAT, 0o755)
1492
+		try:
1493
+			try:
1494
+				fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
1495
+			except EnvironmentError:
1496
+				sys.stderr.write('another process is running!\n')
1497
+				pass
1498
+			else:
1499
+				# now dow the actual cleanup
1500
+				lru_trim()
1501
+				os.utime(lockfile, None)
1502
+		finally:
1503
+			os.close(fd)
1504
+
1505
+class netcache(object):
1506
+	def __init__(self):
1507
+		self.http = urllib3.PoolManager()
1508
+
1509
+	def url_of(self, sig, i):
1510
+		return "%s/%s/%s" % (CACHE_DIR, sig, i)
1511
+
1512
+	def upload(self, file_path, sig, i):
1513
+		url = self.url_of(sig, i)
1514
+		with open(file_path, 'rb') as f:
1515
+			file_data = f.read()
1516
+		r = self.http.request('POST', url, timeout=60,
1517
+			fields={ 'file': ('%s/%s' % (sig, i), file_data), })
1518
+		if r.status >= 400:
1519
+			raise OSError("Invalid status %r %r" % (url, r.status))
1520
+
1521
+	def download(self, file_path, sig, i):
1522
+		url = self.url_of(sig, i)
1523
+		with self.http.request('GET', url, preload_content=False, timeout=60) as inf:
1524
+			if inf.status >= 400:
1525
+				raise OSError("Invalid status %r %r" % (url, inf.status))
1526
+			with open(file_path, 'wb') as out:
1527
+				shutil.copyfileobj(inf, out)
1528
+
1529
+	def copy_to_cache(self, sig, files_from, files_to):
1530
+		try:
1531
+			for i, x in enumerate(files_from):
1532
+				if not os.path.islink(x):
1533
+					self.upload(x, sig, i)
1534
+		except Exception:
1535
+			return traceback.format_exc()
1536
+		return OK
1537
+
1538
+	def copy_from_cache(self, sig, files_from, files_to):
1539
+		try:
1540
+			for i, x in enumerate(files_to):
1541
+				self.download(x, sig, i)
1542
+		except Exception:
1543
+			return traceback.format_exc()
1544
+		return OK
1545
+
1546
+class fcache(object):
1547
+	def __init__(self):
1548
+		if not os.path.exists(CACHE_DIR):
1549
+			os.makedirs(CACHE_DIR)
1550
+		if not os.path.exists(CACHE_DIR):
1551
+			raise ValueError('Could not initialize the cache directory')
1552
+
1553
+	def copy_to_cache(self, sig, files_from, files_to):
1554
+		"""
1555
+		Copy files to the cache, existing files are overwritten,
1556
+		and the copy is atomic only for a given file, not for all files
1557
+		that belong to a given task object
1558
+		"""
1559
+		try:
1560
+			for i, x in enumerate(files_from):
1561
+				dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i))
1562
+				atomic_copy(x, dest)
1563
+		except Exception:
1564
+			return traceback.format_exc()
1565
+		else:
1566
+			# attempt trimming if caching was successful:
1567
+			# we may have things to trim!
1568
+			lru_evict()
1569
+		return OK
1570
+
1571
+	def copy_from_cache(self, sig, files_from, files_to):
1572
+		"""
1573
+		Copy files from the cache
1574
+		"""
1575
+		try:
1576
+			for i, x in enumerate(files_to):
1577
+				orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i))
1578
+				atomic_copy(orig, x)
1579
+
1580
+			# success! update the cache time
1581
+			os.utime(os.path.join(CACHE_DIR, sig[:2], sig), None)
1582
+		except Exception:
1583
+			return traceback.format_exc()
1584
+		return OK
1585
+
1586
+class bucket_cache(object):
1587
+	def bucket_copy(self, source, target):
1588
+		if CACHE_DIR.startswith('s3://'):
1589
+			cmd = ['aws', 's3', 'cp', source, target]
1590
+		else:
1591
+			cmd = ['gsutil', 'cp', source, target]
1592
+		proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
1593
+		out, err = proc.communicate()
1594
+		if proc.returncode:
1595
+			raise OSError('Error copy %r to %r using: %r (exit %r):\n  out:%s\n  err:%s' % (
1596
+				source, target, cmd, proc.returncode, out.decode(), err.decode()))
1597
+
1598
+	def copy_to_cache(self, sig, files_from, files_to):
1599
+		try:
1600
+			for i, x in enumerate(files_from):
1601
+				dest = os.path.join(CACHE_DIR, sig[:2], sig, str(i))
1602
+				self.bucket_copy(x, dest)
1603
+		except Exception:
1604
+			return traceback.format_exc()
1605
+		return OK
1606
+
1607
+	def copy_from_cache(self, sig, files_from, files_to):
1608
+		try:
1609
+			for i, x in enumerate(files_to):
1610
+				orig = os.path.join(CACHE_DIR, sig[:2], sig, str(i))
1611
+				self.bucket_copy(orig, x)
1612
+		except EnvironmentError:
1613
+			return traceback.format_exc()
1614
+		return OK
1615
+
1616
+def loop(service):
1617
+	"""
1618
+	This function is run when this file is run as a standalone python script,
1619
+	it assumes a parent process that will communicate the commands to it
1620
+	as pickled-encoded tuples (one line per command)
1621
+
1622
+	The commands are to copy files to the cache or copy files from the
1623
+	cache to a target destination
1624
+	"""
1625
+	# one operation is performed at a single time by a single process
1626
+	# therefore stdin never has more than one line
1627
+	txt = sys.stdin.readline().strip()
1628
+	if not txt:
1629
+		# parent process probably ended
1630
+		sys.exit(1)
1631
+	ret = OK
1632
+
1633
+	[sig, files_from, files_to] = cPickle.loads(base64.b64decode(txt))
1634
+	if files_from:
1635
+		# TODO return early when pushing files upstream
1636
+		ret = service.copy_to_cache(sig, files_from, files_to)
1637
+	elif files_to:
1638
+		# the build process waits for workers to (possibly) obtain files from the cache
1639
+		ret = service.copy_from_cache(sig, files_from, files_to)
1640
+	else:
1641
+		ret = "Invalid command"
1642
+
1643
+	obj = base64.b64encode(cPickle.dumps(ret))
1644
+	sys.stdout.write(obj.decode())
1645
+	sys.stdout.write('\n')
1646
+	sys.stdout.flush()
1647
+
1648
+if __name__ == '__main__':
1649
+	if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://'):
1650
+		service = bucket_cache()
1651
+	elif CACHE_DIR.startswith('http'):
1652
+		service = netcache()
1653
+	else:
1654
+		service = fcache()
1655
+	while 1:
1656
+		try:
1657
+			loop(service)
1658
+		except KeyboardInterrupt:
1659
+			break
1660
+
1661
-- 
1662
2.37.3
1663
(-)b/net/samba413/files/patch-waf-2.0.21 (+703 lines)
Added Link Here
1
From 6718b5e6d059e5668fc538be802ebd9fbe5ce9af Mon Sep 17 00:00:00 2001
2
From: Stefan Metzmacher <metze@samba.org>
3
Date: Wed, 25 Nov 2020 16:29:06 +0100
4
Subject: [PATCH] waf: upgrade to 2.0.21
5
6
This commit message was wrong:
7
8
    commit 5fc3a71d0f54b176d3cb2e399718d0468507e797
9
    Author: David Mulder <dmulder@suse.com>
10
    Date:   Mon Aug 24 13:12:46 2020 -0600
11
12
        waf: upgrade to 2.0.20
13
14
        This contain an important change:
15
        "Fix gccdeps.scan() returning nodes that no longer exist on disk."
16
        https://gitlab.com/ita1024/waf/-/merge_requests/2293
17
18
        Signed-off-by: David Mulder <dmulder@suse.com>
19
        Reviewed-by: Stefan Metzmacher <metze@samba.org>
20
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
21
22
The fix was in in waf master, but not included in 2.0.20,
23
but it's now included in 2.0.21.
24
25
Signed-off-by: Stefan Metzmacher <metze@samba.org>
26
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
27
---
28
 buildtools/bin/waf                            |  2 +-
29
 buildtools/wafsamba/wafsamba.py               |  2 +-
30
 third_party/waf/waflib/Build.py               |  6 ++-
31
 third_party/waf/waflib/Context.py             |  8 ++--
32
 third_party/waf/waflib/Tools/asm.py           |  5 +-
33
 third_party/waf/waflib/Tools/c_config.py      |  1 +
34
 third_party/waf/waflib/Tools/msvc.py          |  8 +++-
35
 third_party/waf/waflib/Tools/qt5.py           | 26 +++++++++--
36
 third_party/waf/waflib/Tools/waf_unit_test.py | 10 +++-
37
 third_party/waf/waflib/extras/boost.py        |  5 +-
38
 .../waf/waflib/extras/c_dumbpreproc.py        |  2 +-
39
 third_party/waf/waflib/extras/doxygen.py      |  4 +-
40
 .../waf/waflib/extras/file_to_object.py       |  9 +++-
41
 third_party/waf/waflib/extras/gccdeps.py      | 21 +++++++--
42
 third_party/waf/waflib/extras/msvcdeps.py     | 27 +++++++++--
43
 third_party/waf/waflib/extras/pch.py          |  4 +-
44
 third_party/waf/waflib/extras/sphinx.py       | 40 ++++++++++++----
45
 third_party/waf/waflib/extras/wafcache.py     | 46 +++++++++++++++----
46
 third_party/waf/waflib/extras/xcode6.py       | 18 ++++----
47
 19 files changed, 181 insertions(+), 63 deletions(-)
48
49
diff --git buildtools/bin/waf buildtools/bin/waf
50
index feabe25d131..041450fc131 100755
51
--- buildtools/bin/waf
52
+++ buildtools/bin/waf
53
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
54
 
55
 import os, sys, inspect
56
 
57
-VERSION="2.0.20"
58
+VERSION="2.0.21"
59
 REVISION="x"
60
 GIT="x"
61
 INSTALL="x"
62
diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py
63
index 9dd6d05b91b..d1baa3b4940 100644
64
--- buildtools/wafsamba/wafsamba.py
65
+++ buildtools/wafsamba/wafsamba.py
66
@@ -38,7 +38,7 @@ LIB_PATH="shared"
67
 
68
 os.environ['PYTHONUNBUFFERED'] = '1'
69
 
70
-if Context.HEXVERSION not in (0x2001400,):
71
+if Context.HEXVERSION not in (0x2001500,):
72
     Logs.error('''
73
 Please use the version of waf that comes with Samba, not
74
 a system installed version. See http://wiki.samba.org/index.php/Waf
75
diff --git third_party/waf/waflib/Build.py third_party/waf/waflib/Build.py
76
index 39f0991918b..52837618577 100644
77
--- third_party/waf/waflib/Build.py
78
+++ third_party/waf/waflib/Build.py
79
@@ -753,10 +753,12 @@ class BuildContext(Context.Context):
80
 		else:
81
 			ln = self.launch_node()
82
 			if ln.is_child_of(self.bldnode):
83
-				Logs.warn('Building from the build directory, forcing --targets=*')
84
+				if Logs.verbose > 1:
85
+					Logs.warn('Building from the build directory, forcing --targets=*')
86
 				ln = self.srcnode
87
 			elif not ln.is_child_of(self.srcnode):
88
-				Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath())
89
+				if Logs.verbose > 1:
90
+					Logs.warn('CWD %s is not under %s, forcing --targets=* (run distclean?)', ln.abspath(), self.srcnode.abspath())
91
 				ln = self.srcnode
92
 
93
 			def is_post(tg, ln):
94
diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py
95
index 3f1b4fa48ab..0ce9df6e91f 100644
96
--- third_party/waf/waflib/Context.py
97
+++ third_party/waf/waflib/Context.py
98
@@ -18,13 +18,13 @@ else:
99
 	import imp
100
 
101
 # the following 3 constants are updated on each new release (do not touch)
102
-HEXVERSION=0x2001400
103
+HEXVERSION=0x2001500
104
 """Constant updated on new releases"""
105
 
106
-WAFVERSION="2.0.20"
107
+WAFVERSION="2.0.21"
108
 """Constant updated on new releases"""
109
 
110
-WAFREVISION="668769470956da8c5b60817cb8884cd7d0f87cd4"
111
+WAFREVISION="edde20a6425a5c3eb6b47d5f3f5c4fbc93fed5f4"
112
 """Git revision when the waf version is updated"""
113
 
114
 WAFNAME="waf"
115
@@ -530,7 +530,7 @@ class Context(ctx):
116
 		"""
117
 		Prints a configuration message of the form ``msg: result``.
118
 		The second part of the message will be in colors. The output
119
-		can be disabled easly by setting ``in_msg`` to a positive value::
120
+		can be disabled easily by setting ``in_msg`` to a positive value::
121
 
122
 			def configure(conf):
123
 				self.in_msg = 1
124
diff --git third_party/waf/waflib/Tools/asm.py third_party/waf/waflib/Tools/asm.py
125
index a57e83bb5ec..1d34ddaca7f 100644
126
--- third_party/waf/waflib/Tools/asm.py
127
+++ third_party/waf/waflib/Tools/asm.py
128
@@ -56,13 +56,11 @@ class asm(Task.Task):
129
 	Compiles asm files by gas/nasm/yasm/...
130
 	"""
131
 	color = 'BLUE'
132
-	run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${DEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}'
133
+	run_str = '${AS} ${ASFLAGS} ${ASMPATH_ST:INCPATHS} ${ASMDEFINES_ST:DEFINES} ${AS_SRC_F}${SRC} ${AS_TGT_F}${TGT}'
134
 
135
 	def scan(self):
136
 		if self.env.ASM_NAME == 'gas':
137
 			return c_preproc.scan(self)
138
-			Logs.warn('There is no dependency scanner for Nasm!')
139
-			return  [[], []]
140
 		elif self.env.ASM_NAME == 'nasm':
141
 			Logs.warn('The Nasm dependency scanner is incomplete!')
142
 
143
@@ -106,3 +104,4 @@ class asmstlib(stlink_task):
144
 
145
 def configure(conf):
146
 	conf.env.ASMPATH_ST = '-I%s'
147
+	conf.env.ASMDEFINES_ST = '-D%s'
148
diff --git third_party/waf/waflib/Tools/c_config.py third_party/waf/waflib/Tools/c_config.py
149
index 98187fac2e2..03b6bf61bc0 100644
150
--- third_party/waf/waflib/Tools/c_config.py
151
+++ third_party/waf/waflib/Tools/c_config.py
152
@@ -68,6 +68,7 @@ MACRO_TO_DEST_CPU = {
153
 '__s390__'    : 's390',
154
 '__sh__'      : 'sh',
155
 '__xtensa__'  : 'xtensa',
156
+'__e2k__'     : 'e2k',
157
 }
158
 
159
 @conf
160
diff --git third_party/waf/waflib/Tools/msvc.py third_party/waf/waflib/Tools/msvc.py
161
index f169c7f441b..37233be8242 100644
162
--- third_party/waf/waflib/Tools/msvc.py
163
+++ third_party/waf/waflib/Tools/msvc.py
164
@@ -99,7 +99,13 @@ all_icl_platforms = [ ('intel64', 'amd64'), ('em64t', 'amd64'), ('ia32', 'x86'),
165
 """List of icl platforms"""
166
 
167
 def options(opt):
168
-	opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default='')
169
+	default_ver = ''
170
+	vsver = os.getenv('VSCMD_VER')
171
+	if vsver:
172
+		m = re.match(r'(^\d+\.\d+).*', vsver)
173
+		if m:
174
+			default_ver = 'msvc %s' % m.group(1)
175
+	opt.add_option('--msvc_version', type='string', help = 'msvc version, eg: "msvc 10.0,msvc 9.0"', default=default_ver)
176
 	opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='')
177
 	opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy')
178
 
179
diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py
180
index 99e021bae61..cff2028174f 100644
181
--- third_party/waf/waflib/Tools/qt5.py
182
+++ third_party/waf/waflib/Tools/qt5.py
183
@@ -57,7 +57,23 @@ A few options (--qt{dir,bin,...}) and environment variables
184
 (QT5_{ROOT,DIR,MOC,UIC,XCOMPILE}) allow finer tuning of the tool,
185
 tool path selection, etc; please read the source for more info.
186
 
187
-The detection uses pkg-config on Linux by default. To force static library detection use:
188
+The detection uses pkg-config on Linux by default. The list of
189
+libraries to be requested to pkg-config is formulated by scanning
190
+in the QTLIBS directory (that can be passed via --qtlibs or by
191
+setting the environment variable QT5_LIBDIR otherwise is derived
192
+by querying qmake for QT_INSTALL_LIBS directory) for shared/static
193
+libraries present.
194
+Alternatively the list of libraries to be requested via pkg-config
195
+can be set using the qt5_vars attribute, ie:
196
+
197
+      conf.qt5_vars = ['Qt5Core', 'Qt5Gui', 'Qt5Widgets', 'Qt5Test'];
198
+
199
+This can speed up configuration phase if needed libraries are
200
+known beforehand, can improve detection on systems with a
201
+sparse QT5 libraries installation (ie. NIX) and can improve
202
+detection of some header-only Qt modules (ie. Qt5UiPlugin).
203
+
204
+To force static library detection use:
205
 QT5_XCOMPILE=1 QT5_FORCE_STATIC=1 waf configure
206
 """
207
 
208
@@ -466,6 +482,9 @@ def configure(self):
209
 
210
 	The detection uses the program ``pkg-config`` through :py:func:`waflib.Tools.config_c.check_cfg`
211
 	"""
212
+	if 'COMPILER_CXX' not in self.env:
213
+		self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?')
214
+
215
 	self.find_qt5_binaries()
216
 	self.set_qt5_libs_dir()
217
 	self.set_qt5_libs_to_check()
218
@@ -478,9 +497,6 @@ def configure(self):
219
 	if not has_xml:
220
 		Logs.error('No xml.sax support was found, rcc dependencies will be incomplete!')
221
 
222
-	if 'COMPILER_CXX' not in self.env:
223
-		self.fatal('No CXX compiler defined: did you forget to configure compiler_cxx first?')
224
-
225
 	# Qt5 may be compiled with '-reduce-relocations' which requires dependent programs to have -fPIE or -fPIC?
226
 	frag = '#include <QMap>\nint main(int argc, char **argv) {QMap<int,int> m;return m.keys().size();}\n'
227
 	uses = 'QT5CORE'
228
@@ -637,7 +653,7 @@ def set_qt5_libs_dir(self):
229
 		except Errors.WafError:
230
 			qtdir = self.cmd_and_log(env.QMAKE + ['-query', 'QT_INSTALL_PREFIX']).strip()
231
 			qtlibs = os.path.join(qtdir, 'lib')
232
-	self.msg('Found the Qt5 libraries in', qtlibs)
233
+	self.msg('Found the Qt5 library path', qtlibs)
234
 	env.QTLIBS = qtlibs
235
 
236
 @conf
237
diff --git third_party/waf/waflib/Tools/waf_unit_test.py third_party/waf/waflib/Tools/waf_unit_test.py
238
index 6ff6f72739f..dc66fe9c184 100644
239
--- third_party/waf/waflib/Tools/waf_unit_test.py
240
+++ third_party/waf/waflib/Tools/waf_unit_test.py
241
@@ -97,6 +97,7 @@ def make_interpreted_test(self):
242
 		if isinstance(v, str):
243
 			v = v.split(os.pathsep)
244
 		self.ut_env[k] = os.pathsep.join(p + v)
245
+	self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env])
246
 
247
 @feature('test')
248
 @after_method('apply_link', 'process_use')
249
@@ -108,7 +109,8 @@ def make_test(self):
250
 	tsk = self.create_task('utest', self.link_task.outputs)
251
 	if getattr(self, 'ut_str', None):
252
 		self.ut_run, lst = Task.compile_fun(self.ut_str, shell=getattr(self, 'ut_shell', False))
253
-		tsk.vars = lst + tsk.vars
254
+		tsk.vars = tsk.vars + lst
255
+		self.env.append_value('UT_DEPS', self.ut_str)
256
 
257
 	self.handle_ut_cwd('ut_cwd')
258
 
259
@@ -139,6 +141,10 @@ def make_test(self):
260
 	if not hasattr(self, 'ut_cmd'):
261
 		self.ut_cmd = getattr(Options.options, 'testcmd', False)
262
 
263
+	self.env.append_value('UT_DEPS', str(self.ut_cmd))
264
+	self.env.append_value('UT_DEPS', self.ut_paths)
265
+	self.env.append_value('UT_DEPS', ['%r%r' % (key, self.ut_env[key]) for key in self.ut_env])
266
+
267
 @taskgen_method
268
 def add_test_results(self, tup):
269
 	"""Override and return tup[1] to interrupt the build immediately if a test does not run"""
270
@@ -159,7 +165,7 @@ class utest(Task.Task):
271
 	"""
272
 	color = 'PINK'
273
 	after = ['vnum', 'inst']
274
-	vars = []
275
+	vars = ['UT_DEPS']
276
 
277
 	def runnable_status(self):
278
 		"""
279
diff --git third_party/waf/waflib/extras/boost.py third_party/waf/waflib/extras/boost.py
280
index c2aaaa938a2..93b312a1e6e 100644
281
--- third_party/waf/waflib/extras/boost.py
282
+++ third_party/waf/waflib/extras/boost.py
283
@@ -270,10 +270,12 @@ def boost_get_libs(self, *k, **kw):
284
 				return file
285
 		return None
286
 
287
+	# extensions from Tools.ccroot.lib_patterns
288
+	wo_ext = re.compile(r"\.(a|so|lib|dll|dylib)(\.[0-9\.]+)?$")
289
 	def format_lib_name(name):
290
 		if name.startswith('lib') and self.env.CC_NAME != 'msvc':
291
 			name = name[3:]
292
-		return name[:name.rfind('.')]
293
+		return wo_ext.sub("", name)
294
 
295
 	def match_libs(lib_names, is_static):
296
 		libs = []
297
@@ -522,4 +524,3 @@ def install_boost(self):
298
 		except:
299
 			continue
300
 install_boost.done = False
301
-
302
diff --git third_party/waf/waflib/extras/c_dumbpreproc.py third_party/waf/waflib/extras/c_dumbpreproc.py
303
index ce9e1a400b9..1fdd5c364ae 100644
304
--- third_party/waf/waflib/extras/c_dumbpreproc.py
305
+++ third_party/waf/waflib/extras/c_dumbpreproc.py
306
@@ -66,7 +66,7 @@ class dumb_parser(parser):
307
 			if x == c_preproc.POPFILE:
308
 				self.currentnode_stack.pop()
309
 				continue
310
-			self.tryfind(y)
311
+			self.tryfind(y, env=env)
312
 
313
 c_preproc.c_parser = dumb_parser
314
 
315
diff --git third_party/waf/waflib/extras/doxygen.py third_party/waf/waflib/extras/doxygen.py
316
index de75bc2738a..0fda70361f3 100644
317
--- third_party/waf/waflib/extras/doxygen.py
318
+++ third_party/waf/waflib/extras/doxygen.py
319
@@ -208,10 +208,10 @@ def process_doxy(self):
320
 		self.bld.fatal('doxygen file %s not found' % self.doxyfile)
321
 
322
 	# the task instance
323
-	dsk = self.create_task('doxygen', node)
324
+	dsk = self.create_task('doxygen', node, always_run=getattr(self, 'always', False))
325
 
326
 	if getattr(self, 'doxy_tar', None):
327
-		tsk = self.create_task('tar')
328
+		tsk = self.create_task('tar', always_run=getattr(self, 'always', False))
329
 		tsk.input_tasks = [dsk]
330
 		tsk.set_outputs(self.path.find_or_declare(self.doxy_tar))
331
 		if self.doxy_tar.endswith('bz2'):
332
diff --git third_party/waf/waflib/extras/file_to_object.py third_party/waf/waflib/extras/file_to_object.py
333
index 1393b511d63..13d2aef37df 100644
334
--- third_party/waf/waflib/extras/file_to_object.py
335
+++ third_party/waf/waflib/extras/file_to_object.py
336
@@ -31,7 +31,7 @@ Known issues:
337
 
338
 """
339
 
340
-import os
341
+import os, sys
342
 from waflib import Task, TaskGen, Errors
343
 
344
 def filename_c_escape(x):
345
@@ -95,12 +95,17 @@ class file_to_object_c(Task.Task):
346
 
347
 		name = "_binary_" + "".join(name)
348
 
349
+		def char_to_num(ch):
350
+			if sys.version_info[0] < 3:
351
+				return ord(ch)
352
+			return ch
353
+
354
 		data = self.inputs[0].read('rb')
355
 		lines, line = [], []
356
 		for idx_byte, byte in enumerate(data):
357
 			line.append(byte)
358
 			if len(line) > 15 or idx_byte == size-1:
359
-				lines.append(", ".join(("0x%02x" % ord(x)) for x in line))
360
+				lines.append(", ".join(("0x%02x" % char_to_num(x)) for x in line))
361
 				line = []
362
 		data = ",\n ".join(lines)
363
 
364
diff --git third_party/waf/waflib/extras/gccdeps.py third_party/waf/waflib/extras/gccdeps.py
365
index c3a809e252a..1fc9373489a 100644
366
--- third_party/waf/waflib/extras/gccdeps.py
367
+++ third_party/waf/waflib/extras/gccdeps.py
368
@@ -163,10 +163,25 @@ def post_run(self):
369
 def sig_implicit_deps(self):
370
 	if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS:
371
 		return super(self.derived_gccdeps, self).sig_implicit_deps()
372
+	bld = self.generator.bld
373
+
374
 	try:
375
-		return Task.Task.sig_implicit_deps(self)
376
-	except Errors.WafError:
377
-		return Utils.SIG_NIL
378
+		return self.compute_sig_implicit_deps()
379
+	except Errors.TaskNotReady:
380
+		raise ValueError("Please specify the build order precisely with gccdeps (asm/c/c++ tasks)")
381
+	except EnvironmentError:
382
+		# If a file is renamed, assume the dependencies are stale and must be recalculated
383
+		for x in bld.node_deps.get(self.uid(), []):
384
+			if not x.is_bld() and not x.exists():
385
+				try:
386
+					del x.parent.children[x.name]
387
+				except KeyError:
388
+					pass
389
+
390
+	key = self.uid()
391
+	bld.node_deps[key] = []
392
+	bld.raw_deps[key] = []
393
+	return Utils.SIG_NIL
394
 
395
 def wrap_compiled_task(classname):
396
 	derived_class = type(classname, (Task.classes[classname],), {})
397
diff --git third_party/waf/waflib/extras/msvcdeps.py third_party/waf/waflib/extras/msvcdeps.py
398
index 873a4193150..52985dce058 100644
399
--- third_party/waf/waflib/extras/msvcdeps.py
400
+++ third_party/waf/waflib/extras/msvcdeps.py
401
@@ -150,11 +150,25 @@ def scan(self):
402
 def sig_implicit_deps(self):
403
 	if self.env.CC_NAME not in supported_compilers:
404
 		return super(self.derived_msvcdeps, self).sig_implicit_deps()
405
+	bld = self.generator.bld
406
 
407
 	try:
408
-		return Task.Task.sig_implicit_deps(self)
409
-	except Errors.WafError:
410
-		return Utils.SIG_NIL
411
+		return self.compute_sig_implicit_deps()
412
+	except Errors.TaskNotReady:
413
+		raise ValueError("Please specify the build order precisely with msvcdeps (c/c++ tasks)")
414
+	except EnvironmentError:
415
+		# If a file is renamed, assume the dependencies are stale and must be recalculated
416
+		for x in bld.node_deps.get(self.uid(), []):
417
+			if not x.is_bld() and not x.exists():
418
+				try:
419
+					del x.parent.children[x.name]
420
+				except KeyError:
421
+					pass
422
+
423
+	key = self.uid()
424
+	bld.node_deps[key] = []
425
+	bld.raw_deps[key] = []
426
+	return Utils.SIG_NIL
427
 
428
 def exec_command(self, cmd, **kw):
429
 	if self.env.CC_NAME not in supported_compilers:
430
@@ -211,11 +225,14 @@ def exec_command(self, cmd, **kw):
431
 			# get one from the exception object
432
 			ret = getattr(e, 'returncode', 1)
433
 
434
+		Logs.debug('msvcdeps: Running for: %s' % self.inputs[0])
435
 		for line in raw_out.splitlines():
436
 			if line.startswith(INCLUDE_PATTERN):
437
-				inc_path = line[len(INCLUDE_PATTERN):].strip()
438
+				# Only strip whitespace after log to preserve
439
+				# dependency structure in debug output
440
+				inc_path = line[len(INCLUDE_PATTERN):]
441
 				Logs.debug('msvcdeps: Regex matched %s', inc_path)
442
-				self.msvcdeps_paths.append(inc_path)
443
+				self.msvcdeps_paths.append(inc_path.strip())
444
 			else:
445
 				out.append(line)
446
 
447
diff --git third_party/waf/waflib/extras/pch.py third_party/waf/waflib/extras/pch.py
448
index 103e752838c..b44c7a2e8fd 100644
449
--- third_party/waf/waflib/extras/pch.py
450
+++ third_party/waf/waflib/extras/pch.py
451
@@ -90,7 +90,7 @@ def apply_pch(self):
452
 
453
 	if getattr(self, 'name', None):
454
 		try:
455
-			task = self.bld.pch_tasks["%s.%s" % (self.name, self.idx)]
456
+			task = self.bld.pch_tasks[self.name]
457
 			self.bld.fatal("Duplicated 'pch' task with name %r" % "%s.%s" % (self.name, self.idx))
458
 		except KeyError:
459
 			pass
460
@@ -104,7 +104,7 @@ def apply_pch(self):
461
 
462
 	self.pch_task = task
463
 	if getattr(self, 'name', None):
464
-		self.bld.pch_tasks["%s.%s" % (self.name, self.idx)] = task
465
+		self.bld.pch_tasks[self.name] = task
466
 
467
 @TaskGen.feature('cxx')
468
 @TaskGen.after_method('process_source', 'propagate_uselib_vars')
469
diff --git third_party/waf/waflib/extras/sphinx.py third_party/waf/waflib/extras/sphinx.py
470
index ce11110e634..71d1028393b 100644
471
--- third_party/waf/waflib/extras/sphinx.py
472
+++ third_party/waf/waflib/extras/sphinx.py
473
@@ -20,7 +20,7 @@ def build(bld):
474
 
475
 from waflib.Node import Node
476
 from waflib import Utils
477
-from waflib.Task import Task
478
+from waflib import Task
479
 from waflib.TaskGen import feature, after_method
480
 
481
 
482
@@ -55,13 +55,9 @@ def build_sphinx(self):
483
     sphinx_build_task.set_outputs(self.path.get_bld())
484
 
485
     # the sphinx-build results are in <build + output_format> directory
486
-    sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT)
487
-    sphinx_output_directory.mkdir()
488
+    self.sphinx_output_directory = self.path.get_bld().make_node(self.env.SPHINX_OUTPUT_FORMAT)
489
+    self.sphinx_output_directory.mkdir()
490
     Utils.def_attrs(self, install_path=get_install_path(self))
491
-    self.add_install_files(install_to=self.install_path,
492
-                           install_from=sphinx_output_directory.ant_glob('**/*'),
493
-                           cwd=sphinx_output_directory,
494
-                           relative_trick=True)
495
 
496
 
497
 def get_install_path(tg):
498
@@ -73,9 +69,37 @@ def get_install_path(tg):
499
         return tg.env.DOCDIR
500
 
501
 
502
-class SphinxBuildingTask(Task):
503
+class SphinxBuildingTask(Task.Task):
504
     color = 'BOLD'
505
     run_str = '${SPHINX_BUILD} -M ${SPHINX_OUTPUT_FORMAT} ${SRC} ${TGT} ${SPHINX_OPTIONS}'
506
 
507
     def keyword(self):
508
         return 'Compiling (%s)' % self.env.SPHINX_OUTPUT_FORMAT
509
+
510
+    def runnable_status(self):
511
+
512
+        for x in self.run_after:
513
+            if not x.hasrun:
514
+                return Task.ASK_LATER
515
+
516
+        self.signature()
517
+        ret = Task.Task.runnable_status(self)
518
+        if ret == Task.SKIP_ME:
519
+            # in case the files were removed
520
+            self.add_install()
521
+        return ret
522
+
523
+
524
+    def post_run(self):
525
+        self.add_install()
526
+        return Task.Task.post_run(self)
527
+
528
+
529
+    def add_install(self):
530
+        nodes = self.generator.sphinx_output_directory.ant_glob('**/*', quiet=True)
531
+        self.outputs += nodes
532
+        self.generator.add_install_files(install_to=self.generator.install_path,
533
+                                         install_from=nodes,
534
+                                         postpone=False,
535
+                                         cwd=self.generator.sphinx_output_directory,
536
+                                         relative_trick=True)
537
diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py
538
index 8b9567faf14..088fd0d098d 100644
539
--- third_party/waf/waflib/extras/wafcache.py
540
+++ third_party/waf/waflib/extras/wafcache.py
541
@@ -16,10 +16,19 @@ The following environment variables may be set:
542
   - URL to a cache server, for example:
543
     export WAFCACHE=http://localhost:8080/files/
544
     in that case, GET/POST requests are made to urls of the form
545
-    http://localhost:8080/files/000000000/0 (cache management is then up to the server)
546
-  - GCS or S3 bucket
547
-    gs://my-bucket/
548
-    s3://my-bucket/
549
+    http://localhost:8080/files/000000000/0 (cache management is delegated to the server)
550
+  - GCS, S3 or MINIO bucket
551
+    gs://my-bucket/    (uses gsutil command line tool or WAFCACHE_CMD)
552
+    s3://my-bucket/    (uses aws command line tool or WAFCACHE_CMD)
553
+    minio://my-bucket/ (uses mc command line tool or WAFCACHE_CMD)
554
+* WAFCACHE_CMD: bucket upload/download command, for example:
555
+    WAFCACHE_CMD="gsutil cp %{SRC} %{TGT}"
556
+  Note that the WAFCACHE bucket value is used for the source or destination
557
+  depending on the operation (upload or download). For example, with:
558
+    WAFCACHE="gs://mybucket/"
559
+  the following commands may be run:
560
+    gsutil cp build/myprogram  gs://mybucket/aa/aaaaa/1
561
+    gsutil cp gs://mybucket/bb/bbbbb/2 build/somefile
562
 * WAFCACHE_NO_PUSH: if set, disables pushing to the cache
563
 * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations
564
 
565
@@ -30,6 +39,7 @@ File cache specific options:
566
 * WAFCACHE_EVICT_MAX_BYTES: maximum amount of cache size in bytes (10GB)
567
 * WAFCACHE_EVICT_INTERVAL_MINUTES: minimum time interval to try
568
                                    and trim the cache (3 minutess)
569
+
570
 Usage::
571
 
572
 	def build(bld):
573
@@ -41,7 +51,7 @@ To troubleshoot::
574
 	waf clean build --zones=wafcache
575
 """
576
 
577
-import atexit, base64, errno, fcntl, getpass, os, shutil, sys, time, traceback, urllib3
578
+import atexit, base64, errno, fcntl, getpass, os, re, shutil, sys, time, traceback, urllib3, shlex
579
 try:
580
 	import subprocess32 as subprocess
581
 except ImportError:
582
@@ -53,6 +63,7 @@ if not os.path.isdir(base_cache):
583
 default_wafcache_dir = os.path.join(base_cache, 'wafcache_' + getpass.getuser())
584
 
585
 CACHE_DIR = os.environ.get('WAFCACHE', default_wafcache_dir)
586
+WAFCACHE_CMD = os.environ.get('WAFCACHE_CMD')
587
 TRIM_MAX_FOLDERS = int(os.environ.get('WAFCACHE_TRIM_MAX_FOLDER', 1000000))
588
 EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3))
589
 EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10))
590
@@ -60,6 +71,8 @@ WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0
591
 WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0
592
 OK = "ok"
593
 
594
+re_waf_cmd = re.compile('(?P<src>%{SRC})|(?P<tgt>%{TGT})')
595
+
596
 try:
597
 	import cPickle
598
 except ImportError:
599
@@ -233,8 +246,9 @@ def build(bld):
600
 		# already called once
601
 		return
602
 
603
-	for x in range(bld.jobs):
604
-		process_pool.append(get_process())
605
+	# pre-allocation
606
+	processes = [get_process() for x in range(bld.jobs)]
607
+	process_pool.extend(processes)
608
 
609
 	Task.Task.can_retrieve_cache = can_retrieve_cache
610
 	Task.Task.put_files_cache = put_files_cache
611
@@ -449,10 +463,20 @@ class fcache(object):
612
 
613
 class bucket_cache(object):
614
 	def bucket_copy(self, source, target):
615
-		if CACHE_DIR.startswith('s3://'):
616
+		if WAFCACHE_CMD:
617
+			def replacer(match):
618
+				if match.group('src'):
619
+					return source
620
+				elif match.group('tgt'):
621
+					return target
622
+			cmd = [re_waf_cmd.sub(replacer, x) for x in shlex.split(WAFCACHE_CMD)]
623
+		elif CACHE_DIR.startswith('s3://'):
624
 			cmd = ['aws', 's3', 'cp', source, target]
625
-		else:
626
+		elif CACHE_DIR.startswith('gs://'):
627
 			cmd = ['gsutil', 'cp', source, target]
628
+		else:
629
+			cmd = ['mc', 'cp', source, target]
630
+
631
 		proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
632
 		out, err = proc.communicate()
633
 		if proc.returncode:
634
@@ -510,7 +534,9 @@ def loop(service):
635
 	sys.stdout.flush()
636
 
637
 if __name__ == '__main__':
638
-	if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://'):
639
+	if CACHE_DIR.startswith('s3://') or CACHE_DIR.startswith('gs://') or CACHE_DIR.startswith('minio://'):
640
+		if CACHE_DIR.startswith('minio://'):
641
+			CACHE_DIR = CACHE_DIR[8:]   # minio doesn't need the protocol part, uses config aliases
642
 		service = bucket_cache()
643
 	elif CACHE_DIR.startswith('http'):
644
 		service = netcache()
645
diff --git third_party/waf/waflib/extras/xcode6.py third_party/waf/waflib/extras/xcode6.py
646
index 91bbff181ec..c5b309120c9 100644
647
--- third_party/waf/waflib/extras/xcode6.py
648
+++ third_party/waf/waflib/extras/xcode6.py
649
@@ -99,7 +99,7 @@ env.PROJ_CONFIGURATION = {
650
 		...
651
 	}
652
 	'Release': {
653
-		'ARCHS' x86_64'
654
+		'ARCHS': x86_64'
655
 		...
656
 	}
657
 }
658
@@ -163,12 +163,12 @@ class XCodeNode(object):
659
 			result = result + "\t\t}"
660
 			return result
661
 		elif isinstance(value, str):
662
-			return "\"%s\"" % value
663
+			return '"%s"' % value.replace('"', '\\\\\\"')
664
 		elif isinstance(value, list):
665
 			result = "(\n"
666
 			for i in value:
667
-				result = result + "\t\t\t%s,\n" % self.tostring(i)
668
-			result = result + "\t\t)"
669
+				result = result + "\t\t\t\t%s,\n" % self.tostring(i)
670
+			result = result + "\t\t\t)"
671
 			return result
672
 		elif isinstance(value, XCodeNode):
673
 			return value._id
674
@@ -565,13 +565,13 @@ def process_xcode(self):
675
 	# Override target specific build settings
676
 	bldsettings = {
677
 		'HEADER_SEARCH_PATHS': ['$(inherited)'] + self.env['INCPATHS'],
678
-		'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR) ,
679
+		'LIBRARY_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.LIBPATH) + Utils.to_list(self.env.STLIBPATH) + Utils.to_list(self.env.LIBDIR),
680
 		'FRAMEWORK_SEARCH_PATHS': ['$(inherited)'] + Utils.to_list(self.env.FRAMEWORKPATH),
681
-		'OTHER_LDFLAGS': libs + ' ' + frameworks,
682
-		'OTHER_LIBTOOLFLAGS': bld.env['LINKFLAGS'],
683
+		'OTHER_LDFLAGS': libs + ' ' + frameworks + ' ' + ' '.join(bld.env['LINKFLAGS']),
684
 		'OTHER_CPLUSPLUSFLAGS': Utils.to_list(self.env['CXXFLAGS']),
685
 		'OTHER_CFLAGS': Utils.to_list(self.env['CFLAGS']),
686
-		'INSTALL_PATH': []
687
+		'INSTALL_PATH': [],
688
+		'GCC_PREPROCESSOR_DEFINITIONS': self.env['DEFINES']
689
 	}
690
 
691
 	# Install path
692
@@ -591,7 +591,7 @@ def process_xcode(self):
693
 
694
 	# The keys represents different build configuration, e.g. Debug, Release and so on..
695
 	# Insert our generated build settings to all configuration names
696
-	keys = set(settings.keys() + bld.env.PROJ_CONFIGURATION.keys())
697
+	keys = set(settings.keys()) | set(bld.env.PROJ_CONFIGURATION.keys())
698
 	for k in keys:
699
 		if k in settings:
700
 			settings[k].update(bldsettings)
701
-- 
702
2.37.3
703
(-)b/net/samba413/files/patch-waf-2.0.22 (+596 lines)
Added Link Here
1
From 59ed09928541d40df72592419247add608a54aca Mon Sep 17 00:00:00 2001
2
From: Andreas Schneider <asn@samba.org>
3
Date: Wed, 25 Aug 2021 15:34:58 +0200
4
Subject: [PATCH] third_party: Update waf to version 2.0.22
5
6
New in waf 2.0.22
7
8
* Fix stdin propagation with faulty vcvarsall scripts #2315
9
* Enable mixing Unix-style paths with destdir on Windows platforms #2337
10
* Fix shell escaping unit test parameters #2314
11
* Improve extras/clang_compilation_database and extras/swig compatibility #2336
12
* Propagate C++ flags to the Cuda compiler in extras/cuda #2311
13
* Fix detection of Qt 5.0.0 (preparation for Qt6) #2331
14
* Enable Haxe processing #2308
15
* Fix regression in MACOSX_DEPLOYMENT_TARGET caused by distutils #2330
16
* Fix extras/wafcache concurrent trimming issues #2312
17
* Fix extras/wafcache symlink handling #2327
18
19
The import was done like this:
20
21
./third_party/waf/update.sh
22
23
Then changing buildtools/bin/waf and buildtools/wafsamba/wafsamba.py
24
by hand.
25
26
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org>
27
28
Signed-off-by: Andreas Schneider <asn@samba.org>
29
Signed-off-by: Stefan Metzmacher <metze@samba.org>
30
Reviewed-by: Andrew Bartlett <abartlet@samba.org>
31
32
Autobuild-User(master): Andrew Bartlett <abartlet@samba.org>
33
Autobuild-Date(master): Thu Sep  2 21:22:17 UTC 2021 on sn-devel-184
34
---
35
 buildtools/bin/waf                            |   2 +-
36
 buildtools/wafsamba/wafsamba.py               |   2 +-
37
 third_party/waf/waflib/Build.py               |   4 +-
38
 third_party/waf/waflib/Context.py             |   6 +-
39
 third_party/waf/waflib/Tools/msvc.py          |   2 +-
40
 third_party/waf/waflib/Tools/python.py        |   2 +-
41
 third_party/waf/waflib/Tools/qt5.py           |   6 +-
42
 third_party/waf/waflib/Tools/waf_unit_test.py |   2 +-
43
 third_party/waf/waflib/Utils.py               |  15 +-
44
 .../extras/clang_compilation_database.py      |  28 ++--
45
 third_party/waf/waflib/extras/haxe.py         | 131 ++++++++++++++++++
46
 third_party/waf/waflib/extras/wafcache.py     |  59 ++++++--
47
 12 files changed, 215 insertions(+), 44 deletions(-)
48
 create mode 100644 third_party/waf/waflib/extras/haxe.py
49
50
diff --git buildtools/bin/waf buildtools/bin/waf
51
index 041450fc131..b0ccb09a877 100755
52
--- buildtools/bin/waf
53
+++ buildtools/bin/waf
54
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
55
 
56
 import os, sys, inspect
57
 
58
-VERSION="2.0.21"
59
+VERSION="2.0.22"
60
 REVISION="x"
61
 GIT="x"
62
 INSTALL="x"
63
diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py
64
index 4fe9daf160e..dee007bf84e 100644
65
--- buildtools/wafsamba/wafsamba.py
66
+++ buildtools/wafsamba/wafsamba.py
67
@@ -38,7 +38,7 @@ LIB_PATH="shared"
68
 
69
 os.environ['PYTHONUNBUFFERED'] = '1'
70
 
71
-if Context.HEXVERSION not in (0x2001500,):
72
+if Context.HEXVERSION not in (0x2001600,):
73
     Logs.error('''
74
 Please use the version of waf that comes with Samba, not
75
 a system installed version. See http://wiki.samba.org/index.php/Waf
76
diff --git third_party/waf/waflib/Build.py third_party/waf/waflib/Build.py
77
index 52837618577..b49dd8302b1 100644
78
--- third_party/waf/waflib/Build.py
79
+++ third_party/waf/waflib/Build.py
80
@@ -1066,9 +1066,9 @@ class inst(Task.Task):
81
 		else:
82
 			dest = os.path.normpath(Utils.subst_vars(self.install_to, self.env))
83
 		if not os.path.isabs(dest):
84
-		    dest = os.path.join(self.env.PREFIX, dest)
85
+			dest = os.path.join(self.env.PREFIX, dest)
86
 		if destdir and Options.options.destdir:
87
-			dest = os.path.join(Options.options.destdir, os.path.splitdrive(dest)[1].lstrip(os.sep))
88
+			dest = Options.options.destdir.rstrip(os.sep) + os.sep + os.path.splitdrive(dest)[1].lstrip(os.sep)
89
 		return dest
90
 
91
 	def copy_fun(self, src, tgt):
92
diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py
93
index 0ce9df6e91f..07ee1201f03 100644
94
--- third_party/waf/waflib/Context.py
95
+++ third_party/waf/waflib/Context.py
96
@@ -18,13 +18,13 @@ else:
97
 	import imp
98
 
99
 # the following 3 constants are updated on each new release (do not touch)
100
-HEXVERSION=0x2001500
101
+HEXVERSION=0x2001600
102
 """Constant updated on new releases"""
103
 
104
-WAFVERSION="2.0.21"
105
+WAFVERSION="2.0.22"
106
 """Constant updated on new releases"""
107
 
108
-WAFREVISION="edde20a6425a5c3eb6b47d5f3f5c4fbc93fed5f4"
109
+WAFREVISION="816d5bc48ba2abc4ac22f2b44d94d322bf992b9c"
110
 """Git revision when the waf version is updated"""
111
 
112
 WAFNAME="waf"
113
diff --git third_party/waf/waflib/Tools/msvc.py third_party/waf/waflib/Tools/msvc.py
114
index 37233be8242..0c4703aaee9 100644
115
--- third_party/waf/waflib/Tools/msvc.py
116
+++ third_party/waf/waflib/Tools/msvc.py
117
@@ -193,7 +193,7 @@ echo PATH=%%PATH%%
118
 echo INCLUDE=%%INCLUDE%%
119
 echo LIB=%%LIB%%;%%LIBPATH%%
120
 """ % (vcvars,target))
121
-	sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()])
122
+	sout = conf.cmd_and_log(['cmd.exe', '/E:on', '/V:on', '/C', batfile.abspath()], stdin=getattr(Utils.subprocess, 'DEVNULL', None))
123
 	lines = sout.splitlines()
124
 
125
 	if not lines[0]:
126
diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py
127
index b1c8dd01285..07442561dff 100644
128
--- third_party/waf/waflib/Tools/python.py
129
+++ third_party/waf/waflib/Tools/python.py
130
@@ -327,7 +327,7 @@ def check_python_headers(conf, features='pyembed pyext'):
131
 	dct = dict(zip(v, lst))
132
 	x = 'MACOSX_DEPLOYMENT_TARGET'
133
 	if dct[x]:
134
-		env[x] = conf.environ[x] = dct[x]
135
+		env[x] = conf.environ[x] = str(dct[x])
136
 	env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake
137
 
138
 
139
diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py
140
index cff2028174f..82c83e18c8a 100644
141
--- third_party/waf/waflib/Tools/qt5.py
142
+++ third_party/waf/waflib/Tools/qt5.py
143
@@ -566,7 +566,7 @@ def find_qt5_binaries(self):
144
 	# at the end, try to find qmake in the paths given
145
 	# keep the one with the highest version
146
 	cand = None
147
-	prev_ver = ['5', '0', '0']
148
+	prev_ver = ['0', '0', '0']
149
 	for qmk in ('qmake-qt5', 'qmake5', 'qmake'):
150
 		try:
151
 			qmake = self.find_program(qmk, path_list=paths)
152
@@ -580,7 +580,7 @@ def find_qt5_binaries(self):
153
 			else:
154
 				if version:
155
 					new_ver = version.split('.')
156
-					if new_ver > prev_ver:
157
+					if new_ver[0] == '5' and new_ver > prev_ver:
158
 						cand = qmake
159
 						prev_ver = new_ver
160
 
161
@@ -783,7 +783,7 @@ def set_qt5_libs_to_check(self):
162
 			pat = self.env.cxxstlib_PATTERN
163
 		if Utils.unversioned_sys_platform() == 'darwin':
164
 			pat = r"%s\.framework"
165
-		re_qt = re.compile(pat%'Qt5?(?P<name>.*)'+'$')
166
+		re_qt = re.compile(pat % 'Qt5?(?P<name>\\D+)' + '$')
167
 		for x in dirlst:
168
 			m = re_qt.match(x)
169
 			if m:
170
diff --git third_party/waf/waflib/Tools/waf_unit_test.py third_party/waf/waflib/Tools/waf_unit_test.py
171
index dc66fe9c184..8cff89bdeb9 100644
172
--- third_party/waf/waflib/Tools/waf_unit_test.py
173
+++ third_party/waf/waflib/Tools/waf_unit_test.py
174
@@ -206,7 +206,7 @@ class utest(Task.Task):
175
 		self.ut_exec = getattr(self.generator, 'ut_exec', [self.inputs[0].abspath()])
176
 		ut_cmd = getattr(self.generator, 'ut_cmd', False)
177
 		if ut_cmd:
178
-			self.ut_exec = shlex.split(ut_cmd % ' '.join(self.ut_exec))
179
+			self.ut_exec = shlex.split(ut_cmd % Utils.shell_escape(self.ut_exec))
180
 
181
 		return self.exec_command(self.ut_exec)
182
 
183
diff --git third_party/waf/waflib/Utils.py third_party/waf/waflib/Utils.py
184
index fc64fa05154..669490ca908 100644
185
--- third_party/waf/waflib/Utils.py
186
+++ third_party/waf/waflib/Utils.py
187
@@ -11,7 +11,7 @@ through Python versions 2.5 to 3.X and across different platforms (win32, linux,
188
 
189
 from __future__ import with_statement
190
 
191
-import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time
192
+import atexit, os, sys, errno, inspect, re, datetime, platform, base64, signal, functools, time, shlex
193
 
194
 try:
195
 	import cPickle
196
@@ -577,10 +577,13 @@ def quote_define_name(s):
197
 	fu = fu.upper()
198
 	return fu
199
 
200
-re_sh = re.compile('\\s|\'|"')
201
-"""
202
-Regexp used for shell_escape below
203
-"""
204
+# shlex.quote didn't exist until python 3.3. Prior to that it was a non-documented
205
+# function in pipes.
206
+try:
207
+	shell_quote = shlex.quote
208
+except AttributeError:
209
+	import pipes
210
+	shell_quote = pipes.quote
211
 
212
 def shell_escape(cmd):
213
 	"""
214
@@ -589,7 +592,7 @@ def shell_escape(cmd):
215
 	"""
216
 	if isinstance(cmd, str):
217
 		return cmd
218
-	return ' '.join(repr(x) if re_sh.search(x) else x for x in cmd)
219
+	return ' '.join(shell_quote(x) for x in cmd)
220
 
221
 def h_list(lst):
222
 	"""
223
diff --git third_party/waf/waflib/extras/clang_compilation_database.py third_party/waf/waflib/extras/clang_compilation_database.py
224
index ff71f22ecfd..17f66949376 100644
225
--- third_party/waf/waflib/extras/clang_compilation_database.py
226
+++ third_party/waf/waflib/extras/clang_compilation_database.py
227
@@ -29,22 +29,9 @@ from waflib import Logs, TaskGen, Task, Build, Scripting
228
 
229
 Task.Task.keep_last_cmd = True
230
 
231
-@TaskGen.feature('c', 'cxx')
232
-@TaskGen.after_method('process_use')
233
-def collect_compilation_db_tasks(self):
234
-	"Add a compilation database entry for compiled tasks"
235
-	if not isinstance(self.bld, ClangDbContext):
236
-		return
237
-
238
-	tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y)
239
-	for task in getattr(self, 'compiled_tasks', []):
240
-		if isinstance(task, tup):
241
-			self.bld.clang_compilation_database_tasks.append(task)
242
-
243
 class ClangDbContext(Build.BuildContext):
244
 	'''generates compile_commands.json by request'''
245
 	cmd = 'clangdb'
246
-	clang_compilation_database_tasks = []
247
 
248
 	def write_compilation_database(self):
249
 		"""
250
@@ -78,6 +65,8 @@ class ClangDbContext(Build.BuildContext):
251
 		Build dry run
252
 		"""
253
 		self.restore()
254
+		self.cur_tasks = []
255
+		self.clang_compilation_database_tasks = []
256
 
257
 		if not self.all_envs:
258
 			self.load_envs()
259
@@ -103,8 +92,21 @@ class ClangDbContext(Build.BuildContext):
260
 					lst = [tg]
261
 				else: lst = tg.tasks
262
 				for tsk in lst:
263
+					if tsk.__class__.__name__ == "swig":
264
+						tsk.runnable_status()
265
+						if hasattr(tsk, 'more_tasks'):
266
+							lst.extend(tsk.more_tasks)
267
+					# Not all dynamic tasks can be processed, in some cases
268
+					# one may have to call the method "run()" like this:
269
+					#elif tsk.__class__.__name__ == 'src2c':
270
+					#	tsk.run()
271
+					#	if hasattr(tsk, 'more_tasks'):
272
+					#		lst.extend(tsk.more_tasks)
273
+
274
 					tup = tuple(y for y in [Task.classes.get(x) for x in ('c', 'cxx')] if y)
275
 					if isinstance(tsk, tup):
276
+						self.clang_compilation_database_tasks.append(tsk)
277
+						tsk.nocache = True
278
 						old_exec = tsk.exec_command
279
 						tsk.exec_command = exec_command
280
 						tsk.run()
281
diff --git third_party/waf/waflib/extras/haxe.py third_party/waf/waflib/extras/haxe.py
282
new file mode 100644
283
index 00000000000..cb3ba6a949c
284
--- /dev/null
285
+++ third_party/waf/waflib/extras/haxe.py
286
@@ -0,0 +1,131 @@
287
+import os, re
288
+from waflib import Utils, Task, Errors
289
+from waflib.TaskGen import extension, taskgen_method, feature
290
+from waflib.Configure import conf
291
+
292
+@conf
293
+def libname_haxe(self, libname):
294
+	return libname
295
+
296
+@conf
297
+def check_lib_haxe(self, libname, uselib_store=None):
298
+	haxe_libs = [node.name for node in self.root.find_node('haxe_libraries').ant_glob()]
299
+	changed = False
300
+	self.start_msg('Checking for library %s' % libname)
301
+	if libname + '.hxml' in haxe_libs:
302
+		self.end_msg('yes')
303
+	else:
304
+		changed = True
305
+		try:
306
+			cmd = self.env.LIX + ['+lib', libname]
307
+			res = self.cmd_and_log(cmd)
308
+			if (res):
309
+				raise Errors.WafError(res)
310
+			else:
311
+				self.end_msg('downloaded', color = 'YELLOW')
312
+		except Errors.WafError as e:
313
+			self.end_msg('no', color = 'RED')
314
+			self.fatal('Getting %s has failed' % libname)
315
+
316
+	postfix = uselib_store if uselib_store else libname.upper()
317
+	self.env['LIB_' + postfix] += [self.libname_haxe(libname)]
318
+	return changed
319
+
320
+@conf
321
+def check_libs_haxe(self, libnames, uselib_store=None):
322
+	changed = False
323
+	for libname in Utils.to_list(libnames):
324
+		if self.check_lib_haxe(libname, uselib_store):
325
+			changed = True
326
+	return changed
327
+
328
+@conf
329
+def ensure_lix_pkg(self, *k, **kw):
330
+	if kw.get('compiler') == 'hx':
331
+		if isinstance(kw.get('libs'), list) and len(kw.get('libs')):
332
+			changed = self.check_libs_haxe(kw.get('libs'), kw.get('uselib_store'))
333
+			if changed:
334
+				try:
335
+					cmd = self.env.LIX + ['download']
336
+					res = self.cmd_and_log(cmd)
337
+					if (res):
338
+						raise Errors.WafError(res)
339
+				except Errors.WafError as e:
340
+					self.fatal('lix download has failed')
341
+		else:
342
+			self.check_lib_haxe(kw.get('lib'), kw.get('uselib_store'))
343
+
344
+@conf
345
+def haxe(bld, *k, **kw):
346
+	task_gen = bld(*k, **kw)
347
+
348
+class haxe(Task.Task):
349
+	vars = ['HAXE', 'HAXE_VERSION', 'HAXEFLAGS']
350
+	ext_out = ['.hl', '.c', '.h']
351
+
352
+	def run(self):
353
+		cmd = self.env.HAXE + self.env.HAXEFLAGS
354
+		return self.exec_command(cmd, stdout = open(os.devnull, 'w'))
355
+
356
+@taskgen_method
357
+def init_haxe_task(self, node):
358
+	def addflags(flags):
359
+		self.env.append_value('HAXEFLAGS', flags)
360
+
361
+	if node.suffix() == '.hxml':
362
+		addflags(self.path.abspath() + '/' + node.name)
363
+	else:
364
+		addflags(['-main', node.name])
365
+	addflags(['-hl', self.path.get_bld().make_node(self.target).abspath()])
366
+	addflags(['-cp', self.path.abspath()])
367
+	addflags(['-D', 'resourcesPath=%s' % getattr(self, 'res', '')])
368
+	if hasattr(self, 'use'):
369
+		for dep in self.use:
370
+			if self.env['LIB_' + dep]:
371
+				for lib in self.env['LIB_' + dep]: addflags(['-lib', lib])
372
+
373
+@extension('.hx', '.hxml')
374
+def haxe_file(self, node):
375
+	if len(self.source) > 1:
376
+		self.bld.fatal('Use separate task generators for multiple files')
377
+
378
+	try:
379
+		haxetask = self.haxetask
380
+	except AttributeError:
381
+		haxetask = self.haxetask = self.create_task('haxe')
382
+		self.init_haxe_task(node)
383
+
384
+	haxetask.inputs.append(node)
385
+	haxetask.outputs.append(self.path.get_bld().make_node(self.target))
386
+
387
+@conf
388
+def find_haxe(self, min_version):
389
+	npx = self.env.NPX = self.find_program('npx')
390
+	self.env.LIX = npx + ['lix']
391
+	npx_haxe = self.env.HAXE = npx + ['haxe']
392
+	try:
393
+		output = self.cmd_and_log(npx_haxe + ['-version'])
394
+	except Errors.WafError:
395
+		haxe_version = None
396
+	else:
397
+		ver = re.search(r'\d+.\d+.\d+', output).group().split('.')
398
+		haxe_version = tuple([int(x) for x in ver])
399
+
400
+	self.msg('Checking for haxe version',
401
+	         haxe_version, haxe_version and haxe_version >= min_version)
402
+	if npx_haxe and haxe_version < min_version:
403
+		self.fatal('haxe version %r is too old, need >= %r' % (haxe_version, min_version))
404
+
405
+	self.env.HAXE_VERSION = haxe_version
406
+	return npx_haxe
407
+
408
+@conf
409
+def check_haxe(self, min_version=(4,1,4)):
410
+	if self.env.HAXE_MINVER:
411
+		min_version = self.env.HAXE_MINVER
412
+	find_haxe(self, min_version)
413
+
414
+def configure(self):
415
+	self.env.HAXEFLAGS = []
416
+	self.check_haxe()
417
+	self.add_os_flags('HAXEFLAGS', dup = False)
418
diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py
419
index 088fd0d098d..cc23fcd6673 100644
420
--- third_party/waf/waflib/extras/wafcache.py
421
+++ third_party/waf/waflib/extras/wafcache.py
422
@@ -31,6 +31,7 @@ The following environment variables may be set:
423
     gsutil cp gs://mybucket/bb/bbbbb/2 build/somefile
424
 * WAFCACHE_NO_PUSH: if set, disables pushing to the cache
425
 * WAFCACHE_VERBOSITY: if set, displays more detailed cache operations
426
+* WAFCACHE_STATS: if set, displays cache usage statistics on exit
427
 
428
 File cache specific options:
429
   Files are copied using hard links by default; if the cache is located
430
@@ -69,6 +70,7 @@ EVICT_INTERVAL_MINUTES = int(os.environ.get('WAFCACHE_EVICT_INTERVAL_MINUTES', 3
431
 EVICT_MAX_BYTES = int(os.environ.get('WAFCACHE_EVICT_MAX_BYTES', 10**10))
432
 WAFCACHE_NO_PUSH = 1 if os.environ.get('WAFCACHE_NO_PUSH') else 0
433
 WAFCACHE_VERBOSITY = 1 if os.environ.get('WAFCACHE_VERBOSITY') else 0
434
+WAFCACHE_STATS = 1 if os.environ.get('WAFCACHE_STATS') else 0
435
 OK = "ok"
436
 
437
 re_waf_cmd = re.compile('(?P<src>%{SRC})|(?P<tgt>%{TGT})')
438
@@ -93,6 +95,9 @@ def can_retrieve_cache(self):
439
 	sig = self.signature()
440
 	ssig = Utils.to_hex(self.uid() + sig)
441
 
442
+	if WAFCACHE_STATS:
443
+		self.generator.bld.cache_reqs += 1
444
+
445
 	files_to = [node.abspath() for node in self.outputs]
446
 	err = cache_command(ssig, [], files_to)
447
 	if err.startswith(OK):
448
@@ -100,6 +105,8 @@ def can_retrieve_cache(self):
449
 			Logs.pprint('CYAN', '  Fetched %r from cache' % files_to)
450
 		else:
451
 			Logs.debug('wafcache: fetched %r from cache', files_to)
452
+		if WAFCACHE_STATS:
453
+			self.generator.bld.cache_hits += 1
454
 	else:
455
 		if WAFCACHE_VERBOSITY:
456
 			Logs.pprint('YELLOW', '  No cache entry %s' % files_to)
457
@@ -117,11 +124,17 @@ def put_files_cache(self):
458
 	if WAFCACHE_NO_PUSH or getattr(self, 'cached', None) or not self.outputs:
459
 		return
460
 
461
+	files_from = []
462
+	for node in self.outputs:
463
+		path = node.abspath()
464
+		if not os.path.isfile(path):
465
+			return
466
+		files_from.append(path)
467
+
468
 	bld = self.generator.bld
469
 	sig = self.signature()
470
 	ssig = Utils.to_hex(self.uid() + sig)
471
 
472
-	files_from = [node.abspath() for node in self.outputs]
473
 	err = cache_command(ssig, files_from, [])
474
 
475
 	if err.startswith(OK):
476
@@ -129,6 +142,8 @@ def put_files_cache(self):
477
 			Logs.pprint('CYAN', '  Successfully uploaded %s to cache' % files_from)
478
 		else:
479
 			Logs.debug('wafcache: Successfully uploaded %r to cache', files_from)
480
+		if WAFCACHE_STATS:
481
+			self.generator.bld.cache_puts += 1
482
 	else:
483
 		if WAFCACHE_VERBOSITY:
484
 			Logs.pprint('RED', '  Error caching step results %s: %s' % (files_from, err))
485
@@ -193,6 +208,10 @@ def make_cached(cls):
486
 	if getattr(cls, 'nocache', None) or getattr(cls, 'has_cache', False):
487
 		return
488
 
489
+	full_name = "%s.%s" % (cls.__module__, cls.__name__)
490
+	if full_name in ('waflib.Tools.ccroot.vnum', 'waflib.Build.inst'):
491
+		return
492
+
493
 	m1 = getattr(cls, 'run', None)
494
 	def run(self):
495
 		if getattr(self, 'nocache', False):
496
@@ -208,9 +227,6 @@ def make_cached(cls):
497
 			return m2(self)
498
 		ret = m2(self)
499
 		self.put_files_cache()
500
-		if hasattr(self, 'chmod'):
501
-			for node in self.outputs:
502
-				os.chmod(node.abspath(), self.chmod)
503
 		return ret
504
 	cls.post_run = post_run
505
 	cls.has_cache = True
506
@@ -257,6 +273,19 @@ def build(bld):
507
 	for x in reversed(list(Task.classes.values())):
508
 		make_cached(x)
509
 
510
+	if WAFCACHE_STATS:
511
+		# Init counter for statistics and hook to print results at the end
512
+		bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0
513
+
514
+		def printstats(bld):
515
+			hit_ratio = 0
516
+			if bld.cache_reqs > 0:
517
+				hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100
518
+			Logs.pprint('CYAN', '  wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' %
519
+					 (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) )
520
+
521
+		bld.add_post_fun(printstats)
522
+
523
 def cache_command(sig, files_from, files_to):
524
 	"""
525
 	Create a command for cache worker processes, returns a pickled
526
@@ -320,7 +349,10 @@ def lru_trim():
527
 
528
 				size = 0
529
 				for fname in os.listdir(path):
530
-					size += os.lstat(os.path.join(path, fname)).st_size
531
+					try:
532
+						size += os.lstat(os.path.join(path, fname)).st_size
533
+					except OSError:
534
+						pass
535
 				lst.append((os.stat(path).st_mtime, size, path))
536
 
537
 	lst.sort(key=lambda x: x[0])
538
@@ -331,7 +363,7 @@ def lru_trim():
539
 		_, tmp_size, path = lst.pop()
540
 		tot -= tmp_size
541
 
542
-		tmp = path + '.tmp'
543
+		tmp = path + '.remove'
544
 		try:
545
 			shutil.rmtree(tmp)
546
 		except OSError:
547
@@ -339,12 +371,12 @@ def lru_trim():
548
 		try:
549
 			os.rename(path, tmp)
550
 		except OSError:
551
-			sys.stderr.write('Could not rename %r to %r' % (path, tmp))
552
+			sys.stderr.write('Could not rename %r to %r\n' % (path, tmp))
553
 		else:
554
 			try:
555
 				shutil.rmtree(tmp)
556
 			except OSError:
557
-				sys.stderr.write('Could not remove %r' % tmp)
558
+				sys.stderr.write('Could not remove %r\n' % tmp)
559
 	sys.stderr.write("Cache trimmed: %r bytes in %r folders left\n" % (tot, len(lst)))
560
 
561
 
562
@@ -371,8 +403,8 @@ def lru_evict():
563
 			try:
564
 				fcntl.flock(fd, fcntl.LOCK_EX | fcntl.LOCK_NB)
565
 			except EnvironmentError:
566
-				sys.stderr.write('another process is running!\n')
567
-				pass
568
+				if WAFCACHE_VERBOSITY:
569
+					sys.stderr.write('wafcache: another cleaning process is running\n')
570
 			else:
571
 				# now dow the actual cleanup
572
 				lru_trim()
573
@@ -443,7 +475,10 @@ class fcache(object):
574
 		else:
575
 			# attempt trimming if caching was successful:
576
 			# we may have things to trim!
577
-			lru_evict()
578
+			try:
579
+				lru_evict()
580
+			except Exception:
581
+				return traceback.format_exc()
582
 		return OK
583
 
584
 	def copy_from_cache(self, sig, files_from, files_to):
585
@@ -481,7 +516,7 @@ class bucket_cache(object):
586
 		out, err = proc.communicate()
587
 		if proc.returncode:
588
 			raise OSError('Error copy %r to %r using: %r (exit %r):\n  out:%s\n  err:%s' % (
589
-				source, target, cmd, proc.returncode, out.decode(), err.decode()))
590
+				source, target, cmd, proc.returncode, out.decode(errors='replace'), err.decode(errors='replace')))
591
 
592
 	def copy_to_cache(self, sig, files_from, files_to):
593
 		try:
594
-- 
595
2.37.3
596
(-)b/net/samba413/files/patch-waf-2.0.23 (+877 lines)
Added Link Here
1
From fb175576b698f43224dab815fd6c0763a12db2b2 Mon Sep 17 00:00:00 2001
2
From: Andreas Schneider <asn@samba.org>
3
Date: Thu, 17 Feb 2022 15:40:20 +0100
4
Subject: [PATCH] third_party: Update waf to verison 2.0.23
5
6
Signed-off-by: Andreas Schneider <asn@samba.org>
7
Reviewed-by: Alexander Bokovoy <ab@samba.org>
8
9
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
10
Autobuild-Date(master): Mon Feb 21 10:06:27 UTC 2022 on sn-devel-184
11
---
12
 buildtools/bin/waf                            |  3 +-
13
 buildtools/wafsamba/wafsamba.py               |  2 +-
14
 third_party/waf/waflib/Context.py             |  6 +-
15
 third_party/waf/waflib/Runner.py              |  4 +-
16
 third_party/waf/waflib/TaskGen.py             |  8 +-
17
 third_party/waf/waflib/Tools/c_config.py      |  1 +
18
 third_party/waf/waflib/Tools/compiler_c.py    | 25 +++---
19
 third_party/waf/waflib/Tools/compiler_cxx.py  | 25 +++---
20
 third_party/waf/waflib/Tools/python.py        |  7 +-
21
 third_party/waf/waflib/Tools/qt5.py           |  4 +-
22
 third_party/waf/waflib/Tools/winres.py        | 35 ++++++++
23
 .../extras/clang_compilation_database.py      |  2 +-
24
 .../waf/waflib/extras/classic_runner.py       | 68 +++++++++++++++
25
 third_party/waf/waflib/extras/color_gcc.py    |  2 +-
26
 third_party/waf/waflib/extras/eclipse.py      | 74 ++++++++++++++++-
27
 third_party/waf/waflib/extras/gccdeps.py      | 82 ++++++++++---------
28
 third_party/waf/waflib/extras/msvcdeps.py     | 54 ++++++++----
29
 third_party/waf/waflib/extras/msvs.py         |  6 +-
30
 third_party/waf/waflib/extras/swig.py         |  2 +-
31
 third_party/waf/waflib/extras/wafcache.py     | 26 +++---
32
 third_party/waf/waflib/fixpy2.py              |  2 +-
33
 21 files changed, 325 insertions(+), 113 deletions(-)
34
 create mode 100644 third_party/waf/waflib/extras/classic_runner.py
35
36
diff --git buildtools/bin/waf buildtools/bin/waf
37
index b0ccb09a877..2001ccdbd8a 100755
38
--- buildtools/bin/waf
39
+++ buildtools/bin/waf
40
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
41
 
42
 import os, sys, inspect
43
 
44
-VERSION="2.0.22"
45
+VERSION="2.0.23"
46
 REVISION="x"
47
 GIT="x"
48
 INSTALL="x"
49
@@ -164,4 +164,3 @@ if __name__ == '__main__':
50
 
51
 	from waflib import Scripting
52
 	Scripting.waf_entry_point(cwd, VERSION, wafdir[0])
53
-
54
diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py
55
index 185ef3b73a2..710b82af663 100644
56
--- buildtools/wafsamba/wafsamba.py
57
+++ buildtools/wafsamba/wafsamba.py
58
@@ -38,7 +38,7 @@ LIB_PATH="shared"
59
 
60
 os.environ['PYTHONUNBUFFERED'] = '1'
61
 
62
-if Context.HEXVERSION not in (0x2001600,):
63
+if Context.HEXVERSION not in (0x2001700,):
64
     Logs.error('''
65
 Please use the version of waf that comes with Samba, not
66
 a system installed version. See http://wiki.samba.org/index.php/Waf
67
diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py
68
index 07ee1201f03..36d1ca74fef 100644
69
--- third_party/waf/waflib/Context.py
70
+++ third_party/waf/waflib/Context.py
71
@@ -18,13 +18,13 @@ else:
72
 	import imp
73
 
74
 # the following 3 constants are updated on each new release (do not touch)
75
-HEXVERSION=0x2001600
76
+HEXVERSION=0x2001700
77
 """Constant updated on new releases"""
78
 
79
-WAFVERSION="2.0.22"
80
+WAFVERSION="2.0.23"
81
 """Constant updated on new releases"""
82
 
83
-WAFREVISION="816d5bc48ba2abc4ac22f2b44d94d322bf992b9c"
84
+WAFREVISION="cc6b34cf555d354c34f554c41206134072588de7"
85
 """Git revision when the waf version is updated"""
86
 
87
 WAFNAME="waf"
88
diff --git third_party/waf/waflib/Runner.py third_party/waf/waflib/Runner.py
89
index 91d55479e20..350c86a22c0 100644
90
--- third_party/waf/waflib/Runner.py
91
+++ third_party/waf/waflib/Runner.py
92
@@ -71,7 +71,7 @@ class Consumer(Utils.threading.Thread):
93
 		"""Task to execute"""
94
 		self.spawner = spawner
95
 		"""Coordinator object"""
96
-		self.setDaemon(1)
97
+		self.daemon = True
98
 		self.start()
99
 	def run(self):
100
 		"""
101
@@ -98,7 +98,7 @@ class Spawner(Utils.threading.Thread):
102
 		""":py:class:`waflib.Runner.Parallel` producer instance"""
103
 		self.sem = Utils.threading.Semaphore(master.numjobs)
104
 		"""Bounded semaphore that prevents spawning more than *n* concurrent consumers"""
105
-		self.setDaemon(1)
106
+		self.daemon = True
107
 		self.start()
108
 	def run(self):
109
 		"""
110
diff --git third_party/waf/waflib/TaskGen.py third_party/waf/waflib/TaskGen.py
111
index f8f92bd57c1..89f63169910 100644
112
--- third_party/waf/waflib/TaskGen.py
113
+++ third_party/waf/waflib/TaskGen.py
114
@@ -631,12 +631,8 @@ def process_rule(self):
115
 			cls.scan = self.scan
116
 		elif has_deps:
117
 			def scan(self):
118
-				nodes = []
119
-				for x in self.generator.to_list(getattr(self.generator, 'deps', None)):
120
-					node = self.generator.path.find_resource(x)
121
-					if not node:
122
-						self.generator.bld.fatal('Could not find %r (was it declared?)' % x)
123
-					nodes.append(node)
124
+				deps = getattr(self.generator, 'deps', None)
125
+				nodes = self.generator.to_nodes(deps)
126
 				return [nodes, []]
127
 			cls.scan = scan
128
 
129
diff --git third_party/waf/waflib/Tools/c_config.py third_party/waf/waflib/Tools/c_config.py
130
index 03b6bf61bc0..f5ab19bf6ce 100644
131
--- third_party/waf/waflib/Tools/c_config.py
132
+++ third_party/waf/waflib/Tools/c_config.py
133
@@ -69,6 +69,7 @@ MACRO_TO_DEST_CPU = {
134
 '__sh__'      : 'sh',
135
 '__xtensa__'  : 'xtensa',
136
 '__e2k__'     : 'e2k',
137
+'__riscv'     : 'riscv',
138
 }
139
 
140
 @conf
141
diff --git third_party/waf/waflib/Tools/compiler_c.py third_party/waf/waflib/Tools/compiler_c.py
142
index 931dc57efec..e033ce6c5c3 100644
143
--- third_party/waf/waflib/Tools/compiler_c.py
144
+++ third_party/waf/waflib/Tools/compiler_c.py
145
@@ -36,18 +36,19 @@ from waflib import Utils
146
 from waflib.Logs import debug
147
 
148
 c_compiler = {
149
-'win32':  ['msvc', 'gcc', 'clang'],
150
-'cygwin': ['gcc', 'clang'],
151
-'darwin': ['clang', 'gcc'],
152
-'aix':    ['xlc', 'gcc', 'clang'],
153
-'linux':  ['gcc', 'clang', 'icc'],
154
-'sunos':  ['suncc', 'gcc'],
155
-'irix':   ['gcc', 'irixcc'],
156
-'hpux':   ['gcc'],
157
-'osf1V':  ['gcc'],
158
-'gnu':    ['gcc', 'clang'],
159
-'java':   ['gcc', 'msvc', 'clang', 'icc'],
160
-'default':['clang', 'gcc'],
161
+'win32':       ['msvc', 'gcc', 'clang'],
162
+'cygwin':      ['gcc', 'clang'],
163
+'darwin':      ['clang', 'gcc'],
164
+'aix':         ['xlc', 'gcc', 'clang'],
165
+'linux':       ['gcc', 'clang', 'icc'],
166
+'sunos':       ['suncc', 'gcc'],
167
+'irix':        ['gcc', 'irixcc'],
168
+'hpux':        ['gcc'],
169
+'osf1V':       ['gcc'],
170
+'gnu':         ['gcc', 'clang'],
171
+'java':        ['gcc', 'msvc', 'clang', 'icc'],
172
+'gnukfreebsd': ['gcc', 'clang'],
173
+'default':     ['clang', 'gcc'],
174
 }
175
 """
176
 Dict mapping platform names to Waf tools finding specific C compilers::
177
diff --git third_party/waf/waflib/Tools/compiler_cxx.py third_party/waf/waflib/Tools/compiler_cxx.py
178
index 09fca7e4dc6..42658c5847e 100644
179
--- third_party/waf/waflib/Tools/compiler_cxx.py
180
+++ third_party/waf/waflib/Tools/compiler_cxx.py
181
@@ -37,18 +37,19 @@ from waflib import Utils
182
 from waflib.Logs import debug
183
 
184
 cxx_compiler = {
185
-'win32':  ['msvc', 'g++', 'clang++'],
186
-'cygwin': ['g++', 'clang++'],
187
-'darwin': ['clang++', 'g++'],
188
-'aix':    ['xlc++', 'g++', 'clang++'],
189
-'linux':  ['g++', 'clang++', 'icpc'],
190
-'sunos':  ['sunc++', 'g++'],
191
-'irix':   ['g++'],
192
-'hpux':   ['g++'],
193
-'osf1V':  ['g++'],
194
-'gnu':    ['g++', 'clang++'],
195
-'java':   ['g++', 'msvc', 'clang++', 'icpc'],
196
-'default': ['clang++', 'g++']
197
+'win32':       ['msvc', 'g++', 'clang++'],
198
+'cygwin':      ['g++', 'clang++'],
199
+'darwin':      ['clang++', 'g++'],
200
+'aix':         ['xlc++', 'g++', 'clang++'],
201
+'linux':       ['g++', 'clang++', 'icpc'],
202
+'sunos':       ['sunc++', 'g++'],
203
+'irix':        ['g++'],
204
+'hpux':        ['g++'],
205
+'osf1V':       ['g++'],
206
+'gnu':         ['g++', 'clang++'],
207
+'java':        ['g++', 'msvc', 'clang++', 'icpc'],
208
+'gnukfreebsd': ['g++', 'clang++'],
209
+'default':     ['clang++', 'g++']
210
 }
211
 """
212
 Dict mapping the platform names to Waf tools finding specific C++ compilers::
213
diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py
214
index 07442561dff..fb641e5e20d 100644
215
--- third_party/waf/waflib/Tools/python.py
216
+++ third_party/waf/waflib/Tools/python.py
217
@@ -416,9 +416,14 @@ def check_python_headers(conf, features='pyembed pyext'):
218
 
219
 		if not result:
220
 			path = [os.path.join(dct['prefix'], "libs")]
221
-			conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY name rather than pythonX.Y (win32)\n")
222
+			conf.to_log("\n\n# try again with -L$prefix/libs, and pythonXY rather than pythonX.Y (win32)\n")
223
 			result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $prefix/libs' % name)
224
 
225
+		if not result:
226
+			path = [os.path.normpath(os.path.join(dct['INCLUDEPY'], '..', 'libs'))]
227
+			conf.to_log("\n\n# try again with -L$INCLUDEPY/../libs, and pythonXY rather than pythonX.Y (win32)\n")
228
+			result = conf.check(lib=name, uselib='PYEMBED', libpath=path, mandatory=False, msg='Checking for library %s in $INCLUDEPY/../libs' % name)
229
+
230
 		if result:
231
 			break # do not forget to set LIBPATH_PYEMBED
232
 
233
diff --git third_party/waf/waflib/Tools/qt5.py third_party/waf/waflib/Tools/qt5.py
234
index 82c83e18c8a..b3e61325e50 100644
235
--- third_party/waf/waflib/Tools/qt5.py
236
+++ third_party/waf/waflib/Tools/qt5.py
237
@@ -783,8 +783,8 @@ def set_qt5_libs_to_check(self):
238
 			pat = self.env.cxxstlib_PATTERN
239
 		if Utils.unversioned_sys_platform() == 'darwin':
240
 			pat = r"%s\.framework"
241
-		re_qt = re.compile(pat % 'Qt5?(?P<name>\\D+)' + '$')
242
-		for x in dirlst:
243
+		re_qt = re.compile(pat % 'Qt5?(?P<name>\\w+)' + '$')
244
+		for x in sorted(dirlst):
245
 			m = re_qt.match(x)
246
 			if m:
247
 				self.qt5_vars.append("Qt5%s" % m.group('name'))
248
diff --git third_party/waf/waflib/Tools/winres.py third_party/waf/waflib/Tools/winres.py
249
index 9be1ed66009..73c0e95315b 100644
250
--- third_party/waf/waflib/Tools/winres.py
251
+++ third_party/waf/waflib/Tools/winres.py
252
@@ -4,10 +4,12 @@
253
 
254
 "Process *.rc* files for C/C++: X{.rc -> [.res|.rc.o]}"
255
 
256
+import os
257
 import re
258
 from waflib import Task
259
 from waflib.TaskGen import extension
260
 from waflib.Tools import c_preproc
261
+from waflib import Utils
262
 
263
 @extension('.rc')
264
 def rc_file(self, node):
265
@@ -61,6 +63,39 @@ class winrc(Task.Task):
266
 		tmp.start(self.inputs[0], self.env)
267
 		return (tmp.nodes, tmp.names)
268
 
269
+	def exec_command(self, cmd, **kw):
270
+		if self.env.WINRC_TGT_F == '/fo':
271
+			# Since winres include paths may contain spaces, they do not fit in
272
+			# response files and are best passed as environment variables
273
+			replace_cmd = []
274
+			incpaths = []
275
+			while cmd:
276
+				# filter include path flags
277
+				flag = cmd.pop(0)
278
+				if flag.upper().startswith('/I'):
279
+					if len(flag) == 2:
280
+						incpaths.append(cmd.pop(0))
281
+					else:
282
+						incpaths.append(flag[2:])
283
+				else:
284
+					replace_cmd.append(flag)
285
+			cmd = replace_cmd
286
+			if incpaths:
287
+				# append to existing environment variables in INCLUDE
288
+				env = kw['env'] = dict(kw.get('env') or self.env.env or os.environ)
289
+				pre_includes = env.get('INCLUDE', '')
290
+				env['INCLUDE'] = pre_includes + os.pathsep + os.pathsep.join(incpaths)
291
+
292
+		return super(winrc, self).exec_command(cmd, **kw)
293
+
294
+	def quote_flag(self, flag):
295
+		if self.env.WINRC_TGT_F == '/fo':
296
+			# winres does not support quotes around flags in response files
297
+			return flag
298
+
299
+		return super(winrc, self).quote_flag(flag)
300
+
301
+
302
 def configure(conf):
303
 	"""
304
 	Detects the programs RC or windres, depending on the C/C++ compiler in use
305
diff --git third_party/waf/waflib/extras/clang_compilation_database.py third_party/waf/waflib/extras/clang_compilation_database.py
306
index 17f66949376..bd29db93fd5 100644
307
--- third_party/waf/waflib/extras/clang_compilation_database.py
308
+++ third_party/waf/waflib/extras/clang_compilation_database.py
309
@@ -126,7 +126,7 @@ def patch_execute():
310
 		Invoke clangdb command before build
311
 		"""
312
 		if self.cmd.startswith('build'):
313
-			Scripting.run_command('clangdb')
314
+			Scripting.run_command(self.cmd.replace('build','clangdb'))
315
 
316
 		old_execute_build(self)
317
 
318
diff --git third_party/waf/waflib/extras/classic_runner.py third_party/waf/waflib/extras/classic_runner.py
319
new file mode 100644
320
index 00000000000..b08c794e880
321
--- /dev/null
322
+++ third_party/waf/waflib/extras/classic_runner.py
323
@@ -0,0 +1,68 @@
324
+#!/usr/bin/env python
325
+# encoding: utf-8
326
+# Thomas Nagy, 2021 (ita)
327
+
328
+from waflib import Utils, Runner
329
+
330
+"""
331
+Re-enable the classic threading system from waf 1.x
332
+
333
+def configure(conf):
334
+	conf.load('classic_runner')
335
+"""
336
+
337
+class TaskConsumer(Utils.threading.Thread):
338
+	"""
339
+	Task consumers belong to a pool of workers
340
+
341
+	They wait for tasks in the queue and then use ``task.process(...)``
342
+	"""
343
+	def __init__(self, spawner):
344
+		Utils.threading.Thread.__init__(self)
345
+		"""
346
+		Obtain :py:class:`waflib.Task.TaskBase` instances from this queue.
347
+		"""
348
+		self.spawner = spawner
349
+		self.daemon = True
350
+		self.start()
351
+
352
+	def run(self):
353
+		"""
354
+		Loop over the tasks to execute
355
+		"""
356
+		try:
357
+			self.loop()
358
+		except Exception:
359
+			pass
360
+
361
+	def loop(self):
362
+		"""
363
+		Obtain tasks from :py:attr:`waflib.Runner.TaskConsumer.ready` and call
364
+		:py:meth:`waflib.Task.TaskBase.process`. If the object is a function, execute it.
365
+		"""
366
+		master = self.spawner.master
367
+		while 1:
368
+			if not master.stop:
369
+				try:
370
+					tsk = master.ready.get()
371
+					if tsk:
372
+						tsk.log_display(tsk.generator.bld)
373
+						master.process_task(tsk)
374
+					else:
375
+						break
376
+				finally:
377
+					master.out.put(tsk)
378
+
379
+class Spawner(object):
380
+	"""
381
+	Daemon thread that consumes tasks from :py:class:`waflib.Runner.Parallel` producer and
382
+	spawns a consuming thread :py:class:`waflib.Runner.Consumer` for each
383
+	:py:class:`waflib.Task.Task` instance.
384
+	"""
385
+	def __init__(self, master):
386
+		self.master = master
387
+		""":py:class:`waflib.Runner.Parallel` producer instance"""
388
+
389
+		self.pool = [TaskConsumer(self) for i in range(master.numjobs)]
390
+
391
+Runner.Spawner = Spawner
392
diff --git third_party/waf/waflib/extras/color_gcc.py third_party/waf/waflib/extras/color_gcc.py
393
index b68c5ebf2df..09729035fec 100644
394
--- third_party/waf/waflib/extras/color_gcc.py
395
+++ third_party/waf/waflib/extras/color_gcc.py
396
@@ -19,7 +19,7 @@ class ColorGCCFormatter(Logs.formatter):
397
 			func = frame.f_code.co_name
398
 			if func == 'exec_command':
399
 				cmd = frame.f_locals.get('cmd')
400
-				if isinstance(cmd, list) and ('gcc' in cmd[0] or 'g++' in cmd[0]):
401
+				if isinstance(cmd, list) and (len(cmd) > 0) and ('gcc' in cmd[0] or 'g++' in cmd[0]):
402
 					lines = []
403
 					for line in rec.msg.splitlines():
404
 						if 'warning: ' in line:
405
diff --git third_party/waf/waflib/extras/eclipse.py third_party/waf/waflib/extras/eclipse.py
406
index bb787416e9f..49ca9686b7b 100644
407
--- third_party/waf/waflib/extras/eclipse.py
408
+++ third_party/waf/waflib/extras/eclipse.py
409
@@ -10,6 +10,9 @@ Usage:
410
 def options(opt):
411
 	opt.load('eclipse')
412
 
413
+To add additional targets beside standard ones (configure, dist, install, check)
414
+the environment ECLIPSE_EXTRA_TARGETS can be set (ie. to ['test', 'lint', 'docs'])
415
+
416
 $ waf configure eclipse
417
 """
418
 
419
@@ -25,6 +28,8 @@ cdt_core = oe_cdt + '.core'
420
 cdt_bld = oe_cdt + '.build.core'
421
 extbuilder_dir = '.externalToolBuilders'
422
 extbuilder_name = 'Waf_Builder.launch'
423
+settings_dir = '.settings'
424
+settings_name = 'language.settings.xml'
425
 
426
 class eclipse(Build.BuildContext):
427
 	cmd = 'eclipse'
428
@@ -131,9 +136,11 @@ class eclipse(Build.BuildContext):
429
 					path = p.path_from(self.srcnode)
430
 
431
 					if (path.startswith("/")):
432
-						cpppath.append(path)
433
+						if path not in cpppath:
434
+							cpppath.append(path)
435
 					else:
436
-						workspace_includes.append(path)
437
+						if path not in workspace_includes:
438
+							workspace_includes.append(path)
439
 
440
 					if is_cc and path not in source_dirs:
441
 						source_dirs.append(path)
442
@@ -156,6 +163,61 @@ class eclipse(Build.BuildContext):
443
 			project = self.impl_create_javaproject(javasrcpath, javalibpath)
444
 			self.write_conf_to_xml('.classpath', project)
445
 
446
+		# Create editor language settings to have correct standards applied in IDE, as per project configuration
447
+		try:
448
+			os.mkdir(settings_dir)
449
+		except OSError:
450
+			pass	# Ignore if dir already exists
451
+
452
+		lang_settings = Document()
453
+		project = lang_settings.createElement('project')
454
+
455
+		# Language configurations for C and C++ via cdt
456
+		if hasc:
457
+			configuration = self.add(lang_settings, project, 'configuration',
458
+							{'id' : 'org.eclipse.cdt.core.default.config.1', 'name': 'Default'})
459
+
460
+			extension = self.add(lang_settings, configuration, 'extension', {'point': 'org.eclipse.cdt.core.LanguageSettingsProvider'})
461
+
462
+			provider = self.add(lang_settings, extension, 'provider',
463
+							{ 'copy-of': 'extension',
464
+							  'id': 'org.eclipse.cdt.ui.UserLanguageSettingsProvider'})
465
+
466
+			provider = self.add(lang_settings, extension, 'provider-reference',
467
+							{ 'id': 'org.eclipse.cdt.core.ReferencedProjectsLanguageSettingsProvider',
468
+							  'ref': 'shared-provider'})
469
+
470
+			provider = self.add(lang_settings, extension, 'provider-reference',
471
+							{ 'id': 'org.eclipse.cdt.managedbuilder.core.MBSLanguageSettingsProvider',
472
+							  'ref': 'shared-provider'})
473
+
474
+			# C and C++ are kept as separated providers so appropriate flags are used also in mixed projects
475
+			if self.env.CC:
476
+				provider = self.add(lang_settings, extension, 'provider',
477
+							{ 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector',
478
+							  'console': 'false',
479
+							  'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.1',
480
+							  'keep-relative-paths' : 'false',
481
+							  'name': 'CDT GCC Built-in Compiler Settings',
482
+							  'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CC[0],' '.join(self.env['CFLAGS'])),
483
+							  'prefer-non-shared': 'true' })
484
+
485
+				self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.gcc'})
486
+
487
+			if self.env.CXX:
488
+				provider = self.add(lang_settings, extension, 'provider',
489
+							{ 'class': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector',
490
+							  'console': 'false',
491
+							  'id': 'org.eclipse.cdt.managedbuilder.language.settings.providers.GCCBuiltinSpecsDetector.2',
492
+							  'keep-relative-paths' : 'false',
493
+							  'name': 'CDT GCC Built-in Compiler Settings',
494
+							  'parameter': '%s %s ${FLAGS} -E -P -v -dD "${INPUTS}"'%(self.env.CXX[0],' '.join(self.env['CXXFLAGS'])),
495
+							  'prefer-non-shared': 'true' })
496
+				self.add(lang_settings, provider, 'language-scope', { 'id': 'org.eclipse.cdt.core.g++'})
497
+
498
+		lang_settings.appendChild(project)
499
+		self.write_conf_to_xml('%s%s%s'%(settings_dir, os.path.sep, settings_name), lang_settings)
500
+
501
 	def impl_create_project(self, executable, appname, hasc, hasjava, haspython, waf_executable):
502
 		doc = Document()
503
 		projectDescription = doc.createElement('projectDescription')
504
@@ -341,6 +403,8 @@ class eclipse(Build.BuildContext):
505
 		addTargetWrap('dist', False)
506
 		addTargetWrap('install', False)
507
 		addTargetWrap('check', False)
508
+		for addTgt in self.env.ECLIPSE_EXTRA_TARGETS or []:
509
+			addTargetWrap(addTgt, False)
510
 
511
 		storageModule = self.add(doc, cproject, 'storageModule',
512
 							{'moduleId': 'cdtBuildSystem',
513
@@ -348,6 +412,12 @@ class eclipse(Build.BuildContext):
514
 
515
 		self.add(doc, storageModule, 'project', {'id': '%s.null.1'%appname, 'name': appname})
516
 
517
+		storageModule = self.add(doc, cproject, 'storageModule',
518
+							{'moduleId': 'org.eclipse.cdt.core.LanguageSettingsProviders'})
519
+
520
+		storageModule = self.add(doc, cproject, 'storageModule',
521
+							{'moduleId': 'scannerConfiguration'})
522
+
523
 		doc.appendChild(cproject)
524
 		return doc
525
 
526
diff --git third_party/waf/waflib/extras/gccdeps.py third_party/waf/waflib/extras/gccdeps.py
527
index 1fc9373489a..9e9952f2f7d 100644
528
--- third_party/waf/waflib/extras/gccdeps.py
529
+++ third_party/waf/waflib/extras/gccdeps.py
530
@@ -29,13 +29,6 @@ if not c_preproc.go_absolute:
531
 # Third-party tools are allowed to add extra names in here with append()
532
 supported_compilers = ['gas', 'gcc', 'icc', 'clang']
533
 
534
-def scan(self):
535
-	if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS:
536
-		return super(self.derived_gccdeps, self).scan()
537
-	nodes = self.generator.bld.node_deps.get(self.uid(), [])
538
-	names = []
539
-	return (nodes, names)
540
-
541
 re_o = re.compile(r"\.o$")
542
 re_splitter = re.compile(r'(?<!\\)\s+') # split by space, except when spaces are escaped
543
 
544
@@ -61,28 +54,30 @@ def path_to_node(base_node, path, cached_nodes):
545
 	else:
546
 		# Not hashable, assume it is a list and join into a string
547
 		node_lookup_key = (base_node, os.path.sep.join(path))
548
+
549
 	try:
550
-		lock.acquire()
551
 		node = cached_nodes[node_lookup_key]
552
 	except KeyError:
553
-		node = base_node.find_resource(path)
554
-		cached_nodes[node_lookup_key] = node
555
-	finally:
556
-		lock.release()
557
+		# retry with lock on cache miss
558
+		with lock:
559
+			try:
560
+				node = cached_nodes[node_lookup_key]
561
+			except KeyError:
562
+				node = cached_nodes[node_lookup_key] = base_node.find_resource(path)
563
+
564
 	return node
565
 
566
 def post_run(self):
567
 	if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS:
568
 		return super(self.derived_gccdeps, self).post_run()
569
 
570
-	name = self.outputs[0].abspath()
571
-	name = re_o.sub('.d', name)
572
+	deps_filename = self.outputs[0].abspath()
573
+	deps_filename = re_o.sub('.d', deps_filename)
574
 	try:
575
-		txt = Utils.readf(name)
576
+		deps_txt = Utils.readf(deps_filename)
577
 	except EnvironmentError:
578
 		Logs.error('Could not find a .d dependency file, are cflags/cxxflags overwritten?')
579
 		raise
580
-	#os.remove(name)
581
 
582
 	# Compilers have the choice to either output the file's dependencies
583
 	# as one large Makefile rule:
584
@@ -102,15 +97,16 @@ def post_run(self):
585
 	# So the first step is to sanitize the input by stripping out the left-
586
 	# hand side of all these lines. After that, whatever remains are the
587
 	# implicit dependencies of task.outputs[0]
588
-	txt = '\n'.join([remove_makefile_rule_lhs(line) for line in txt.splitlines()])
589
+	deps_txt = '\n'.join([remove_makefile_rule_lhs(line) for line in deps_txt.splitlines()])
590
 
591
 	# Now join all the lines together
592
-	txt = txt.replace('\\\n', '')
593
+	deps_txt = deps_txt.replace('\\\n', '')
594
 
595
-	val = txt.strip()
596
-	val = [x.replace('\\ ', ' ') for x in re_splitter.split(val) if x]
597
+	dep_paths = deps_txt.strip()
598
+	dep_paths = [x.replace('\\ ', ' ') for x in re_splitter.split(dep_paths) if x]
599
 
600
-	nodes = []
601
+	resolved_nodes = []
602
+	unresolved_names = []
603
 	bld = self.generator.bld
604
 
605
 	# Dynamically bind to the cache
606
@@ -119,39 +115,41 @@ def post_run(self):
607
 	except AttributeError:
608
 		cached_nodes = bld.cached_nodes = {}
609
 
610
-	for x in val:
611
+	for path in dep_paths:
612
 
613
 		node = None
614
-		if os.path.isabs(x):
615
-			node = path_to_node(bld.root, x, cached_nodes)
616
+		if os.path.isabs(path):
617
+			node = path_to_node(bld.root, path, cached_nodes)
618
 		else:
619
 			# TODO waf 1.9 - single cwd value
620
-			path = getattr(bld, 'cwdx', bld.bldnode)
621
+			base_node = getattr(bld, 'cwdx', bld.bldnode)
622
 			# when calling find_resource, make sure the path does not contain '..'
623
-			x = [k for k in Utils.split_path(x) if k and k != '.']
624
-			while '..' in x:
625
-				idx = x.index('..')
626
+			path = [k for k in Utils.split_path(path) if k and k != '.']
627
+			while '..' in path:
628
+				idx = path.index('..')
629
 				if idx == 0:
630
-					x = x[1:]
631
-					path = path.parent
632
+					path = path[1:]
633
+					base_node = base_node.parent
634
 				else:
635
-					del x[idx]
636
-					del x[idx-1]
637
+					del path[idx]
638
+					del path[idx-1]
639
 
640
-			node = path_to_node(path, x, cached_nodes)
641
+			node = path_to_node(base_node, path, cached_nodes)
642
 
643
 		if not node:
644
-			raise ValueError('could not find %r for %r' % (x, self))
645
+			raise ValueError('could not find %r for %r' % (path, self))
646
+
647
 		if id(node) == id(self.inputs[0]):
648
 			# ignore the source file, it is already in the dependencies
649
 			# this way, successful config tests may be retrieved from the cache
650
 			continue
651
-		nodes.append(node)
652
 
653
-	Logs.debug('deps: gccdeps for %s returned %s', self, nodes)
654
+		resolved_nodes.append(node)
655
 
656
-	bld.node_deps[self.uid()] = nodes
657
-	bld.raw_deps[self.uid()] = []
658
+	Logs.debug('deps: gccdeps for %s returned %s', self, resolved_nodes)
659
+
660
+	bld.node_deps[self.uid()] = resolved_nodes
661
+	bld.raw_deps[self.uid()] = unresolved_names
662
 
663
 	try:
664
 		del self.cache_sig
665
@@ -160,6 +158,14 @@ def post_run(self):
666
 
667
 	Task.Task.post_run(self)
668
 
669
+def scan(self):
670
+	if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS:
671
+		return super(self.derived_gccdeps, self).scan()
672
+
673
+	resolved_nodes = self.generator.bld.node_deps.get(self.uid(), [])
674
+	unresolved_names = []
675
+	return (resolved_nodes, unresolved_names)
676
+
677
 def sig_implicit_deps(self):
678
 	if not self.__class__.__name__ in self.env.ENABLE_GCCDEPS:
679
 		return super(self.derived_gccdeps, self).sig_implicit_deps()
680
diff --git third_party/waf/waflib/extras/msvcdeps.py third_party/waf/waflib/extras/msvcdeps.py
681
index 52985dce058..e8985bde7c7 100644
682
--- third_party/waf/waflib/extras/msvcdeps.py
683
+++ third_party/waf/waflib/extras/msvcdeps.py
684
@@ -32,7 +32,6 @@ from waflib.Tools import c_preproc, c, cxx, msvc
685
 from waflib.TaskGen import feature, before_method
686
 
687
 lock = threading.Lock()
688
-nodes = {} # Cache the path -> Node lookup
689
 
690
 PREPROCESSOR_FLAG = '/showIncludes'
691
 INCLUDE_PATTERN = 'Note: including file:'
692
@@ -50,23 +49,47 @@ def apply_msvcdeps_flags(taskgen):
693
 		if taskgen.env.get_flat(flag).find(PREPROCESSOR_FLAG) < 0:
694
 			taskgen.env.append_value(flag, PREPROCESSOR_FLAG)
695
 
696
+
697
+def get_correct_path_case(base_path, path):
698
+	'''
699
+	Return a case-corrected version of ``path`` by searching the filesystem for
700
+	``path``, relative to ``base_path``, using the case returned by the filesystem.
701
+	'''
702
+	components = Utils.split_path(path)
703
+
704
+	corrected_path = ''
705
+	if os.path.isabs(path):
706
+		corrected_path = components.pop(0).upper() + os.sep
707
+
708
+	for part in components:
709
+		part = part.lower()
710
+		search_path = os.path.join(base_path, corrected_path)
711
+		if part == '..':
712
+			corrected_path = os.path.join(corrected_path, part)
713
+			search_path = os.path.normpath(search_path)
714
+			continue
715
+
716
+		for item in sorted(os.listdir(search_path)):
717
+			if item.lower() == part:
718
+				corrected_path = os.path.join(corrected_path, item)
719
+				break
720
+		else:
721
+			raise ValueError("Can't find %r in %r" % (part, search_path))
722
+
723
+	return corrected_path
724
+
725
+
726
 def path_to_node(base_node, path, cached_nodes):
727
 	'''
728
 	Take the base node and the path and return a node
729
 	Results are cached because searching the node tree is expensive
730
 	The following code is executed by threads, it is not safe, so a lock is needed...
731
 	'''
732
-	# normalize the path because ant_glob() does not understand
733
-	# parent path components (..)
734
+	# normalize the path to remove parent path components (..)
735
 	path = os.path.normpath(path)
736
 
737
 	# normalize the path case to increase likelihood of a cache hit
738
-	path = os.path.normcase(path)
739
-
740
-	# ant_glob interprets [] and () characters, so those must be replaced
741
-	path = path.replace('[', '?').replace(']', '?').replace('(', '[(]').replace(')', '[)]')
742
-
743
-	node_lookup_key = (base_node, path)
744
+	node_lookup_key = (base_node, os.path.normcase(path))
745
 
746
 	try:
747
 		node = cached_nodes[node_lookup_key]
748
@@ -76,8 +99,8 @@ def path_to_node(base_node, path, cached_nodes):
749
 			try:
750
 				node = cached_nodes[node_lookup_key]
751
 			except KeyError:
752
-				node_list = base_node.ant_glob([path], ignorecase=True, remove=False, quiet=True, regex=False)
753
-				node = cached_nodes[node_lookup_key] = node_list[0] if node_list else None
754
+				path = get_correct_path_case(base_node.abspath(), path)
755
+				node = cached_nodes[node_lookup_key] = base_node.find_node(path)
756
 
757
 	return node
758
 
759
@@ -89,9 +112,9 @@ def post_run(self):
760
 	if getattr(self, 'cached', None):
761
 		return Task.Task.post_run(self)
762
 
763
-	bld = self.generator.bld
764
-	unresolved_names = []
765
 	resolved_nodes = []
766
+	unresolved_names = []
767
+	bld = self.generator.bld
768
 
769
 	# Dynamically bind to the cache
770
 	try:
771
@@ -124,11 +147,14 @@ def post_run(self):
772
 					continue
773
 
774
 			if id(node) == id(self.inputs[0]):
775
-				# Self-dependency
776
+				# ignore the source file, it is already in the dependencies
777
+				# this way, successful config tests may be retrieved from the cache
778
 				continue
779
 
780
 			resolved_nodes.append(node)
781
 
782
+	Logs.debug('deps: msvcdeps for %s returned %s', self, resolved_nodes)
783
+
784
 	bld.node_deps[self.uid()] = resolved_nodes
785
 	bld.raw_deps[self.uid()] = unresolved_names
786
 
787
diff --git third_party/waf/waflib/extras/msvs.py third_party/waf/waflib/extras/msvs.py
788
index 8aa2db0b751..03b739f849c 100644
789
--- third_party/waf/waflib/extras/msvs.py
790
+++ third_party/waf/waflib/extras/msvs.py
791
@@ -787,8 +787,12 @@ class msvs_generator(BuildContext):
792
 		self.collect_dirs()
793
 		default_project = getattr(self, 'default_project', None)
794
 		def sortfun(x):
795
-			if x.name == default_project:
796
+			# folders should sort to the top
797
+			if getattr(x, 'VS_GUID_SOLUTIONFOLDER', None):
798
 				return ''
799
+			# followed by the default project
800
+			elif x.name == default_project:
801
+				return ' '
802
 			return getattr(x, 'path', None) and x.path.win32path() or x.name
803
 		self.all_projects.sort(key=sortfun)
804
 
805
diff --git third_party/waf/waflib/extras/swig.py third_party/waf/waflib/extras/swig.py
806
index 740ab46d963..967caeb5a82 100644
807
--- third_party/waf/waflib/extras/swig.py
808
+++ third_party/waf/waflib/extras/swig.py
809
@@ -17,7 +17,7 @@ tasks have to be added dynamically:
810
 
811
 SWIG_EXTS = ['.swig', '.i']
812
 
813
-re_module = re.compile(r'%module(?:\s*\(.*\))?\s+(.+)', re.M)
814
+re_module = re.compile(r'%module(?:\s*\(.*\))?\s+([^\r\n]+)', re.M)
815
 
816
 re_1 = re.compile(r'^%module.*?\s+([\w]+)\s*?$', re.M)
817
 re_2 = re.compile(r'[#%](?:include|import(?:\(module=".*"\))+|python(?:begin|code)) [<"](.*)[">]', re.M)
818
diff --git third_party/waf/waflib/extras/wafcache.py third_party/waf/waflib/extras/wafcache.py
819
index cc23fcd6673..2cef46c0e1c 100644
820
--- third_party/waf/waflib/extras/wafcache.py
821
+++ third_party/waf/waflib/extras/wafcache.py
822
@@ -258,6 +258,19 @@ def build(bld):
823
 	"""
824
 	Called during the build process to enable file caching
825
 	"""
826
+	if WAFCACHE_STATS:
827
+		# Init counter for statistics and hook to print results at the end
828
+		bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0
829
+
830
+		def printstats(bld):
831
+			hit_ratio = 0
832
+			if bld.cache_reqs > 0:
833
+				hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100
834
+			Logs.pprint('CYAN', '  wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' %
835
+					 (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) )
836
+
837
+		bld.add_post_fun(printstats)
838
+
839
 	if process_pool:
840
 		# already called once
841
 		return
842
@@ -273,19 +286,6 @@ def build(bld):
843
 	for x in reversed(list(Task.classes.values())):
844
 		make_cached(x)
845
 
846
-	if WAFCACHE_STATS:
847
-		# Init counter for statistics and hook to print results at the end
848
-		bld.cache_reqs = bld.cache_hits = bld.cache_puts = 0
849
-
850
-		def printstats(bld):
851
-			hit_ratio = 0
852
-			if bld.cache_reqs > 0:
853
-				hit_ratio = (bld.cache_hits / bld.cache_reqs) * 100
854
-			Logs.pprint('CYAN', '  wafcache stats: requests: %s, hits, %s, ratio: %.2f%%, writes %s' %
855
-					 (bld.cache_reqs, bld.cache_hits, hit_ratio, bld.cache_puts) )
856
-
857
-		bld.add_post_fun(printstats)
858
-
859
 def cache_command(sig, files_from, files_to):
860
 	"""
861
 	Create a command for cache worker processes, returns a pickled
862
diff --git third_party/waf/waflib/fixpy2.py third_party/waf/waflib/fixpy2.py
863
index 24176e06645..c99bff4b9ae 100644
864
--- third_party/waf/waflib/fixpy2.py
865
+++ third_party/waf/waflib/fixpy2.py
866
@@ -56,7 +56,7 @@ def r1(code):
867
 @subst('Runner.py')
868
 def r4(code):
869
 	"generator syntax"
870
-	return code.replace('next(self.biter)', 'self.biter.next()')
871
+	return code.replace('next(self.biter)', 'self.biter.next()').replace('self.daemon = True', 'self.setDaemon(1)')
872
 
873
 @subst('Context.py')
874
 def r5(code):
875
-- 
876
2.37.3
877
(-)b/net/samba413/files/patch-waf-2.0.24 (+164 lines)
Added Link Here
1
From d19dfe1efb2f6cb0dcf0a63b957df584d8ed5945 Mon Sep 17 00:00:00 2001
2
From: Andreas Schneider <asn@samba.org>
3
Date: Mon, 23 May 2022 07:54:06 +0200
4
Subject: [PATCH] third_party: Update waf to version 2.0.24
5
6
This fixes building of python libraries with Python 3.11!
7
8
BUG: https://bugzilla.samba.org/show_bug.cgi?id=15071
9
10
Signed-off-by: Andreas Schneider <asn@samba.org>
11
Reviewed-by: Stefan Metzmacher <metze@samba.org>
12
13
Autobuild-User(master): Andreas Schneider <asn@cryptomilk.org>
14
Autobuild-Date(master): Mon May 23 09:34:51 UTC 2022 on sn-devel-184
15
---
16
 buildtools/bin/waf                     |  2 +-
17
 buildtools/wafsamba/wafsamba.py        |  2 +-
18
 third_party/waf/waflib/Context.py      |  8 ++++----
19
 third_party/waf/waflib/Tools/ccroot.py |  1 +
20
 third_party/waf/waflib/Tools/msvc.py   | 17 ++++++++++++++++-
21
 third_party/waf/waflib/Tools/python.py |  4 ++--
22
 third_party/waf/waflib/Tools/tex.py    |  1 +
23
 7 files changed, 26 insertions(+), 9 deletions(-)
24
25
diff --git buildtools/bin/waf buildtools/bin/waf
26
index 2001ccdbd8a..d9cba343623 100755
27
--- buildtools/bin/waf
28
+++ buildtools/bin/waf
29
@@ -32,7 +32,7 @@ POSSIBILITY OF SUCH DAMAGE.
30
 
31
 import os, sys, inspect
32
 
33
-VERSION="2.0.23"
34
+VERSION="2.0.24"
35
 REVISION="x"
36
 GIT="x"
37
 INSTALL="x"
38
diff --git buildtools/wafsamba/wafsamba.py buildtools/wafsamba/wafsamba.py
39
index 4bd4e9f7fe3..79fe8b5e575 100644
40
--- buildtools/wafsamba/wafsamba.py
41
+++ buildtools/wafsamba/wafsamba.py
42
@@ -38,7 +38,7 @@ LIB_PATH="shared"
43
 
44
 os.environ['PYTHONUNBUFFERED'] = '1'
45
 
46
-if Context.HEXVERSION not in (0x2001700,):
47
+if Context.HEXVERSION not in (0x2001800,):
48
     Logs.error('''
49
 Please use the version of waf that comes with Samba, not
50
 a system installed version. See http://wiki.samba.org/index.php/Waf
51
diff --git third_party/waf/waflib/Context.py third_party/waf/waflib/Context.py
52
index 36d1ca74fef..4a0130b24a0 100644
53
--- third_party/waf/waflib/Context.py
54
+++ third_party/waf/waflib/Context.py
55
@@ -18,13 +18,13 @@ else:
56
 	import imp
57
 
58
 # the following 3 constants are updated on each new release (do not touch)
59
-HEXVERSION=0x2001700
60
+HEXVERSION=0x2001800
61
 """Constant updated on new releases"""
62
 
63
-WAFVERSION="2.0.23"
64
+WAFVERSION="2.0.24"
65
 """Constant updated on new releases"""
66
 
67
-WAFREVISION="cc6b34cf555d354c34f554c41206134072588de7"
68
+WAFREVISION="1af97c71f5a6756abf36d0f78ed8fd551596d7cb"
69
 """Git revision when the waf version is updated"""
70
 
71
 WAFNAME="waf"
72
@@ -144,7 +144,7 @@ class Context(ctx):
73
 	:type fun: string
74
 
75
 	.. inheritance-diagram:: waflib.Context.Context waflib.Build.BuildContext waflib.Build.InstallContext waflib.Build.UninstallContext waflib.Build.StepContext waflib.Build.ListContext waflib.Configure.ConfigurationContext waflib.Scripting.Dist waflib.Scripting.DistCheck waflib.Build.CleanContext
76
-
77
+	   :top-classes: waflib.Context.Context
78
 	"""
79
 
80
 	errors = Errors
81
diff --git third_party/waf/waflib/Tools/ccroot.py third_party/waf/waflib/Tools/ccroot.py
82
index 579d5b2b72b..76deff54dcb 100644
83
--- third_party/waf/waflib/Tools/ccroot.py
84
+++ third_party/waf/waflib/Tools/ccroot.py
85
@@ -128,6 +128,7 @@ class link_task(Task.Task):
86
 	Base class for all link tasks. A task generator is supposed to have at most one link task bound in the attribute *link_task*. See :py:func:`waflib.Tools.ccroot.apply_link`.
87
 
88
 	.. inheritance-diagram:: waflib.Tools.ccroot.stlink_task waflib.Tools.c.cprogram waflib.Tools.c.cshlib waflib.Tools.cxx.cxxstlib  waflib.Tools.cxx.cxxprogram waflib.Tools.cxx.cxxshlib waflib.Tools.d.dprogram waflib.Tools.d.dshlib waflib.Tools.d.dstlib waflib.Tools.ccroot.fake_shlib waflib.Tools.ccroot.fake_stlib waflib.Tools.asm.asmprogram waflib.Tools.asm.asmshlib waflib.Tools.asm.asmstlib
89
+	  :top-classes: waflib.Tools.ccroot.link_task
90
 	"""
91
 	color   = 'YELLOW'
92
 
93
diff --git third_party/waf/waflib/Tools/msvc.py third_party/waf/waflib/Tools/msvc.py
94
index 0c4703aaee9..026a4c7fc48 100644
95
--- third_party/waf/waflib/Tools/msvc.py
96
+++ third_party/waf/waflib/Tools/msvc.py
97
@@ -109,6 +109,21 @@ def options(opt):
98
 	opt.add_option('--msvc_targets', type='string', help = 'msvc targets, eg: "x64,arm"', default='')
99
 	opt.add_option('--no-msvc-lazy', action='store_false', help = 'lazily check msvc target environments', default=True, dest='msvc_lazy')
100
 
101
+class MSVCVersion(object):
102
+	def __init__(self, ver):
103
+		m = re.search('^(.*)\s+(\d+[.]\d+)', ver)
104
+		if m:
105
+			self.name = m.group(1)
106
+			self.number = float(m.group(2))
107
+		else:
108
+			self.name = ver
109
+			self.number = 0.
110
+
111
+	def __lt__(self, other):
112
+		if self.number == other.number:
113
+			return self.name < other.name
114
+		return self.number < other.number
115
+
116
 @conf
117
 def setup_msvc(conf, versiondict):
118
 	"""
119
@@ -125,7 +140,7 @@ def setup_msvc(conf, versiondict):
120
 		platforms=Utils.to_list(conf.env.MSVC_TARGETS) or [i for i,j in all_msvc_platforms+all_icl_platforms+all_wince_platforms]
121
 	desired_versions = getattr(Options.options, 'msvc_version', '').split(',')
122
 	if desired_versions == ['']:
123
-		desired_versions = conf.env.MSVC_VERSIONS or list(reversed(sorted(versiondict.keys())))
124
+		desired_versions = conf.env.MSVC_VERSIONS or list(sorted(versiondict.keys(), key=MSVCVersion, reverse=True))
125
 
126
 	# Override lazy detection by evaluating after the fact.
127
 	lazy_detect = getattr(Options.options, 'msvc_lazy', True)
128
diff --git third_party/waf/waflib/Tools/python.py third_party/waf/waflib/Tools/python.py
129
index fb641e5e20d..a23bd019335 100644
130
--- third_party/waf/waflib/Tools/python.py
131
+++ third_party/waf/waflib/Tools/python.py
132
@@ -315,7 +315,7 @@ def check_python_headers(conf, features='pyembed pyext'):
133
 		conf.fatal('Could not find the python executable')
134
 
135
 	# so we actually do all this for compatibility reasons and for obtaining pyext_PATTERN below
136
-	v = 'prefix SO LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split()
137
+	v = 'prefix SO EXT_SUFFIX LDFLAGS LIBDIR LIBPL INCLUDEPY Py_ENABLE_SHARED MACOSX_DEPLOYMENT_TARGET LDSHARED CFLAGS LDVERSION'.split()
138
 	try:
139
 		lst = conf.get_python_variables(["get_config_var('%s') or ''" % x for x in v])
140
 	except RuntimeError:
141
@@ -328,7 +328,7 @@ def check_python_headers(conf, features='pyembed pyext'):
142
 	x = 'MACOSX_DEPLOYMENT_TARGET'
143
 	if dct[x]:
144
 		env[x] = conf.environ[x] = str(dct[x])
145
-	env.pyext_PATTERN = '%s' + dct['SO'] # not a mistake
146
+	env.pyext_PATTERN = '%s' + (dct['EXT_SUFFIX'] or dct['SO']) # SO is deprecated in 3.5 and removed in 3.11
147
 
148
 
149
 	# Try to get pythonX.Y-config
150
diff --git third_party/waf/waflib/Tools/tex.py third_party/waf/waflib/Tools/tex.py
151
index eaf9fdb5802..b4792c3fe87 100644
152
--- third_party/waf/waflib/Tools/tex.py
153
+++ third_party/waf/waflib/Tools/tex.py
154
@@ -90,6 +90,7 @@ class tex(Task.Task):
155
 	Compiles a tex/latex file.
156
 
157
 	.. inheritance-diagram:: waflib.Tools.tex.latex waflib.Tools.tex.xelatex waflib.Tools.tex.pdflatex
158
+	   :top-classes: waflib.Tools.tex.tex
159
 	"""
160
 
161
 	bibtex_fun, _ = Task.compile_fun('${BIBTEX} ${BIBTEXFLAGS} ${SRCFILE}', shell=False)
162
-- 
163
2.37.3
164
(-)b/net/samba413/pkg-plist.ad_dc (-2 lines)
Lines 5-11 sbin/samba_dnsupdate Link Here
5
sbin/samba_kcc
5
sbin/samba_kcc
6
sbin/samba_spnupdate
6
sbin/samba_spnupdate
7
sbin/samba_upgradedns
7
sbin/samba_upgradedns
8
sbin/samba-gpupdate
9
include/samba4/dcerpc_server.h
8
include/samba4/dcerpc_server.h
10
lib/samba4/libdcerpc-server.so
9
lib/samba4/libdcerpc-server.so
11
lib/samba4/libdcerpc-server.so.0
10
lib/samba4/libdcerpc-server.so.0
Lines 172-175 lib/samba4/private/libscavenge-dns-records-samba4.so Link Here
172
@dir %%DATADIR%%/setup/ad-schema
171
@dir %%DATADIR%%/setup/ad-schema
173
@dir %%DATADIR%%/setup
172
@dir %%DATADIR%%/setup
174
@dir %%DATADIR%%
173
@dir %%DATADIR%%
175
man/man8/samba-gpupdate.8.gz
(-)b/net/samba413/pkg-plist.python (-1 / +3 lines)
Lines 1-5 Link Here
1
bin/smbtorture
1
bin/smbtorture
2
sbin/samba-gpupdate
2
man/man1/smbtorture.1.gz
3
man/man1/smbtorture.1.gz
4
man/man8/samba-gpupdate.8.gz
3
include/samba4/policy.h
5
include/samba4/policy.h
4
lib/samba4/libsamba-policy%%PYTHON_EXT_SUFFIX%%.so
6
lib/samba4/libsamba-policy%%PYTHON_EXT_SUFFIX%%.so
5
lib/samba4/libsamba-policy%%PYTHON_EXT_SUFFIX%%.so.0
7
lib/samba4/libsamba-policy%%PYTHON_EXT_SUFFIX%%.so.0
Lines 258-263 lib/samba4/private/libsamba-python%%PYTHON_EXT_SUFFIX%%-samba4.so Link Here
258
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_base_test.py
260
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_base_test.py
259
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_tests.py
261
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_tests.py
260
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_tgs_tests.py
262
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kdc_tgs_tests.py
263
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/kpasswd_tests.py
261
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py
264
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/ms_kile_client_principal_lookup_tests.py
262
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/raw_testcase.py
265
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/raw_testcase.py
263
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/rfc4120_constants.py
266
%%PYTHON_SITELIBDIR%%/samba/tests/krb5/rfc4120_constants.py
264
- 

Return to bug 266641