1 |
From 76aae7405595ca76bc0419a97f4a69e0ed528b32 Mon Sep 17 00:00:00 2001 |
2 |
From: Stefan Metzmacher <metze@samba.org> |
3 |
Date: Thu, 29 Dec 2016 14:00:36 +0100 |
4 |
Subject: [PATCH 01/20] s4:gensec_gssapi: the value |
5 |
gensec_get_target_principal() should overwrite gensec_get_target_hostname() |
6 |
|
7 |
If gensec_get_target_principal() has a value, we no longer have to verify |
8 |
the gensec_get_target_hostname() value, it can be just an ipadress. |
9 |
|
10 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
11 |
Reviewed-by: Andreas Schneider <asn@samba.org> |
12 |
(cherry picked from commit 48bcca566ebb3a5385b15b0525d7fbdd06361e04) |
13 |
--- |
14 |
source4/auth/gensec/gensec_gssapi.c | 24 ++++++++++++++++++------ |
15 |
1 file changed, 18 insertions(+), 6 deletions(-) |
16 |
|
17 |
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c |
18 |
index a6c4019aa6f..3974c3d42a0 100644 |
19 |
--- a/source4/auth/gensec/gensec_gssapi.c |
20 |
+++ b/source4/auth/gensec/gensec_gssapi.c |
21 |
@@ -307,7 +307,15 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi |
22 |
gss_buffer_desc name_token; |
23 |
gss_OID name_type; |
24 |
OM_uint32 maj_stat, min_stat; |
25 |
+ const char *target_principal = NULL; |
26 |
const char *hostname = gensec_get_target_hostname(gensec_security); |
27 |
+ const char *service = gensec_get_target_service(gensec_security); |
28 |
+ const char *realm = cli_credentials_get_realm(creds); |
29 |
+ |
30 |
+ target_principal = gensec_get_target_principal(gensec_security); |
31 |
+ if (target_principal != NULL) { |
32 |
+ goto do_start; |
33 |
+ } |
34 |
|
35 |
if (!hostname) { |
36 |
DEBUG(3, ("No hostname for target computer passed in, cannot use kerberos for this connection\n")); |
37 |
@@ -322,6 +330,8 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi |
38 |
return NT_STATUS_INVALID_PARAMETER; |
39 |
} |
40 |
|
41 |
+do_start: |
42 |
+ |
43 |
nt_status = gensec_gssapi_start(gensec_security); |
44 |
if (!NT_STATUS_IS_OK(nt_status)) { |
45 |
return nt_status; |
46 |
@@ -333,16 +343,18 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi |
47 |
gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); |
48 |
} |
49 |
|
50 |
- gensec_gssapi_state->target_principal = gensec_get_target_principal(gensec_security); |
51 |
- if (gensec_gssapi_state->target_principal) { |
52 |
+ if (target_principal != NULL) { |
53 |
name_type = GSS_C_NULL_OID; |
54 |
} else { |
55 |
- gensec_gssapi_state->target_principal = talloc_asprintf(gensec_gssapi_state, "%s/%s@%s", |
56 |
- gensec_get_target_service(gensec_security), |
57 |
- hostname, cli_credentials_get_realm(creds)); |
58 |
- |
59 |
+ target_principal = talloc_asprintf(gensec_gssapi_state, |
60 |
+ "%s/%s@%s", service, hostname, realm); |
61 |
+ if (target_principal == NULL) { |
62 |
+ return NT_STATUS_NO_MEMORY; |
63 |
+ } |
64 |
name_type = GSS_C_NT_USER_NAME; |
65 |
} |
66 |
+ gensec_gssapi_state->target_principal = target_principal; |
67 |
+ |
68 |
name_token.value = discard_const_p(uint8_t, gensec_gssapi_state->target_principal); |
69 |
name_token.length = strlen(gensec_gssapi_state->target_principal); |
70 |
|
71 |
-- |
72 |
2.12.0 |
73 |
|
74 |
|
75 |
From 12d74cd165db3603ba2f3a58343e9a82fb22ee93 Mon Sep 17 00:00:00 2001 |
76 |
From: Stefan Metzmacher <metze@samba.org> |
77 |
Date: Thu, 29 Dec 2016 15:20:00 +0100 |
78 |
Subject: [PATCH 02/20] s4:gensec_gssapi: require a realm in |
79 |
gensec_gssapi_client_start() |
80 |
|
81 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
82 |
Reviewed-by: Andreas Schneider <asn@samba.org> |
83 |
(cherry picked from commit 3a870baee8d9dbe5359f04a108814afc27e57d46) |
84 |
--- |
85 |
source4/auth/gensec/gensec_gssapi.c | 10 ++++++++++ |
86 |
1 file changed, 10 insertions(+) |
87 |
|
88 |
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c |
89 |
index 3974c3d42a0..957cfa4229d 100644 |
90 |
--- a/source4/auth/gensec/gensec_gssapi.c |
91 |
+++ b/source4/auth/gensec/gensec_gssapi.c |
92 |
@@ -330,6 +330,16 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi |
93 |
return NT_STATUS_INVALID_PARAMETER; |
94 |
} |
95 |
|
96 |
+ if (realm == NULL) { |
97 |
+ const char *cred_name = cli_credentials_get_unparsed_name(creds, |
98 |
+ gensec_security); |
99 |
+ DEBUG(3, ("cli_credentials(%s) without realm, " |
100 |
+ "cannot use kerberos for this connection %s/%s\n", |
101 |
+ cred_name, service, hostname)); |
102 |
+ talloc_free(discard_const_p(char, cred_name)); |
103 |
+ return NT_STATUS_INVALID_PARAMETER; |
104 |
+ } |
105 |
+ |
106 |
do_start: |
107 |
|
108 |
nt_status = gensec_gssapi_start(gensec_security); |
109 |
-- |
110 |
2.12.0 |
111 |
|
112 |
|
113 |
From beb9e4379333872ff1e5a3422ba70ccb409e9915 Mon Sep 17 00:00:00 2001 |
114 |
From: Andreas Schneider <asn@samba.org> |
115 |
Date: Mon, 6 Mar 2017 09:13:09 +0100 |
116 |
Subject: [PATCH 03/20] testprogs: Use smbclient by default in |
117 |
test_kinit_trusts |
118 |
|
119 |
This is the tool we use by default and we should test with it. |
120 |
|
121 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
122 |
|
123 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
124 |
Reviewed-by: Stefan Metzmacher <metze@samba.org> |
125 |
(cherry picked from commit 9b3ff90dbc5cc1017dfc89831a1081272e6c2356) |
126 |
--- |
127 |
testprogs/blackbox/test_kinit_trusts_heimdal.sh | 2 +- |
128 |
1 file changed, 1 insertion(+), 1 deletion(-) |
129 |
|
130 |
diff --git a/testprogs/blackbox/test_kinit_trusts_heimdal.sh b/testprogs/blackbox/test_kinit_trusts_heimdal.sh |
131 |
index 073e0e7517e..040bf919203 100755 |
132 |
--- a/testprogs/blackbox/test_kinit_trusts_heimdal.sh |
133 |
+++ b/testprogs/blackbox/test_kinit_trusts_heimdal.sh |
134 |
@@ -32,7 +32,7 @@ if test -x $samba4bindir/samba4kinit; then |
135 |
samba4kinit=$samba4bindir/samba4kinit |
136 |
fi |
137 |
|
138 |
-smbclient="$samba4bindir/smbclient4" |
139 |
+smbclient="$samba4bindir/smbclient" |
140 |
wbinfo="$samba4bindir/wbinfo" |
141 |
rpcclient="$samba4bindir/rpcclient" |
142 |
samba_tool="$samba4bindir/samba-tool" |
143 |
-- |
144 |
2.12.0 |
145 |
|
146 |
|
147 |
From 7feebdec869ed633bea612630ebca8d9b85a3e2e Mon Sep 17 00:00:00 2001 |
148 |
From: Andreas Schneider <asn@samba.org> |
149 |
Date: Mon, 6 Mar 2017 09:15:45 +0100 |
150 |
Subject: [PATCH 04/20] testprogs: Add kinit_trusts tests with smbclient4 |
151 |
|
152 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
153 |
|
154 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
155 |
Reviewed-by: Stefan Metzmacher <metze@samba.org> |
156 |
(cherry picked from commit 42bd003f468ab95b6ac97c774e2cd217d06c05ed) |
157 |
--- |
158 |
testprogs/blackbox/test_kinit_trusts_heimdal.sh | 8 ++++++++ |
159 |
1 file changed, 8 insertions(+) |
160 |
|
161 |
diff --git a/testprogs/blackbox/test_kinit_trusts_heimdal.sh b/testprogs/blackbox/test_kinit_trusts_heimdal.sh |
162 |
index 040bf919203..e67f77361a4 100755 |
163 |
--- a/testprogs/blackbox/test_kinit_trusts_heimdal.sh |
164 |
+++ b/testprogs/blackbox/test_kinit_trusts_heimdal.sh |
165 |
@@ -52,8 +52,16 @@ rm -rf $KRB5CCNAME_PATH |
166 |
echo $TRUST_PASSWORD > $PREFIX/tmppassfile |
167 |
testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` |
168 |
test_smbclient "Test login with user kerberos ccache" 'ls' "$unc" -k yes || failed=`expr $failed + 1` |
169 |
+rm -rf $KRB5CCNAME_PATH |
170 |
+ |
171 |
+# Test with smbclient4 |
172 |
+smbclient="$samba4bindir/smbclient4" |
173 |
+testit "kinit with password" $samba4kinit $enctype --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` |
174 |
+test_smbclient "Test login with user kerberos ccache (smbclient4)" 'ls' "$unc" -k yes || failed=`expr $failed + 1` |
175 |
+rm -rf $KRB5CCNAME_PATH |
176 |
|
177 |
testit "kinit with password (enterprise style)" $samba4kinit $enctype --enterprise --password-file=$PREFIX/tmppassfile --request-pac $TRUST_USERNAME@$TRUST_REALM || failed=`expr $failed + 1` |
178 |
+smbclient="$samba4bindir/smbclient" |
179 |
test_smbclient "Test login with user kerberos ccache" 'ls' "$unc" -k yes || failed=`expr $failed + 1` |
180 |
|
181 |
if test x"${TYPE}" = x"forest" ;then |
182 |
-- |
183 |
2.12.0 |
184 |
|
185 |
|
186 |
From cae7475df03e7d464dc8642a7a02dad388215d1e Mon Sep 17 00:00:00 2001 |
187 |
From: Andreas Schneider <asn@samba.org> |
188 |
Date: Wed, 8 Mar 2017 10:40:08 +0100 |
189 |
Subject: [PATCH 05/20] krb5_wrap: Do not return an empty realm from |
190 |
smb_krb5_get_realm_from_hostname() |
191 |
|
192 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
193 |
|
194 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
195 |
|
196 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
197 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
198 |
(cherry picked from commit 946f9dd1170be63b91e31ce825ea123f3c07329b) |
199 |
--- |
200 |
lib/krb5_wrap/krb5_samba.c | 4 +++- |
201 |
1 file changed, 3 insertions(+), 1 deletion(-) |
202 |
|
203 |
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c |
204 |
index 10b42dec53f..9dc7304d566 100644 |
205 |
--- a/lib/krb5_wrap/krb5_samba.c |
206 |
+++ b/lib/krb5_wrap/krb5_samba.c |
207 |
@@ -2691,7 +2691,9 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
208 |
goto out; |
209 |
} |
210 |
|
211 |
- if (realm_list && realm_list[0]) { |
212 |
+ if (realm_list != NULL && |
213 |
+ realm_list[0] != NULL && |
214 |
+ realm_list[0][0] != '\0') { |
215 |
realm = talloc_strdup(mem_ctx, realm_list[0]); |
216 |
} |
217 |
|
218 |
-- |
219 |
2.12.0 |
220 |
|
221 |
|
222 |
From 1d2b4a00e2a1213df81192e01f2d833ed4a6ec54 Mon Sep 17 00:00:00 2001 |
223 |
From: Andreas Schneider <asn@samba.org> |
224 |
Date: Wed, 8 Mar 2017 10:48:52 +0100 |
225 |
Subject: [PATCH 06/20] krb5_wrap: Try to guess the correct realm from the |
226 |
service hostname |
227 |
|
228 |
If we do not get a realm mapping from the krb5.conf or from the Kerberos |
229 |
library try to guess it from the service hostname. The guessing of the |
230 |
realm from the service hostname is already implemented in Heimdal. This |
231 |
makes the behavior of smb_krb5_get_realm_from_hostname() consistent |
232 |
with both MIT and Heimdal. |
233 |
|
234 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
235 |
|
236 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
237 |
|
238 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
239 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
240 |
(cherry picked from commit 65228925ab3c4da4ae299f77cae219fc7d37cc68) |
241 |
--- |
242 |
lib/krb5_wrap/krb5_samba.c | 13 +++++++++++++ |
243 |
1 file changed, 13 insertions(+) |
244 |
|
245 |
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c |
246 |
index 9dc7304d566..f8ef9f1df0f 100644 |
247 |
--- a/lib/krb5_wrap/krb5_samba.c |
248 |
+++ b/lib/krb5_wrap/krb5_samba.c |
249 |
@@ -2695,6 +2695,19 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
250 |
realm_list[0] != NULL && |
251 |
realm_list[0][0] != '\0') { |
252 |
realm = talloc_strdup(mem_ctx, realm_list[0]); |
253 |
+ } else { |
254 |
+ const char *p = NULL; |
255 |
+ |
256 |
+ /* |
257 |
+ * "dc6.samba2003.example.com" |
258 |
+ * returns a realm of "SAMBA2003.EXAMPLE.COM" |
259 |
+ * |
260 |
+ * "dc6." returns realm as NULL |
261 |
+ */ |
262 |
+ p = strchr_m(hostname, '.'); |
263 |
+ if (p != NULL && p[1] != '\0') { |
264 |
+ realm = talloc_strdup_upper(mem_ctx, p + 1); |
265 |
+ } |
266 |
} |
267 |
|
268 |
out: |
269 |
-- |
270 |
2.12.0 |
271 |
|
272 |
|
273 |
From 0e99683587c9047055ca6432fae0a11604710b69 Mon Sep 17 00:00:00 2001 |
274 |
From: Andreas Schneider <asn@samba.org> |
275 |
Date: Wed, 8 Mar 2017 11:56:30 +0100 |
276 |
Subject: [PATCH 07/20] krb5_wrap: pass client_realm to |
277 |
smb_krb5_get_realm_from_hostname() |
278 |
|
279 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
280 |
|
281 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
282 |
|
283 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
284 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
285 |
(cherry picked from commit f0c4fcace586197d5c170f6a9dcc175df23e3802) |
286 |
--- |
287 |
lib/krb5_wrap/krb5_samba.c | 16 ++++++++++++++-- |
288 |
1 file changed, 14 insertions(+), 2 deletions(-) |
289 |
|
290 |
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c |
291 |
index f8ef9f1df0f..36bcc65e22a 100644 |
292 |
--- a/lib/krb5_wrap/krb5_samba.c |
293 |
+++ b/lib/krb5_wrap/krb5_samba.c |
294 |
@@ -2664,7 +2664,8 @@ static char *smb_krb5_get_default_realm_from_ccache(TALLOC_CTX *mem_ctx) |
295 |
************************************************************************/ |
296 |
|
297 |
static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
298 |
- const char *hostname) |
299 |
+ const char *hostname, |
300 |
+ const char *client_realm) |
301 |
{ |
302 |
#if defined(HAVE_KRB5_REALM_TYPE) |
303 |
/* Heimdal. */ |
304 |
@@ -2695,6 +2696,9 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
305 |
realm_list[0] != NULL && |
306 |
realm_list[0][0] != '\0') { |
307 |
realm = talloc_strdup(mem_ctx, realm_list[0]); |
308 |
+ if (realm == NULL) { |
309 |
+ goto out; |
310 |
+ } |
311 |
} else { |
312 |
const char *p = NULL; |
313 |
|
314 |
@@ -2707,9 +2711,16 @@ static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
315 |
p = strchr_m(hostname, '.'); |
316 |
if (p != NULL && p[1] != '\0') { |
317 |
realm = talloc_strdup_upper(mem_ctx, p + 1); |
318 |
+ if (realm == NULL) { |
319 |
+ goto out; |
320 |
+ } |
321 |
} |
322 |
} |
323 |
|
324 |
+ if (realm == NULL) { |
325 |
+ realm = talloc_strdup(mem_ctx, client_realm); |
326 |
+ } |
327 |
+ |
328 |
out: |
329 |
|
330 |
if (ctx) { |
331 |
@@ -2752,7 +2763,8 @@ char *smb_krb5_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, |
332 |
if (host) { |
333 |
/* DNS name. */ |
334 |
realm = smb_krb5_get_realm_from_hostname(talloc_tos(), |
335 |
- remote_name); |
336 |
+ remote_name, |
337 |
+ default_realm); |
338 |
} else { |
339 |
/* NetBIOS name - use our realm. */ |
340 |
realm = smb_krb5_get_default_realm_from_ccache(talloc_tos()); |
341 |
-- |
342 |
2.12.0 |
343 |
|
344 |
|
345 |
From 6876b0d12f8aad4448f4a7d770db7ff129df6c50 Mon Sep 17 00:00:00 2001 |
346 |
From: Andreas Schneider <asn@samba.org> |
347 |
Date: Wed, 8 Mar 2017 11:56:30 +0100 |
348 |
Subject: [PATCH 08/20] krb5_wrap: Make smb_krb5_get_realm_from_hostname() |
349 |
public |
350 |
|
351 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
352 |
|
353 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
354 |
|
355 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
356 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
357 |
(cherry picked from commit 339a2ecb3f05d0c9e860a5dd59b8bdbc51d4ffa7) |
358 |
--- |
359 |
lib/krb5_wrap/krb5_samba.c | 28 +++++++++++++++++++++------- |
360 |
lib/krb5_wrap/krb5_samba.h | 4 ++++ |
361 |
2 files changed, 25 insertions(+), 7 deletions(-) |
362 |
|
363 |
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c |
364 |
index 36bcc65e22a..2b0ec6bfa0e 100644 |
365 |
--- a/lib/krb5_wrap/krb5_samba.c |
366 |
+++ b/lib/krb5_wrap/krb5_samba.c |
367 |
@@ -2659,13 +2659,27 @@ static char *smb_krb5_get_default_realm_from_ccache(TALLOC_CTX *mem_ctx) |
368 |
return realm; |
369 |
} |
370 |
|
371 |
-/************************************************************************ |
372 |
- Routine to get the realm from a given DNS name. |
373 |
-************************************************************************/ |
374 |
- |
375 |
-static char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
376 |
- const char *hostname, |
377 |
- const char *client_realm) |
378 |
+/** |
379 |
+ * @brief Get the realm from the service hostname. |
380 |
+ * |
381 |
+ * This function will look for a domain realm mapping in the [domain_realm] |
382 |
+ * section of the krb5.conf first and fallback to extract the realm from |
383 |
+ * the provided service hostname. As a last resort it will return the |
384 |
+ * provided client_realm. |
385 |
+ * |
386 |
+ * @param[in] mem_ctx The talloc context |
387 |
+ * |
388 |
+ * @param[in] hostname The service hostname |
389 |
+ * |
390 |
+ * @param[in] client_realm If we can not find a mapping, fall back to |
391 |
+ * this realm. |
392 |
+ * |
393 |
+ * @return The realm to use for the service hostname, NULL if a fatal error |
394 |
+ * occured. |
395 |
+ */ |
396 |
+char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
397 |
+ const char *hostname, |
398 |
+ const char *client_realm) |
399 |
{ |
400 |
#if defined(HAVE_KRB5_REALM_TYPE) |
401 |
/* Heimdal. */ |
402 |
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h |
403 |
index 71e81ea26e1..accae449a0e 100644 |
404 |
--- a/lib/krb5_wrap/krb5_samba.h |
405 |
+++ b/lib/krb5_wrap/krb5_samba.h |
406 |
@@ -314,6 +314,10 @@ krb5_error_code smb_krb5_principal_set_realm(krb5_context context, |
407 |
krb5_principal principal, |
408 |
const char *realm); |
409 |
|
410 |
+char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
411 |
+ const char *hostname, |
412 |
+ const char *client_realm); |
413 |
+ |
414 |
char *smb_krb5_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, |
415 |
const char *service, |
416 |
const char *remote_name, |
417 |
-- |
418 |
2.12.0 |
419 |
|
420 |
|
421 |
From 08a81c315129c3d07637a8a5064b4ef988864efd Mon Sep 17 00:00:00 2001 |
422 |
From: Andreas Schneider <asn@samba.org> |
423 |
Date: Mon, 6 Mar 2017 09:19:13 +0100 |
424 |
Subject: [PATCH 09/20] s4:gensec-gssapi: Create a helper function to setup |
425 |
server_principal |
426 |
|
427 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
428 |
|
429 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
430 |
|
431 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
432 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
433 |
(cherry picked from commit 8f7c4529420316b553c80cd3d19b6996525b029a) |
434 |
--- |
435 |
source4/auth/gensec/gensec_gssapi.c | 88 +++++++++++++++++++++++++------------ |
436 |
source4/auth/gensec/gensec_gssapi.h | 2 +- |
437 |
2 files changed, 61 insertions(+), 29 deletions(-) |
438 |
|
439 |
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c |
440 |
index 957cfa4229d..ec57d193714 100644 |
441 |
--- a/source4/auth/gensec/gensec_gssapi.c |
442 |
+++ b/source4/auth/gensec/gensec_gssapi.c |
443 |
@@ -83,6 +83,56 @@ static int gensec_gssapi_destructor(struct gensec_gssapi_state *gensec_gssapi_st |
444 |
return 0; |
445 |
} |
446 |
|
447 |
+static NTSTATUS gensec_gssapi_setup_server_principal(TALLOC_CTX *mem_ctx, |
448 |
+ const char *target_principal, |
449 |
+ const char *service, |
450 |
+ const char *hostname, |
451 |
+ const char *realm, |
452 |
+ const gss_OID mech, |
453 |
+ char **pserver_principal, |
454 |
+ gss_name_t *pserver_name) |
455 |
+{ |
456 |
+ char *server_principal = NULL; |
457 |
+ gss_buffer_desc name_token; |
458 |
+ gss_OID name_type; |
459 |
+ OM_uint32 maj_stat, min_stat = 0; |
460 |
+ |
461 |
+ if (target_principal != NULL) { |
462 |
+ server_principal = talloc_strdup(mem_ctx, target_principal); |
463 |
+ name_type = GSS_C_NULL_OID; |
464 |
+ } else { |
465 |
+ server_principal = talloc_asprintf(mem_ctx, |
466 |
+ "%s/%s@%s", |
467 |
+ service, hostname, realm); |
468 |
+ name_type = GSS_C_NT_USER_NAME; |
469 |
+ } |
470 |
+ if (server_principal == NULL) { |
471 |
+ return NT_STATUS_NO_MEMORY; |
472 |
+ } |
473 |
+ |
474 |
+ name_token.value = (uint8_t *)server_principal; |
475 |
+ name_token.length = strlen(server_principal); |
476 |
+ |
477 |
+ maj_stat = gss_import_name(&min_stat, |
478 |
+ &name_token, |
479 |
+ name_type, |
480 |
+ pserver_name); |
481 |
+ if (maj_stat) { |
482 |
+ DBG_WARNING("GSS Import name of %s failed: %s\n", |
483 |
+ server_principal, |
484 |
+ gssapi_error_string(mem_ctx, |
485 |
+ maj_stat, |
486 |
+ min_stat, |
487 |
+ mech)); |
488 |
+ TALLOC_FREE(server_principal); |
489 |
+ return NT_STATUS_INVALID_PARAMETER; |
490 |
+ } |
491 |
+ |
492 |
+ *pserver_principal = server_principal; |
493 |
+ |
494 |
+ return NT_STATUS_OK; |
495 |
+} |
496 |
+ |
497 |
static NTSTATUS gensec_gssapi_start(struct gensec_security *gensec_security) |
498 |
{ |
499 |
struct gensec_gssapi_state *gensec_gssapi_state; |
500 |
@@ -304,9 +354,6 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi |
501 |
struct gensec_gssapi_state *gensec_gssapi_state; |
502 |
struct cli_credentials *creds = gensec_get_credentials(gensec_security); |
503 |
NTSTATUS nt_status; |
504 |
- gss_buffer_desc name_token; |
505 |
- gss_OID name_type; |
506 |
- OM_uint32 maj_stat, min_stat; |
507 |
const char *target_principal = NULL; |
508 |
const char *hostname = gensec_get_target_hostname(gensec_security); |
509 |
const char *service = gensec_get_target_service(gensec_security); |
510 |
@@ -353,31 +400,16 @@ do_start: |
511 |
gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); |
512 |
} |
513 |
|
514 |
- if (target_principal != NULL) { |
515 |
- name_type = GSS_C_NULL_OID; |
516 |
- } else { |
517 |
- target_principal = talloc_asprintf(gensec_gssapi_state, |
518 |
- "%s/%s@%s", service, hostname, realm); |
519 |
- if (target_principal == NULL) { |
520 |
- return NT_STATUS_NO_MEMORY; |
521 |
- } |
522 |
- name_type = GSS_C_NT_USER_NAME; |
523 |
- } |
524 |
- gensec_gssapi_state->target_principal = target_principal; |
525 |
- |
526 |
- name_token.value = discard_const_p(uint8_t, gensec_gssapi_state->target_principal); |
527 |
- name_token.length = strlen(gensec_gssapi_state->target_principal); |
528 |
- |
529 |
- |
530 |
- maj_stat = gss_import_name (&min_stat, |
531 |
- &name_token, |
532 |
- name_type, |
533 |
- &gensec_gssapi_state->server_name); |
534 |
- if (maj_stat) { |
535 |
- DEBUG(2, ("GSS Import name of %s failed: %s\n", |
536 |
- (char *)name_token.value, |
537 |
- gssapi_error_string(gensec_gssapi_state, maj_stat, min_stat, gensec_gssapi_state->gss_oid))); |
538 |
- return NT_STATUS_INVALID_PARAMETER; |
539 |
+ nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, |
540 |
+ target_principal, |
541 |
+ service, |
542 |
+ hostname, |
543 |
+ realm, |
544 |
+ gensec_gssapi_state->gss_oid, |
545 |
+ &gensec_gssapi_state->target_principal, |
546 |
+ &gensec_gssapi_state->server_name); |
547 |
+ if (!NT_STATUS_IS_OK(nt_status)) { |
548 |
+ return nt_status; |
549 |
} |
550 |
|
551 |
return NT_STATUS_OK; |
552 |
diff --git a/source4/auth/gensec/gensec_gssapi.h b/source4/auth/gensec/gensec_gssapi.h |
553 |
index cf0e3a8d914..d788b5ebc38 100644 |
554 |
--- a/source4/auth/gensec/gensec_gssapi.h |
555 |
+++ b/source4/auth/gensec/gensec_gssapi.h |
556 |
@@ -65,5 +65,5 @@ struct gensec_gssapi_state { |
557 |
int gss_exchange_count; |
558 |
size_t sig_size; |
559 |
|
560 |
- const char *target_principal; |
561 |
+ char *target_principal; |
562 |
}; |
563 |
-- |
564 |
2.12.0 |
565 |
|
566 |
|
567 |
From 78a76c53e9b0e7caf67a43eeb7929a4fe94fa25e Mon Sep 17 00:00:00 2001 |
568 |
From: Andreas Schneider <asn@samba.org> |
569 |
Date: Wed, 8 Mar 2017 12:34:59 +0100 |
570 |
Subject: [PATCH 10/20] s4:gensec_gssapi: Move setup of service_principal to |
571 |
update function |
572 |
|
573 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
574 |
|
575 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
576 |
|
577 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
578 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
579 |
(cherry picked from commit bf6358bf035e7ad48bd15cc2164afab2a19e7ad6) |
580 |
--- |
581 |
source4/auth/gensec/gensec_gssapi.c | 33 ++++++++++++++++++++------------- |
582 |
1 file changed, 20 insertions(+), 13 deletions(-) |
583 |
|
584 |
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c |
585 |
index ec57d193714..6cb4431e0d9 100644 |
586 |
--- a/source4/auth/gensec/gensec_gssapi.c |
587 |
+++ b/source4/auth/gensec/gensec_gssapi.c |
588 |
@@ -400,18 +400,6 @@ do_start: |
589 |
gensec_gssapi_state->gss_want_flags &= ~(GSS_C_DELEG_FLAG|GSS_C_DELEG_POLICY_FLAG); |
590 |
} |
591 |
|
592 |
- nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, |
593 |
- target_principal, |
594 |
- service, |
595 |
- hostname, |
596 |
- realm, |
597 |
- gensec_gssapi_state->gss_oid, |
598 |
- &gensec_gssapi_state->target_principal, |
599 |
- &gensec_gssapi_state->server_name); |
600 |
- if (!NT_STATUS_IS_OK(nt_status)) { |
601 |
- return nt_status; |
602 |
- } |
603 |
- |
604 |
return NT_STATUS_OK; |
605 |
} |
606 |
|
607 |
@@ -452,7 +440,11 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
608 |
OM_uint32 min_stat2; |
609 |
gss_buffer_desc input_token = { 0, NULL }; |
610 |
gss_buffer_desc output_token = { 0, NULL }; |
611 |
- |
612 |
+ struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security); |
613 |
+ const char *target_principal = gensec_get_target_principal(gensec_security); |
614 |
+ const char *hostname = gensec_get_target_hostname(gensec_security); |
615 |
+ const char *service = gensec_get_target_service(gensec_security); |
616 |
+ const char *client_realm = cli_credentials_get_realm(cli_creds); |
617 |
gss_OID gss_oid_p = NULL; |
618 |
OM_uint32 time_req = 0; |
619 |
OM_uint32 time_rec = 0; |
620 |
@@ -491,6 +483,21 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
621 |
return NT_STATUS_INTERNAL_ERROR; |
622 |
} |
623 |
#endif |
624 |
+ |
625 |
+ if (gensec_gssapi_state->server_name == NULL) { |
626 |
+ nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, |
627 |
+ target_principal, |
628 |
+ service, |
629 |
+ hostname, |
630 |
+ client_realm, |
631 |
+ gensec_gssapi_state->gss_oid, |
632 |
+ &gensec_gssapi_state->target_principal, |
633 |
+ &gensec_gssapi_state->server_name); |
634 |
+ if (!NT_STATUS_IS_OK(nt_status)) { |
635 |
+ return nt_status; |
636 |
+ } |
637 |
+ } |
638 |
+ |
639 |
maj_stat = gss_init_sec_context(&min_stat, |
640 |
gensec_gssapi_state->client_cred->creds, |
641 |
&gensec_gssapi_state->gssapi_context, |
642 |
-- |
643 |
2.12.0 |
644 |
|
645 |
|
646 |
From 7541d4a3c1a665925c8d3aa97963729874c70761 Mon Sep 17 00:00:00 2001 |
647 |
From: Andreas Schneider <asn@samba.org> |
648 |
Date: Wed, 8 Mar 2017 11:03:17 +0100 |
649 |
Subject: [PATCH 11/20] s4:gensec_gssapi: Use |
650 |
smb_krb5_get_realm_from_hostname() |
651 |
|
652 |
With credentials for administrator@FOREST1.EXAMPLE.COM |
653 |
this patch changes the target_principal for |
654 |
the ldap service of host dc2.forest2.example.com |
655 |
from |
656 |
|
657 |
ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
658 |
|
659 |
to |
660 |
|
661 |
ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM |
662 |
|
663 |
Typically ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
664 |
should be used in order to allow the KDC of FOREST1.EXAMPLE.COM |
665 |
to generate a referral ticket for |
666 |
krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM. |
667 |
|
668 |
The problem is that KDCs only return such referral tickets |
669 |
if there's a forest trust between FOREST1.EXAMPLE.COM |
670 |
and FOREST2.EXAMPLE.COM. If there's only an external domain |
671 |
trust between FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM |
672 |
the KDC of FOREST1.EXAMPLE.COM will respond with S_PRINCIPAL_UNKNOWN |
673 |
when being asked for ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM. |
674 |
|
675 |
In the case of an external trust the client can still ask |
676 |
explicitly for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM |
677 |
and the KDC of FOREST1.EXAMPLE.COM will generate it. |
678 |
|
679 |
From there the client can use the |
680 |
krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM |
681 |
ticket and ask a KDC of FOREST2.EXAMPLE.COM for a |
682 |
service ticket for ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM. |
683 |
|
684 |
With Heimdal we'll get the fallback on S_PRINCIPAL_UNKNOWN behavior |
685 |
when we pass ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as |
686 |
target principal. As _krb5_get_cred_kdc_any() first calls |
687 |
get_cred_kdc_referral() (which always starts with the client realm) |
688 |
and falls back to get_cred_kdc_capath() (which starts with the given realm). |
689 |
|
690 |
MIT krb5 only tries the given realm of the target principal, |
691 |
if we want to autodetect support for transitive forest trusts, |
692 |
we'll have to do the fallback ourself. |
693 |
|
694 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
695 |
|
696 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
697 |
|
698 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
699 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
700 |
(cherry picked from commit 3781eb250173981a8890b82d1ff9358f144034cd) |
701 |
--- |
702 |
source4/auth/gensec/gensec_gssapi.c | 62 ++++++++++++++++++++++++++++++++++++- |
703 |
1 file changed, 61 insertions(+), 1 deletion(-) |
704 |
|
705 |
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c |
706 |
index 6cb4431e0d9..57392a04e60 100644 |
707 |
--- a/source4/auth/gensec/gensec_gssapi.c |
708 |
+++ b/source4/auth/gensec/gensec_gssapi.c |
709 |
@@ -445,6 +445,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
710 |
const char *hostname = gensec_get_target_hostname(gensec_security); |
711 |
const char *service = gensec_get_target_service(gensec_security); |
712 |
const char *client_realm = cli_credentials_get_realm(cli_creds); |
713 |
+ const char *server_realm = NULL; |
714 |
gss_OID gss_oid_p = NULL; |
715 |
OM_uint32 time_req = 0; |
716 |
OM_uint32 time_rec = 0; |
717 |
@@ -484,12 +485,71 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
718 |
} |
719 |
#endif |
720 |
|
721 |
+ /* |
722 |
+ * With credentials for |
723 |
+ * administrator@FOREST1.EXAMPLE.COM this patch changes |
724 |
+ * the target_principal for the ldap service of host |
725 |
+ * dc2.forest2.example.com from |
726 |
+ * |
727 |
+ * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
728 |
+ * |
729 |
+ * to |
730 |
+ * |
731 |
+ * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM |
732 |
+ * |
733 |
+ * Typically |
734 |
+ * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
735 |
+ * should be used in order to allow the KDC of |
736 |
+ * FOREST1.EXAMPLE.COM to generate a referral ticket |
737 |
+ * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM. |
738 |
+ * |
739 |
+ * The problem is that KDCs only return such referral |
740 |
+ * tickets if there's a forest trust between |
741 |
+ * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM. If |
742 |
+ * there's only an external domain trust between |
743 |
+ * FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC |
744 |
+ * of FOREST1.EXAMPLE.COM will respond with |
745 |
+ * S_PRINCIPAL_UNKNOWN when being asked for |
746 |
+ * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM. |
747 |
+ * |
748 |
+ * In the case of an external trust the client can |
749 |
+ * still ask explicitly for |
750 |
+ * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and |
751 |
+ * the KDC of FOREST1.EXAMPLE.COM will generate it. |
752 |
+ * |
753 |
+ * From there the client can use the |
754 |
+ * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM |
755 |
+ * ticket and ask a KDC of FOREST2.EXAMPLE.COM for a |
756 |
+ * service ticket for |
757 |
+ * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM. |
758 |
+ * |
759 |
+ * With Heimdal we'll get the fallback on |
760 |
+ * S_PRINCIPAL_UNKNOWN behavior when we pass |
761 |
+ * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as |
762 |
+ * target principal. As _krb5_get_cred_kdc_any() first |
763 |
+ * calls get_cred_kdc_referral() (which always starts |
764 |
+ * with the client realm) and falls back to |
765 |
+ * get_cred_kdc_capath() (which starts with the given |
766 |
+ * realm). |
767 |
+ * |
768 |
+ * MIT krb5 only tries the given realm of the target |
769 |
+ * principal, if we want to autodetect support for |
770 |
+ * transitive forest trusts, would have to do the |
771 |
+ * fallback ourself. |
772 |
+ */ |
773 |
if (gensec_gssapi_state->server_name == NULL) { |
774 |
+ server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state, |
775 |
+ hostname, |
776 |
+ client_realm); |
777 |
+ if (server_realm == NULL) { |
778 |
+ return NT_STATUS_NO_MEMORY; |
779 |
+ } |
780 |
+ |
781 |
nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, |
782 |
target_principal, |
783 |
service, |
784 |
hostname, |
785 |
- client_realm, |
786 |
+ server_realm, |
787 |
gensec_gssapi_state->gss_oid, |
788 |
&gensec_gssapi_state->target_principal, |
789 |
&gensec_gssapi_state->server_name); |
790 |
-- |
791 |
2.12.0 |
792 |
|
793 |
|
794 |
From 97935a1164d328b466bc305c37869e78d306173a Mon Sep 17 00:00:00 2001 |
795 |
From: Andreas Schneider <asn@samba.org> |
796 |
Date: Wed, 8 Mar 2017 13:10:05 +0100 |
797 |
Subject: [PATCH 12/20] s4:gensec_gssapi: Correctly handle external trusts with |
798 |
MIT |
799 |
|
800 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
801 |
|
802 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
803 |
|
804 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
805 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
806 |
(cherry picked from commit 2dd4887648bf006a577e03fc027e881738ca04ab) |
807 |
--- |
808 |
source4/auth/gensec/gensec_gssapi.c | 51 +++++++++++++++++++++++++++++++++++++ |
809 |
1 file changed, 51 insertions(+) |
810 |
|
811 |
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c |
812 |
index 57392a04e60..61911aae9d9 100644 |
813 |
--- a/source4/auth/gensec/gensec_gssapi.c |
814 |
+++ b/source4/auth/gensec/gensec_gssapi.c |
815 |
@@ -464,6 +464,7 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
816 |
switch (gensec_security->gensec_role) { |
817 |
case GENSEC_CLIENT: |
818 |
{ |
819 |
+ bool fallback = false; |
820 |
#ifdef SAMBA4_USES_HEIMDAL |
821 |
struct gsskrb5_send_to_kdc send_to_kdc; |
822 |
krb5_error_code ret; |
823 |
@@ -537,6 +538,48 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
824 |
* transitive forest trusts, would have to do the |
825 |
* fallback ourself. |
826 |
*/ |
827 |
+#ifndef SAMBA4_USES_HEIMDAL |
828 |
+ if (gensec_gssapi_state->server_name == NULL) { |
829 |
+ nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, |
830 |
+ target_principal, |
831 |
+ service, |
832 |
+ hostname, |
833 |
+ client_realm, |
834 |
+ gensec_gssapi_state->gss_oid, |
835 |
+ &gensec_gssapi_state->target_principal, |
836 |
+ &gensec_gssapi_state->server_name); |
837 |
+ if (!NT_STATUS_IS_OK(nt_status)) { |
838 |
+ return nt_status; |
839 |
+ } |
840 |
+ |
841 |
+ maj_stat = gss_init_sec_context(&min_stat, |
842 |
+ gensec_gssapi_state->client_cred->creds, |
843 |
+ &gensec_gssapi_state->gssapi_context, |
844 |
+ gensec_gssapi_state->server_name, |
845 |
+ gensec_gssapi_state->gss_oid, |
846 |
+ gensec_gssapi_state->gss_want_flags, |
847 |
+ time_req, |
848 |
+ gensec_gssapi_state->input_chan_bindings, |
849 |
+ &input_token, |
850 |
+ &gss_oid_p, |
851 |
+ &output_token, |
852 |
+ &gensec_gssapi_state->gss_got_flags, /* ret flags */ |
853 |
+ &time_rec); |
854 |
+ if (maj_stat != GSS_S_FAILURE) { |
855 |
+ goto init_sec_context_done; |
856 |
+ } |
857 |
+ if (min_stat != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) { |
858 |
+ goto init_sec_context_done; |
859 |
+ } |
860 |
+ if (target_principal != NULL) { |
861 |
+ goto init_sec_context_done; |
862 |
+ } |
863 |
+ |
864 |
+ fallback = true; |
865 |
+ TALLOC_FREE(gensec_gssapi_state->target_principal); |
866 |
+ gss_release_name(&min_stat2, &gensec_gssapi_state->server_name); |
867 |
+ } |
868 |
+#endif /* !SAMBA4_USES_HEIMDAL */ |
869 |
if (gensec_gssapi_state->server_name == NULL) { |
870 |
server_realm = smb_krb5_get_realm_from_hostname(gensec_gssapi_state, |
871 |
hostname, |
872 |
@@ -545,6 +588,11 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
873 |
return NT_STATUS_NO_MEMORY; |
874 |
} |
875 |
|
876 |
+ if (fallback && |
877 |
+ strequal(client_realm, server_realm)) { |
878 |
+ goto init_sec_context_done; |
879 |
+ } |
880 |
+ |
881 |
nt_status = gensec_gssapi_setup_server_principal(gensec_gssapi_state, |
882 |
target_principal, |
883 |
service, |
884 |
@@ -571,6 +619,9 @@ static NTSTATUS gensec_gssapi_update(struct gensec_security *gensec_security, |
885 |
&output_token, |
886 |
&gensec_gssapi_state->gss_got_flags, /* ret flags */ |
887 |
&time_rec); |
888 |
+ goto init_sec_context_done; |
889 |
+ /* JUMP! */ |
890 |
+init_sec_context_done: |
891 |
if (gss_oid_p) { |
892 |
gensec_gssapi_state->gss_oid = gss_oid_p; |
893 |
} |
894 |
-- |
895 |
2.12.0 |
896 |
|
897 |
|
898 |
From 71a49b84ebb8d45d91d21ebf92d3c7302b24f490 Mon Sep 17 00:00:00 2001 |
899 |
From: Andreas Schneider <asn@samba.org> |
900 |
Date: Thu, 9 Mar 2017 07:54:29 +0100 |
901 |
Subject: [PATCH 13/20] s3:gse: Use smb_krb5_get_realm_from_hostname() |
902 |
|
903 |
With credentials for administrator@FOREST1.EXAMPLE.COM |
904 |
this patch changes the target_principal for |
905 |
the ldap service of host dc2.forest2.example.com |
906 |
from |
907 |
|
908 |
ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
909 |
|
910 |
to |
911 |
|
912 |
ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM |
913 |
|
914 |
Typically ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
915 |
should be used in order to allow the KDC of FOREST1.EXAMPLE.COM |
916 |
to generate a referral ticket for |
917 |
krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM. |
918 |
|
919 |
The problem is that KDCs only return such referral tickets |
920 |
if there's a forest trust between FOREST1.EXAMPLE.COM |
921 |
and FOREST2.EXAMPLE.COM. If there's only an external domain |
922 |
trust between FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM |
923 |
the KDC of FOREST1.EXAMPLE.COM will respond with S_PRINCIPAL_UNKNOWN |
924 |
when being asked for ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM. |
925 |
|
926 |
In the case of an external trust the client can still ask |
927 |
explicitly for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM |
928 |
and the KDC of FOREST1.EXAMPLE.COM will generate it. |
929 |
|
930 |
From there the client can use the |
931 |
krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM |
932 |
ticket and ask a KDC of FOREST2.EXAMPLE.COM for a |
933 |
service ticket for ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM. |
934 |
|
935 |
With Heimdal we'll get the fallback on S_PRINCIPAL_UNKNOWN behavior |
936 |
when we pass ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as |
937 |
target principal. As _krb5_get_cred_kdc_any() first calls |
938 |
get_cred_kdc_referral() (which always starts with the client realm) |
939 |
and falls back to get_cred_kdc_capath() (which starts with the given realm). |
940 |
|
941 |
MIT krb5 only tries the given realm of the target principal, |
942 |
if we want to autodetect support for transitive forest trusts, |
943 |
we'll have to do the fallback ourself. |
944 |
|
945 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
946 |
|
947 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
948 |
|
949 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
950 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
951 |
(cherry picked from commit a3d95ed9037fb8b14a451da02dcadf011485ae34) |
952 |
--- |
953 |
source3/librpc/crypto/gse.c | 93 +++++++++++++++++++++++++++++++++------------ |
954 |
1 file changed, 68 insertions(+), 25 deletions(-) |
955 |
|
956 |
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c |
957 |
index abf20bc7dfd..57632f6cc8f 100644 |
958 |
--- a/source3/librpc/crypto/gse.c |
959 |
+++ b/source3/librpc/crypto/gse.c |
960 |
@@ -120,6 +120,54 @@ static int gse_context_destructor(void *ptr) |
961 |
return 0; |
962 |
} |
963 |
|
964 |
+static NTSTATUS gse_setup_server_principal(TALLOC_CTX *mem_ctx, |
965 |
+ const char *target_principal, |
966 |
+ const char *service, |
967 |
+ const char *hostname, |
968 |
+ const char *realm, |
969 |
+ char **pserver_principal, |
970 |
+ gss_name_t *pserver_name) |
971 |
+{ |
972 |
+ char *server_principal = NULL; |
973 |
+ gss_buffer_desc name_token; |
974 |
+ gss_OID name_type; |
975 |
+ OM_uint32 maj_stat, min_stat = 0; |
976 |
+ |
977 |
+ if (target_principal != NULL) { |
978 |
+ server_principal = talloc_strdup(mem_ctx, target_principal); |
979 |
+ name_type = GSS_C_NULL_OID; |
980 |
+ } else { |
981 |
+ server_principal = talloc_asprintf(mem_ctx, |
982 |
+ "%s/%s@%s", |
983 |
+ service, |
984 |
+ hostname, |
985 |
+ realm); |
986 |
+ name_type = GSS_C_NT_USER_NAME; |
987 |
+ } |
988 |
+ if (server_principal == NULL) { |
989 |
+ return NT_STATUS_NO_MEMORY; |
990 |
+ } |
991 |
+ |
992 |
+ name_token.value = (uint8_t *)server_principal; |
993 |
+ name_token.length = strlen(server_principal); |
994 |
+ |
995 |
+ maj_stat = gss_import_name(&min_stat, |
996 |
+ &name_token, |
997 |
+ name_type, |
998 |
+ pserver_name); |
999 |
+ if (maj_stat) { |
1000 |
+ DBG_WARNING("GSS Import name of %s failed: %s\n", |
1001 |
+ server_principal, |
1002 |
+ gse_errstr(mem_ctx, maj_stat, min_stat)); |
1003 |
+ TALLOC_FREE(server_principal); |
1004 |
+ return NT_STATUS_INVALID_PARAMETER; |
1005 |
+ } |
1006 |
+ |
1007 |
+ *pserver_principal = server_principal; |
1008 |
+ |
1009 |
+ return NT_STATUS_OK; |
1010 |
+} |
1011 |
+ |
1012 |
static NTSTATUS gse_context_init(TALLOC_CTX *mem_ctx, |
1013 |
bool do_sign, bool do_seal, |
1014 |
const char *ccache_name, |
1015 |
@@ -203,11 +251,12 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, |
1016 |
{ |
1017 |
struct gse_context *gse_ctx; |
1018 |
OM_uint32 gss_maj, gss_min; |
1019 |
- gss_buffer_desc name_buffer = GSS_C_EMPTY_BUFFER; |
1020 |
#ifdef HAVE_GSS_KRB5_CRED_NO_CI_FLAGS_X |
1021 |
gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; |
1022 |
gss_OID oid = discard_const(GSS_KRB5_CRED_NO_CI_FLAGS_X); |
1023 |
#endif |
1024 |
+ char *server_principal = NULL; |
1025 |
+ char *server_realm = NULL; |
1026 |
NTSTATUS status; |
1027 |
|
1028 |
if (!server || !service) { |
1029 |
@@ -223,30 +272,24 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, |
1030 |
|
1031 |
/* Guess the realm based on the supplied service, and avoid the GSS libs |
1032 |
doing DNS lookups which may fail. |
1033 |
- |
1034 |
- TODO: Loop with the KDC on some more combinations (local |
1035 |
- realm in particular), possibly falling back to |
1036 |
- GSS_C_NT_HOSTBASED_SERVICE |
1037 |
*/ |
1038 |
- name_buffer.value = |
1039 |
- smb_krb5_get_principal_from_service_hostname(gse_ctx, |
1040 |
- service, |
1041 |
- server, |
1042 |
- realm); |
1043 |
- if (!name_buffer.value) { |
1044 |
- status = NT_STATUS_NO_MEMORY; |
1045 |
- goto err_out; |
1046 |
+ server_realm = smb_krb5_get_realm_from_hostname(mem_ctx, |
1047 |
+ server, |
1048 |
+ realm); |
1049 |
+ if (server_realm == NULL) { |
1050 |
+ return NT_STATUS_NO_MEMORY; |
1051 |
} |
1052 |
- name_buffer.length = strlen((char *)name_buffer.value); |
1053 |
- gss_maj = gss_import_name(&gss_min, &name_buffer, |
1054 |
- GSS_C_NT_USER_NAME, |
1055 |
- &gse_ctx->server_name); |
1056 |
- if (gss_maj) { |
1057 |
- DEBUG(5, ("gss_import_name failed for %s, with [%s]\n", |
1058 |
- (char *)name_buffer.value, |
1059 |
- gse_errstr(gse_ctx, gss_maj, gss_min))); |
1060 |
- status = NT_STATUS_INTERNAL_ERROR; |
1061 |
- goto err_out; |
1062 |
+ |
1063 |
+ status = gse_setup_server_principal(mem_ctx, |
1064 |
+ NULL, |
1065 |
+ service, |
1066 |
+ server, |
1067 |
+ server_realm, |
1068 |
+ &server_principal, |
1069 |
+ &gse_ctx->server_name); |
1070 |
+ TALLOC_FREE(server_realm); |
1071 |
+ if (!NT_STATUS_IS_OK(status)) { |
1072 |
+ return status; |
1073 |
} |
1074 |
|
1075 |
/* TODO: get krb5 ticket using username/password, if no valid |
1076 |
@@ -299,11 +342,11 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, |
1077 |
#endif |
1078 |
|
1079 |
*_gse_ctx = gse_ctx; |
1080 |
- TALLOC_FREE(name_buffer.value); |
1081 |
+ TALLOC_FREE(server_principal); |
1082 |
return NT_STATUS_OK; |
1083 |
|
1084 |
err_out: |
1085 |
- TALLOC_FREE(name_buffer.value); |
1086 |
+ TALLOC_FREE(server_principal); |
1087 |
TALLOC_FREE(gse_ctx); |
1088 |
return status; |
1089 |
} |
1090 |
-- |
1091 |
2.12.0 |
1092 |
|
1093 |
|
1094 |
From 905cdd3ee1fea0bf0e2081da4489934944c55fa9 Mon Sep 17 00:00:00 2001 |
1095 |
From: Andreas Schneider <asn@samba.org> |
1096 |
Date: Thu, 9 Mar 2017 09:10:12 +0100 |
1097 |
Subject: [PATCH 14/20] krb5_wrap: Remove obsolete |
1098 |
smb_krb5_get_principal_from_service_hostname() |
1099 |
|
1100 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1101 |
|
1102 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
1103 |
Reviewed-by: Stefan Metzmacher <metze@samba.org> |
1104 |
(cherry picked from commit 804e828d52ec922f3970e847652ab1ee5538b9b0) |
1105 |
--- |
1106 |
lib/krb5_wrap/krb5_samba.c | 111 --------------------------------------------- |
1107 |
lib/krb5_wrap/krb5_samba.h | 5 -- |
1108 |
2 files changed, 116 deletions(-) |
1109 |
|
1110 |
diff --git a/lib/krb5_wrap/krb5_samba.c b/lib/krb5_wrap/krb5_samba.c |
1111 |
index 2b0ec6bfa0e..0b67ea52a19 100644 |
1112 |
--- a/lib/krb5_wrap/krb5_samba.c |
1113 |
+++ b/lib/krb5_wrap/krb5_samba.c |
1114 |
@@ -2604,61 +2604,6 @@ krb5_error_code smb_krb5_principal_set_realm(krb5_context context, |
1115 |
} |
1116 |
|
1117 |
|
1118 |
-/************************************************************************ |
1119 |
- Routine to get the default realm from the kerberos credentials cache. |
1120 |
- Caller must free if the return value is not NULL. |
1121 |
-************************************************************************/ |
1122 |
- |
1123 |
-static char *smb_krb5_get_default_realm_from_ccache(TALLOC_CTX *mem_ctx) |
1124 |
-{ |
1125 |
- char *realm = NULL; |
1126 |
- krb5_context ctx = NULL; |
1127 |
- krb5_ccache cc = NULL; |
1128 |
- krb5_principal princ = NULL; |
1129 |
- |
1130 |
- initialize_krb5_error_table(); |
1131 |
- if (krb5_init_context(&ctx)) { |
1132 |
- return NULL; |
1133 |
- } |
1134 |
- |
1135 |
- DEBUG(5,("kerberos_get_default_realm_from_ccache: " |
1136 |
- "Trying to read krb5 cache: %s\n", |
1137 |
- krb5_cc_default_name(ctx))); |
1138 |
- if (krb5_cc_default(ctx, &cc)) { |
1139 |
- DEBUG(5,("kerberos_get_default_realm_from_ccache: " |
1140 |
- "failed to read default cache\n")); |
1141 |
- goto out; |
1142 |
- } |
1143 |
- if (krb5_cc_get_principal(ctx, cc, &princ)) { |
1144 |
- DEBUG(5,("kerberos_get_default_realm_from_ccache: " |
1145 |
- "failed to get default principal\n")); |
1146 |
- goto out; |
1147 |
- } |
1148 |
- |
1149 |
-#if defined(HAVE_KRB5_PRINCIPAL_GET_REALM) |
1150 |
- realm = talloc_strdup(mem_ctx, krb5_principal_get_realm(ctx, princ)); |
1151 |
-#elif defined(HAVE_KRB5_PRINC_REALM) |
1152 |
- { |
1153 |
- krb5_data *realm_data = krb5_princ_realm(ctx, princ); |
1154 |
- realm = talloc_strndup(mem_ctx, realm_data->data, realm_data->length); |
1155 |
- } |
1156 |
-#endif |
1157 |
- |
1158 |
- out: |
1159 |
- |
1160 |
- if (ctx) { |
1161 |
- if (princ) { |
1162 |
- krb5_free_principal(ctx, princ); |
1163 |
- } |
1164 |
- if (cc) { |
1165 |
- krb5_cc_close(ctx, cc); |
1166 |
- } |
1167 |
- krb5_free_context(ctx); |
1168 |
- } |
1169 |
- |
1170 |
- return realm; |
1171 |
-} |
1172 |
- |
1173 |
/** |
1174 |
* @brief Get the realm from the service hostname. |
1175 |
* |
1176 |
@@ -2749,62 +2694,6 @@ char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
1177 |
} |
1178 |
|
1179 |
/** |
1180 |
- * @brief Get the principal as a string from the service hostname. |
1181 |
- * |
1182 |
- * @param[in] mem_ctx The talloc context |
1183 |
- * |
1184 |
- * @param[in] service The service name |
1185 |
- * |
1186 |
- * @param[in] remote_name The remote name |
1187 |
- * |
1188 |
- * @param[in] default_realm The default_realm if we cannot get it from the |
1189 |
- * hostname or netbios name. |
1190 |
- * |
1191 |
- * @return A talloc'ed principal string or NULL if an error occured. |
1192 |
- * |
1193 |
- * The caller needs to free the principal with talloc_free() if it isn't needed |
1194 |
- * anymore. |
1195 |
- */ |
1196 |
-char *smb_krb5_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, |
1197 |
- const char *service, |
1198 |
- const char *remote_name, |
1199 |
- const char *default_realm) |
1200 |
-{ |
1201 |
- char *realm = NULL; |
1202 |
- char *host = NULL; |
1203 |
- char *principal; |
1204 |
- host = strchr_m(remote_name, '.'); |
1205 |
- if (host) { |
1206 |
- /* DNS name. */ |
1207 |
- realm = smb_krb5_get_realm_from_hostname(talloc_tos(), |
1208 |
- remote_name, |
1209 |
- default_realm); |
1210 |
- } else { |
1211 |
- /* NetBIOS name - use our realm. */ |
1212 |
- realm = smb_krb5_get_default_realm_from_ccache(talloc_tos()); |
1213 |
- } |
1214 |
- |
1215 |
- if (realm == NULL || *realm == '\0') { |
1216 |
- realm = talloc_strdup(talloc_tos(), default_realm); |
1217 |
- if (!realm) { |
1218 |
- return NULL; |
1219 |
- } |
1220 |
- DEBUG(3,("Cannot get realm from, " |
1221 |
- "desthost %s or default ccache. Using default " |
1222 |
- "smb.conf realm %s\n", |
1223 |
- remote_name, |
1224 |
- realm)); |
1225 |
- } |
1226 |
- |
1227 |
- principal = talloc_asprintf(mem_ctx, |
1228 |
- "%s/%s@%s", |
1229 |
- service, remote_name, |
1230 |
- realm); |
1231 |
- TALLOC_FREE(realm); |
1232 |
- return principal; |
1233 |
-} |
1234 |
- |
1235 |
-/** |
1236 |
* @brief Get an error string from a Kerberos error code. |
1237 |
* |
1238 |
* @param[in] context The library context. |
1239 |
diff --git a/lib/krb5_wrap/krb5_samba.h b/lib/krb5_wrap/krb5_samba.h |
1240 |
index accae449a0e..c921538efcb 100644 |
1241 |
--- a/lib/krb5_wrap/krb5_samba.h |
1242 |
+++ b/lib/krb5_wrap/krb5_samba.h |
1243 |
@@ -318,11 +318,6 @@ char *smb_krb5_get_realm_from_hostname(TALLOC_CTX *mem_ctx, |
1244 |
const char *hostname, |
1245 |
const char *client_realm); |
1246 |
|
1247 |
-char *smb_krb5_get_principal_from_service_hostname(TALLOC_CTX *mem_ctx, |
1248 |
- const char *service, |
1249 |
- const char *remote_name, |
1250 |
- const char *default_realm); |
1251 |
- |
1252 |
char *smb_get_krb5_error_message(krb5_context context, |
1253 |
krb5_error_code code, |
1254 |
TALLOC_CTX *mem_ctx); |
1255 |
-- |
1256 |
2.12.0 |
1257 |
|
1258 |
|
1259 |
From 0ea7203430b580e93816035b8201ddd11346cd4e Mon Sep 17 00:00:00 2001 |
1260 |
From: Andreas Schneider <asn@samba.org> |
1261 |
Date: Mon, 6 Mar 2017 08:16:11 +0100 |
1262 |
Subject: [PATCH 15/20] s3:gse: Pass down the gensec_security pointer |
1263 |
|
1264 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1265 |
|
1266 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
1267 |
|
1268 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
1269 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
1270 |
(cherry picked from commit e6b1e58874de30d094f9bce474479cfddb39d3fc) |
1271 |
--- |
1272 |
source3/librpc/crypto/gse.c | 19 ++++++++++++------- |
1273 |
1 file changed, 12 insertions(+), 7 deletions(-) |
1274 |
|
1275 |
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c |
1276 |
index 57632f6cc8f..5a39522a828 100644 |
1277 |
--- a/source3/librpc/crypto/gse.c |
1278 |
+++ b/source3/librpc/crypto/gse.c |
1279 |
@@ -352,10 +352,13 @@ err_out: |
1280 |
} |
1281 |
|
1282 |
static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1283 |
- struct gse_context *gse_ctx, |
1284 |
+ struct gensec_security *gensec_security, |
1285 |
const DATA_BLOB *token_in, |
1286 |
DATA_BLOB *token_out) |
1287 |
{ |
1288 |
+ struct gse_context *gse_ctx = |
1289 |
+ talloc_get_type_abort(gensec_security->private_data, |
1290 |
+ struct gse_context); |
1291 |
OM_uint32 gss_maj, gss_min; |
1292 |
gss_buffer_desc in_data; |
1293 |
gss_buffer_desc out_data; |
1294 |
@@ -542,10 +545,13 @@ done: |
1295 |
} |
1296 |
|
1297 |
static NTSTATUS gse_get_server_auth_token(TALLOC_CTX *mem_ctx, |
1298 |
- struct gse_context *gse_ctx, |
1299 |
+ struct gensec_security *gensec_security, |
1300 |
const DATA_BLOB *token_in, |
1301 |
DATA_BLOB *token_out) |
1302 |
{ |
1303 |
+ struct gse_context *gse_ctx = |
1304 |
+ talloc_get_type_abort(gensec_security->private_data, |
1305 |
+ struct gse_context); |
1306 |
OM_uint32 gss_maj, gss_min; |
1307 |
gss_buffer_desc in_data; |
1308 |
gss_buffer_desc out_data; |
1309 |
@@ -762,17 +768,16 @@ static NTSTATUS gensec_gse_update(struct gensec_security *gensec_security, |
1310 |
const DATA_BLOB in, DATA_BLOB *out) |
1311 |
{ |
1312 |
NTSTATUS status; |
1313 |
- struct gse_context *gse_ctx = |
1314 |
- talloc_get_type_abort(gensec_security->private_data, |
1315 |
- struct gse_context); |
1316 |
|
1317 |
switch (gensec_security->gensec_role) { |
1318 |
case GENSEC_CLIENT: |
1319 |
- status = gse_get_client_auth_token(mem_ctx, gse_ctx, |
1320 |
+ status = gse_get_client_auth_token(mem_ctx, |
1321 |
+ gensec_security, |
1322 |
&in, out); |
1323 |
break; |
1324 |
case GENSEC_SERVER: |
1325 |
- status = gse_get_server_auth_token(mem_ctx, gse_ctx, |
1326 |
+ status = gse_get_server_auth_token(mem_ctx, |
1327 |
+ gensec_security, |
1328 |
&in, out); |
1329 |
break; |
1330 |
} |
1331 |
-- |
1332 |
2.12.0 |
1333 |
|
1334 |
|
1335 |
From 36b353247939414cd7f91abd27bfc553bd62c06f Mon Sep 17 00:00:00 2001 |
1336 |
From: Andreas Schneider <asn@samba.org> |
1337 |
Date: Thu, 9 Mar 2017 08:05:26 +0100 |
1338 |
Subject: [PATCH 16/20] s3:gse: Move setup of service_principal to update |
1339 |
function |
1340 |
|
1341 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1342 |
|
1343 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
1344 |
|
1345 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
1346 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
1347 |
(cherry picked from commit 3ba1ad1f8c7871070d0ecbe5d49c5c44afe98bbf) |
1348 |
--- |
1349 |
source3/librpc/crypto/gse.c | 97 +++++++++++++++++++++++++++++++++------------ |
1350 |
1 file changed, 71 insertions(+), 26 deletions(-) |
1351 |
|
1352 |
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c |
1353 |
index 5a39522a828..3580181061e 100644 |
1354 |
--- a/source3/librpc/crypto/gse.c |
1355 |
+++ b/source3/librpc/crypto/gse.c |
1356 |
@@ -255,8 +255,6 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, |
1357 |
gss_buffer_desc empty_buffer = GSS_C_EMPTY_BUFFER; |
1358 |
gss_OID oid = discard_const(GSS_KRB5_CRED_NO_CI_FLAGS_X); |
1359 |
#endif |
1360 |
- char *server_principal = NULL; |
1361 |
- char *server_realm = NULL; |
1362 |
NTSTATUS status; |
1363 |
|
1364 |
if (!server || !service) { |
1365 |
@@ -270,28 +268,6 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, |
1366 |
return NT_STATUS_NO_MEMORY; |
1367 |
} |
1368 |
|
1369 |
- /* Guess the realm based on the supplied service, and avoid the GSS libs |
1370 |
- doing DNS lookups which may fail. |
1371 |
- */ |
1372 |
- server_realm = smb_krb5_get_realm_from_hostname(mem_ctx, |
1373 |
- server, |
1374 |
- realm); |
1375 |
- if (server_realm == NULL) { |
1376 |
- return NT_STATUS_NO_MEMORY; |
1377 |
- } |
1378 |
- |
1379 |
- status = gse_setup_server_principal(mem_ctx, |
1380 |
- NULL, |
1381 |
- service, |
1382 |
- server, |
1383 |
- server_realm, |
1384 |
- &server_principal, |
1385 |
- &gse_ctx->server_name); |
1386 |
- TALLOC_FREE(server_realm); |
1387 |
- if (!NT_STATUS_IS_OK(status)) { |
1388 |
- return status; |
1389 |
- } |
1390 |
- |
1391 |
/* TODO: get krb5 ticket using username/password, if no valid |
1392 |
* one already available in ccache */ |
1393 |
|
1394 |
@@ -342,11 +318,9 @@ static NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx, |
1395 |
#endif |
1396 |
|
1397 |
*_gse_ctx = gse_ctx; |
1398 |
- TALLOC_FREE(server_principal); |
1399 |
return NT_STATUS_OK; |
1400 |
|
1401 |
err_out: |
1402 |
- TALLOC_FREE(server_principal); |
1403 |
TALLOC_FREE(gse_ctx); |
1404 |
return status; |
1405 |
} |
1406 |
@@ -366,10 +340,81 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1407 |
NTSTATUS status; |
1408 |
OM_uint32 time_rec = 0; |
1409 |
struct timeval tv; |
1410 |
+ struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security); |
1411 |
+ const char *hostname = gensec_get_target_hostname(gensec_security); |
1412 |
+ const char *service = gensec_get_target_service(gensec_security); |
1413 |
+ const char *client_realm = cli_credentials_get_realm(cli_creds); |
1414 |
+ char *server_principal = NULL; |
1415 |
+ char *server_realm = NULL; |
1416 |
|
1417 |
in_data.value = token_in->data; |
1418 |
in_data.length = token_in->length; |
1419 |
|
1420 |
+ /* |
1421 |
+ * With credentials for administrator@FOREST1.EXAMPLE.COM this patch |
1422 |
+ * changes the target_principal for the ldap service of host |
1423 |
+ * dc2.forest2.example.com from |
1424 |
+ * |
1425 |
+ * ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM |
1426 |
+ * |
1427 |
+ * to |
1428 |
+ * |
1429 |
+ * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM |
1430 |
+ * |
1431 |
+ * Typically ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM should be |
1432 |
+ * used in order to allow the KDC of FOREST1.EXAMPLE.COM to generate a |
1433 |
+ * referral ticket for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM. |
1434 |
+ * |
1435 |
+ * The problem is that KDCs only return such referral tickets if |
1436 |
+ * there's a forest trust between FOREST1.EXAMPLE.COM and |
1437 |
+ * FOREST2.EXAMPLE.COM. If there's only an external domain trust |
1438 |
+ * between FOREST1.EXAMPLE.COM and FOREST2.EXAMPLE.COM the KDC of |
1439 |
+ * FOREST1.EXAMPLE.COM will respond with S_PRINCIPAL_UNKNOWN when being |
1440 |
+ * asked for ldap/dc2.forest2.example.com@FOREST1.EXAMPLE.COM. |
1441 |
+ * |
1442 |
+ * In the case of an external trust the client can still ask explicitly |
1443 |
+ * for krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM and the KDC of |
1444 |
+ * FOREST1.EXAMPLE.COM will generate it. |
1445 |
+ * |
1446 |
+ * From there the client can use the |
1447 |
+ * krbtgt/FOREST2.EXAMPLE.COM@FOREST1.EXAMPLE.COM ticket and ask a KDC |
1448 |
+ * of FOREST2.EXAMPLE.COM for a service ticket for |
1449 |
+ * ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM. |
1450 |
+ * |
1451 |
+ * With Heimdal we'll get the fallback on S_PRINCIPAL_UNKNOWN behavior |
1452 |
+ * when we pass ldap/dc2.forest2.example.com@FOREST2.EXAMPLE.COM as |
1453 |
+ * target principal. As _krb5_get_cred_kdc_any() first calls |
1454 |
+ * get_cred_kdc_referral() (which always starts with the client realm) |
1455 |
+ * and falls back to get_cred_kdc_capath() (which starts with the given |
1456 |
+ * realm). |
1457 |
+ * |
1458 |
+ * MIT krb5 only tries the given realm of the target principal, if we |
1459 |
+ * want to autodetect support for transitive forest trusts, would have |
1460 |
+ * to do the fallback ourself. |
1461 |
+ */ |
1462 |
+ if (gse_ctx->server_name == NULL) { |
1463 |
+ server_realm = smb_krb5_get_realm_from_hostname(mem_ctx, |
1464 |
+ hostname, |
1465 |
+ client_realm); |
1466 |
+ if (server_realm == NULL) { |
1467 |
+ return NT_STATUS_NO_MEMORY; |
1468 |
+ } |
1469 |
+ |
1470 |
+ status = gse_setup_server_principal(mem_ctx, |
1471 |
+ NULL, |
1472 |
+ service, |
1473 |
+ hostname, |
1474 |
+ server_realm, |
1475 |
+ &server_principal, |
1476 |
+ &gse_ctx->server_name); |
1477 |
+ TALLOC_FREE(server_realm); |
1478 |
+ if (!NT_STATUS_IS_OK(status)) { |
1479 |
+ return status; |
1480 |
+ } |
1481 |
+ |
1482 |
+ TALLOC_FREE(server_principal); |
1483 |
+ } |
1484 |
+ |
1485 |
gss_maj = gss_init_sec_context(&gss_min, |
1486 |
gse_ctx->creds, |
1487 |
&gse_ctx->gssapi_context, |
1488 |
-- |
1489 |
2.12.0 |
1490 |
|
1491 |
|
1492 |
From 5ca321eaa79cdf9de1166f49365051d4d67560f9 Mon Sep 17 00:00:00 2001 |
1493 |
From: Andreas Schneider <asn@samba.org> |
1494 |
Date: Thu, 9 Mar 2017 08:11:07 +0100 |
1495 |
Subject: [PATCH 17/20] s3:gse: Check if we have a target_princpal set we |
1496 |
should use |
1497 |
|
1498 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1499 |
|
1500 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
1501 |
|
1502 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
1503 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
1504 |
(cherry picked from commit ada31d65d6c5929d2fbddfea5611a5f5fe5a0d74) |
1505 |
--- |
1506 |
source3/librpc/crypto/gse.c | 3 ++- |
1507 |
1 file changed, 2 insertions(+), 1 deletion(-) |
1508 |
|
1509 |
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c |
1510 |
index 3580181061e..721fd8c1625 100644 |
1511 |
--- a/source3/librpc/crypto/gse.c |
1512 |
+++ b/source3/librpc/crypto/gse.c |
1513 |
@@ -341,6 +341,7 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1514 |
OM_uint32 time_rec = 0; |
1515 |
struct timeval tv; |
1516 |
struct cli_credentials *cli_creds = gensec_get_credentials(gensec_security); |
1517 |
+ const char *target_principal = gensec_get_target_principal(gensec_security); |
1518 |
const char *hostname = gensec_get_target_hostname(gensec_security); |
1519 |
const char *service = gensec_get_target_service(gensec_security); |
1520 |
const char *client_realm = cli_credentials_get_realm(cli_creds); |
1521 |
@@ -401,7 +402,7 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1522 |
} |
1523 |
|
1524 |
status = gse_setup_server_principal(mem_ctx, |
1525 |
- NULL, |
1526 |
+ target_principal, |
1527 |
service, |
1528 |
hostname, |
1529 |
server_realm, |
1530 |
-- |
1531 |
2.12.0 |
1532 |
|
1533 |
|
1534 |
From 8b88c6bf158e5da0cc238472390f3346aa05ef53 Mon Sep 17 00:00:00 2001 |
1535 |
From: Andreas Schneider <asn@samba.org> |
1536 |
Date: Thu, 9 Mar 2017 08:18:27 +0100 |
1537 |
Subject: [PATCH 18/20] s3:gse: Correctly handle external trusts with MIT |
1538 |
|
1539 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1540 |
|
1541 |
Pair-Programmed-With: Stefan Metzmacher <metze@samba.org> |
1542 |
|
1543 |
Signed-off-by: Andreas Schneider <asn@samba.org> |
1544 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
1545 |
(cherry picked from commit b8bca7d08fe05758e536767b1146cdcdd8b9fee3) |
1546 |
--- |
1547 |
source3/librpc/crypto/gse.c | 54 +++++++++++++++++++++++++++++++++++++++++++++ |
1548 |
1 file changed, 54 insertions(+) |
1549 |
|
1550 |
diff --git a/source3/librpc/crypto/gse.c b/source3/librpc/crypto/gse.c |
1551 |
index 721fd8c1625..3abf774633b 100644 |
1552 |
--- a/source3/librpc/crypto/gse.c |
1553 |
+++ b/source3/librpc/crypto/gse.c |
1554 |
@@ -347,6 +347,7 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1555 |
const char *client_realm = cli_credentials_get_realm(cli_creds); |
1556 |
char *server_principal = NULL; |
1557 |
char *server_realm = NULL; |
1558 |
+ bool fallback = false; |
1559 |
|
1560 |
in_data.value = token_in->data; |
1561 |
in_data.length = token_in->length; |
1562 |
@@ -393,6 +394,50 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1563 |
* want to autodetect support for transitive forest trusts, would have |
1564 |
* to do the fallback ourself. |
1565 |
*/ |
1566 |
+#ifndef SAMBA4_USES_HEIMDAL |
1567 |
+ if (gse_ctx->server_name == NULL) { |
1568 |
+ OM_uint32 gss_min2 = 0; |
1569 |
+ |
1570 |
+ status = gse_setup_server_principal(mem_ctx, |
1571 |
+ target_principal, |
1572 |
+ service, |
1573 |
+ hostname, |
1574 |
+ client_realm, |
1575 |
+ &server_principal, |
1576 |
+ &gse_ctx->server_name); |
1577 |
+ if (!NT_STATUS_IS_OK(status)) { |
1578 |
+ return status; |
1579 |
+ } |
1580 |
+ |
1581 |
+ gss_maj = gss_init_sec_context(&gss_min, |
1582 |
+ gse_ctx->creds, |
1583 |
+ &gse_ctx->gssapi_context, |
1584 |
+ gse_ctx->server_name, |
1585 |
+ &gse_ctx->gss_mech, |
1586 |
+ gse_ctx->gss_want_flags, |
1587 |
+ 0, |
1588 |
+ GSS_C_NO_CHANNEL_BINDINGS, |
1589 |
+ &in_data, |
1590 |
+ NULL, |
1591 |
+ &out_data, |
1592 |
+ &gse_ctx->gss_got_flags, |
1593 |
+ &time_rec); |
1594 |
+ if (gss_maj != GSS_S_FAILURE) { |
1595 |
+ goto init_sec_context_done; |
1596 |
+ } |
1597 |
+ if (gss_min != (OM_uint32)KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN) { |
1598 |
+ goto init_sec_context_done; |
1599 |
+ } |
1600 |
+ if (target_principal != NULL) { |
1601 |
+ goto init_sec_context_done; |
1602 |
+ } |
1603 |
+ |
1604 |
+ fallback = true; |
1605 |
+ TALLOC_FREE(server_principal); |
1606 |
+ gss_release_name(&gss_min2, &gse_ctx->server_name); |
1607 |
+ } |
1608 |
+#endif /* !SAMBA4_USES_HEIMDAL */ |
1609 |
+ |
1610 |
if (gse_ctx->server_name == NULL) { |
1611 |
server_realm = smb_krb5_get_realm_from_hostname(mem_ctx, |
1612 |
hostname, |
1613 |
@@ -401,6 +446,11 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1614 |
return NT_STATUS_NO_MEMORY; |
1615 |
} |
1616 |
|
1617 |
+ if (fallback && |
1618 |
+ strequal(client_realm, server_realm)) { |
1619 |
+ goto init_sec_context_done; |
1620 |
+ } |
1621 |
+ |
1622 |
status = gse_setup_server_principal(mem_ctx, |
1623 |
target_principal, |
1624 |
service, |
1625 |
@@ -425,6 +475,10 @@ static NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx, |
1626 |
0, GSS_C_NO_CHANNEL_BINDINGS, |
1627 |
&in_data, NULL, &out_data, |
1628 |
&gse_ctx->gss_got_flags, &time_rec); |
1629 |
+ goto init_sec_context_done; |
1630 |
+ /* JUMP! */ |
1631 |
+init_sec_context_done: |
1632 |
+ |
1633 |
switch (gss_maj) { |
1634 |
case GSS_S_COMPLETE: |
1635 |
/* we are done with it */ |
1636 |
-- |
1637 |
2.12.0 |
1638 |
|
1639 |
|
1640 |
From 290de34d42477022d8b5a236b3d0953a178c5e40 Mon Sep 17 00:00:00 2001 |
1641 |
From: Stefan Metzmacher <metze@samba.org> |
1642 |
Date: Sun, 29 Jan 2017 17:19:14 +0100 |
1643 |
Subject: [PATCH 19/20] HEIMDAL:kdc: make it possible to disable the principal |
1644 |
based referral detection |
1645 |
|
1646 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1647 |
|
1648 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
1649 |
Reviewed-by: Andreas Schneider <asn@samba.org> |
1650 |
(cherry picked from commit 209886e95c3afe1e4e50bacc30b40a543856a7a0) |
1651 |
--- |
1652 |
source4/heimdal/kdc/default_config.c | 1 + |
1653 |
source4/heimdal/kdc/kdc.h | 2 ++ |
1654 |
source4/heimdal/kdc/krb5tgs.c | 4 +++- |
1655 |
3 files changed, 6 insertions(+), 1 deletion(-) |
1656 |
|
1657 |
diff --git a/source4/heimdal/kdc/default_config.c b/source4/heimdal/kdc/default_config.c |
1658 |
index 6fbf5fdae15..0129c5d3c54 100644 |
1659 |
--- a/source4/heimdal/kdc/default_config.c |
1660 |
+++ b/source4/heimdal/kdc/default_config.c |
1661 |
@@ -55,6 +55,7 @@ krb5_kdc_get_config(krb5_context context, krb5_kdc_configuration **config) |
1662 |
c->preauth_use_strongest_session_key = FALSE; |
1663 |
c->tgs_use_strongest_session_key = FALSE; |
1664 |
c->use_strongest_server_key = TRUE; |
1665 |
+ c->autodetect_referrals = TRUE; |
1666 |
c->check_ticket_addresses = TRUE; |
1667 |
c->allow_null_ticket_addresses = TRUE; |
1668 |
c->allow_anonymous = FALSE; |
1669 |
diff --git a/source4/heimdal/kdc/kdc.h b/source4/heimdal/kdc/kdc.h |
1670 |
index 9d52fd4c2ec..16263d6919b 100644 |
1671 |
--- a/source4/heimdal/kdc/kdc.h |
1672 |
+++ b/source4/heimdal/kdc/kdc.h |
1673 |
@@ -69,6 +69,8 @@ typedef struct krb5_kdc_configuration { |
1674 |
krb5_boolean allow_anonymous; |
1675 |
enum krb5_kdc_trpolicy trpolicy; |
1676 |
|
1677 |
+ krb5_boolean autodetect_referrals; |
1678 |
+ |
1679 |
krb5_boolean enable_pkinit; |
1680 |
krb5_boolean pkinit_princ_in_cert; |
1681 |
const char *pkinit_kdc_identity; |
1682 |
diff --git a/source4/heimdal/kdc/krb5tgs.c b/source4/heimdal/kdc/krb5tgs.c |
1683 |
index 334a6eb1dc8..a888788bb6f 100644 |
1684 |
--- a/source4/heimdal/kdc/krb5tgs.c |
1685 |
+++ b/source4/heimdal/kdc/krb5tgs.c |
1686 |
@@ -1660,7 +1660,9 @@ server_lookup: |
1687 |
Realm req_rlm; |
1688 |
krb5_realm *realms; |
1689 |
|
1690 |
- if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { |
1691 |
+ if (!config->autodetect_referrals) { |
1692 |
+ /* noop */ |
1693 |
+ } else if ((req_rlm = get_krbtgt_realm(&sp->name)) != NULL) { |
1694 |
if(nloop++ < 2) { |
1695 |
new_rlm = find_rpath(context, tgt->crealm, req_rlm); |
1696 |
if(new_rlm) { |
1697 |
-- |
1698 |
2.12.0 |
1699 |
|
1700 |
|
1701 |
From b98d399a9b3076443fa12fab5f5e13b8d6e2fe26 Mon Sep 17 00:00:00 2001 |
1702 |
From: Stefan Metzmacher <metze@samba.org> |
1703 |
Date: Sun, 29 Jan 2017 17:20:09 +0100 |
1704 |
Subject: [PATCH 20/20] s4:kdc: disable principal based autodetected referral |
1705 |
detection |
1706 |
|
1707 |
BUG: https://bugzilla.samba.org/show_bug.cgi?id=12554 |
1708 |
|
1709 |
Signed-off-by: Stefan Metzmacher <metze@samba.org> |
1710 |
Reviewed-by: Andreas Schneider <asn@samba.org> |
1711 |
(cherry picked from commit 3314bf52aaef60ef5cc1110587b53064df7c475d) |
1712 |
--- |
1713 |
source4/kdc/kdc-heimdal.c | 2 ++ |
1714 |
1 file changed, 2 insertions(+) |
1715 |
|
1716 |
diff --git a/source4/kdc/kdc-heimdal.c b/source4/kdc/kdc-heimdal.c |
1717 |
index f2927e5cb9f..061296a4f40 100644 |
1718 |
--- a/source4/kdc/kdc-heimdal.c |
1719 |
+++ b/source4/kdc/kdc-heimdal.c |
1720 |
@@ -379,6 +379,8 @@ static void kdc_task_init(struct task_server *task) |
1721 |
kdc_config->tgs_use_strongest_session_key = false; |
1722 |
kdc_config->use_strongest_server_key = true; |
1723 |
|
1724 |
+ kdc_config->autodetect_referrals = false; |
1725 |
+ |
1726 |
/* Register hdb-samba4 hooks for use as a keytab */ |
1727 |
|
1728 |
kdc->base_ctx = talloc_zero(kdc, struct samba_kdc_base_context); |
1729 |
-- |
1730 |
2.12.0 |
1731 |
|