]>
Commit | Line | Data |
---|---|---|
ca02e0ec | 1 | /* |
b8ae064d | 2 | * Copyright (C) 1996-2023 The Squid Software Foundation and contributors |
ca02e0ec AJ |
3 | * |
4 | * Squid software is distributed under GPLv2+ license and includes | |
5 | * contributions from numerous individuals and organizations. | |
6 | * Please see the COPYING and CONTRIBUTORS files for details. | |
7 | */ | |
8 | ||
b1218840 AJ |
9 | /* |
10 | * ---------------------------------------------------------------------------- | |
11 | * | |
12 | * Author: Markus Moeller (markus_moeller at compuserve.com) | |
13 | * | |
14 | * Copyright (C) 2007 Markus Moeller. All rights reserved. | |
15 | * | |
16 | * This program is free software; you can redistribute it and/or modify | |
17 | * it under the terms of the GNU General Public License as published by | |
18 | * the Free Software Foundation; either version 2 of the License, or | |
19 | * (at your option) any later version. | |
20 | * | |
21 | * This program is distributed in the hope that it will be useful, | |
22 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
23 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
24 | * GNU General Public License for more details. | |
25 | * | |
26 | * You should have received a copy of the GNU General Public License | |
27 | * along with this program; if not, write to the Free Software | |
28 | * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307, USA. | |
29 | * | |
30 | * ----------------------------------------------------------------------------- | |
31 | */ | |
32 | ||
f7f3304a | 33 | #include "squid.h" |
98cacedb AJ |
34 | |
35 | #include <ctime> | |
b1218840 | 36 | |
1a22a39e | 37 | #if HAVE_LDAP && HAVE_KRB5 |
b1218840 AJ |
38 | |
39 | #include "support.h" | |
40 | ||
7451e5ad MM |
41 | #if HAVE_KRB5 |
42 | extern struct kstruct kparam; | |
43 | #endif | |
b1218840 AJ |
44 | |
45 | #define KT_PATH_MAX 256 | |
46 | ||
47 | void | |
48 | krb5_cleanup() | |
49 | { | |
7451e5ad MM |
50 | if (kparam.context) |
51 | for (int i=0; i<MAX_DOMAINS; i++) { | |
52 | if (kparam.cc[i]) | |
53 | krb5_cc_destroy(kparam.context, kparam.cc[i]); | |
54 | safe_free(kparam.mem_ccache[i]); | |
55 | } | |
56 | krb5_free_context(kparam.context); | |
b1218840 | 57 | } |
f95eb8d8 MM |
58 | |
59 | static void | |
60 | k5_error2(const char* msg, char* msg2, krb5_error_code code) | |
61 | { | |
62 | const char *errmsg; | |
63 | errmsg = krb5_get_error_message(kparam.context, code); | |
64 | error((char *) "%s| %s: ERROR: %s%s : %s\n", LogTime(), PROGRAM, msg, msg2, errmsg); | |
65 | #if HAVE_KRB5_FREE_ERROR_MESSAGE | |
66 | krb5_free_error_message(kparam.context, errmsg); | |
67 | #elif HAVE_KRB5_FREE_ERROR_STRING | |
68 | krb5_free_error_string(kparam.context, (char *)errmsg); | |
69 | #else | |
70 | xfree(errmsg); | |
71 | #endif | |
72 | } | |
73 | ||
40f1fd09 | 74 | static void |
75 | k5_debug(const char* msg, krb5_error_code code) | |
76 | { | |
77 | const char *errmsg; | |
78 | errmsg = krb5_get_error_message(kparam.context, code); | |
79 | debug((char *) "%s| %s: DEBUG: %s : %s\n", LogTime(), PROGRAM, msg, errmsg); | |
80 | #if HAVE_KRB5_FREE_ERROR_MESSAGE | |
81 | krb5_free_error_message(kparam.context, errmsg); | |
82 | #elif HAVE_KRB5_FREE_ERROR_STRING | |
83 | krb5_free_error_string(kparam.context, (char *)errmsg); | |
84 | #else | |
85 | xfree(errmsg); | |
86 | #endif | |
87 | } | |
88 | ||
f95eb8d8 MM |
89 | static void |
90 | k5_error(const char* msg, krb5_error_code code) | |
91 | { | |
92 | k5_error2(msg, (char *)"", code); | |
93 | } | |
94 | ||
b1218840 AJ |
95 | /* |
96 | * create Kerberos memory cache | |
97 | */ | |
98 | int | |
40f1fd09 | 99 | krb5_create_cache(char *domain, char *service_principal_name) |
b1218840 AJ |
100 | { |
101 | ||
aee3523a | 102 | krb5_keytab keytab = nullptr; |
b1218840 AJ |
103 | krb5_keytab_entry entry; |
104 | krb5_kt_cursor cursor; | |
7451e5ad | 105 | krb5_cc_cursor ccursor; |
aee3523a AR |
106 | krb5_creds *creds = nullptr; |
107 | krb5_principal *principal_list = nullptr; | |
108 | krb5_principal principal = nullptr; | |
b1218840 | 109 | char *service; |
aee3523a | 110 | char *keytab_name = nullptr, *principal_name = nullptr, *mem_cache = nullptr; |
b1218840 | 111 | char buf[KT_PATH_MAX], *p; |
4ebcf1ce | 112 | size_t j,nprinc = 0; |
b1218840 | 113 | int retval = 0; |
b1218840 | 114 | krb5_error_code code = 0; |
7451e5ad | 115 | int ccindex=-1; |
b1218840 AJ |
116 | |
117 | if (!domain || !strcmp(domain, "")) | |
2e881a6f | 118 | return (1); |
b1218840 | 119 | |
b2bdde72 MM |
120 | /* |
121 | * prepare memory credential cache | |
122 | */ | |
123 | #if !HAVE_KRB5_MEMORY_CACHE || HAVE_SUN_LDAP_SDK | |
7451e5ad MM |
124 | mem_cache = (char *) xmalloc(strlen("FILE:/tmp/squid_ldap_") + strlen(domain) + 1 + 16); |
125 | snprintf(mem_cache, strlen("FILE:/tmp/squid_ldap_") + strlen(domain) + 1 + 16, "FILE:/tmp/squid_ldap_%s_%d", domain, (int) getpid()); | |
b2bdde72 | 126 | #else |
7451e5ad MM |
127 | mem_cache = (char *) xmalloc(strlen("MEMORY:squid_ldap_") + strlen(domain) + 1 + 16); |
128 | snprintf(mem_cache, strlen("MEMORY:squid_ldap_") + strlen(domain) + 1 + 16, "MEMORY:squid_ldap_%s_%d", domain, (int) getpid()); | |
b2bdde72 MM |
129 | #endif |
130 | ||
131 | setenv("KRB5CCNAME", mem_cache, 1); | |
132 | debug((char *) "%s| %s: DEBUG: Set credential cache to %s\n", LogTime(), PROGRAM, mem_cache); | |
7451e5ad MM |
133 | for (int i=0; i<MAX_DOMAINS; i++) { |
134 | if (kparam.mem_ccache[i] && !strcmp(mem_cache,kparam.mem_ccache[i])) { | |
135 | ccindex=i; | |
136 | break; | |
137 | } | |
138 | } | |
139 | if ( ccindex == -1 ) { | |
581d42c4 | 140 | kparam.mem_ccache[kparam.ncache]=xstrdup(mem_cache); |
7451e5ad MM |
141 | ccindex=kparam.ncache; |
142 | kparam.ncache++; | |
143 | if ( kparam.ncache == MAX_DOMAINS ) { | |
144 | error((char *) "%s| %s: ERROR: Too many domains to support: # domains %d\n", LogTime(), PROGRAM, kparam.ncache); | |
145 | retval = 1; | |
146 | goto cleanup; | |
147 | } | |
148 | code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); | |
149 | if (code) { | |
40f1fd09 | 150 | k5_error("Error while resolving memory ccache", code); |
7451e5ad MM |
151 | retval = 1; |
152 | goto cleanup; | |
153 | } | |
b2bdde72 | 154 | } |
b1218840 | 155 | /* |
7451e5ad | 156 | * getting default principal from cache |
b1218840 AJ |
157 | */ |
158 | ||
7451e5ad | 159 | code = krb5_cc_get_principal(kparam.context, kparam.cc[ccindex], &principal); |
b1218840 | 160 | if (code) { |
7451e5ad MM |
161 | if (principal) |
162 | krb5_free_principal(kparam.context, principal); | |
aee3523a | 163 | principal = nullptr; |
40f1fd09 | 164 | k5_debug("No default principal found in ccache", code); |
7451e5ad MM |
165 | } else { |
166 | /* | |
167 | * Look for krbtgt and check if it is expired (or soon to be expired) | |
168 | */ | |
169 | code = krb5_cc_start_seq_get(kparam.context, kparam.cc[ccindex], &ccursor); | |
170 | if (code) { | |
40f1fd09 | 171 | k5_error("Error while starting ccache scan", code); |
7451e5ad MM |
172 | code = krb5_cc_close (kparam.context, kparam.cc[ccindex]); |
173 | if (code) { | |
40f1fd09 | 174 | k5_error("Error while closing ccache", code); |
7451e5ad MM |
175 | } |
176 | if (kparam.cc[ccindex]) { | |
177 | code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); | |
178 | if (code) { | |
40f1fd09 | 179 | k5_error("Error while destroying ccache", code); |
7451e5ad MM |
180 | } |
181 | } | |
182 | } else { | |
183 | krb5_error_code code2 = 0; | |
4dccc594 | 184 | creds = static_cast<krb5_creds *>(xcalloc(1,sizeof(*creds))); |
7451e5ad MM |
185 | while ((krb5_cc_next_cred(kparam.context, kparam.cc[ccindex], &ccursor, creds)) == 0) { |
186 | code2 = krb5_unparse_name(kparam.context, creds->server, &principal_name); | |
187 | if (code2) { | |
40f1fd09 | 188 | k5_error("Error while unparsing principal", code2); |
7451e5ad MM |
189 | code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); |
190 | if (code) { | |
40f1fd09 | 191 | k5_error("Error while destroying ccache", code); |
7451e5ad | 192 | } |
aee3523a | 193 | assert(creds != nullptr); |
4dccc594 | 194 | krb5_free_creds(kparam.context, creds); |
aee3523a | 195 | creds = nullptr; |
7451e5ad MM |
196 | safe_free(principal_name); |
197 | debug((char *) "%s| %s: DEBUG: Reset credential cache to %s\n", LogTime(), PROGRAM, mem_cache); | |
198 | code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); | |
199 | if (code) { | |
40f1fd09 | 200 | k5_error("Error while resolving memory ccache", code); |
7451e5ad MM |
201 | retval = 1; |
202 | goto cleanup; | |
203 | } | |
204 | code =1; | |
205 | break; | |
206 | } | |
207 | if (!strncmp(KRB5_TGS_NAME,principal_name,KRB5_TGS_NAME_SIZE)) { | |
208 | time_t now; | |
209 | static krb5_deltat skew=MAX_SKEW; | |
210 | ||
211 | debug((char *) "%s| %s: DEBUG: Found %s in cache : %s\n", LogTime(), PROGRAM,KRB5_TGS_NAME,principal_name); | |
212 | /* | |
213 | * Check time | |
214 | */ | |
215 | time(&now); | |
216 | debug((char *) "%s| %s: DEBUG: credential time diff %d\n", LogTime(), PROGRAM, (int)(creds->times.endtime - now)); | |
217 | if (creds->times.endtime - now < 2*skew) { | |
218 | debug((char *) "%s| %s: DEBUG: credential will soon expire %d\n", LogTime(), PROGRAM, (int)(creds->times.endtime - now)); | |
219 | if (principal) | |
220 | krb5_free_principal(kparam.context, principal); | |
aee3523a | 221 | principal = nullptr; |
7451e5ad MM |
222 | code = krb5_cc_destroy(kparam.context, kparam.cc[ccindex]); |
223 | if (code) { | |
40f1fd09 | 224 | k5_error("Error while destroying ccache", code); |
7451e5ad | 225 | } |
aee3523a | 226 | assert(creds != nullptr); |
4dccc594 | 227 | krb5_free_creds(kparam.context, creds); |
aee3523a | 228 | creds = nullptr; |
7451e5ad MM |
229 | safe_free(principal_name); |
230 | debug((char *) "%s| %s: DEBUG: Reset credential cache to %s\n", LogTime(), PROGRAM, mem_cache); | |
231 | code = krb5_cc_resolve(kparam.context, mem_cache, &kparam.cc[ccindex]); | |
232 | if (code) { | |
40f1fd09 | 233 | k5_error("Error while resolving ccache", code); |
7451e5ad MM |
234 | retval = 1; |
235 | goto cleanup; | |
236 | } | |
237 | code = 1; | |
238 | } else { | |
239 | safe_free(principal_name); | |
240 | } | |
241 | break; | |
242 | } | |
aee3523a | 243 | assert(creds != nullptr); |
4dccc594 AJ |
244 | krb5_free_creds(kparam.context, creds); |
245 | creds = static_cast<krb5_creds *>(xcalloc(1, sizeof(*creds))); | |
7451e5ad MM |
246 | safe_free(principal_name); |
247 | } | |
248 | if (creds) | |
249 | krb5_free_creds(kparam.context, creds); | |
aee3523a | 250 | creds = nullptr; |
7451e5ad MM |
251 | code2 = krb5_cc_end_seq_get(kparam.context, kparam.cc[ccindex], &ccursor); |
252 | if (code2) { | |
40f1fd09 | 253 | k5_error("Error while ending ccache scan", code2); |
7451e5ad MM |
254 | retval = 1; |
255 | goto cleanup; | |
256 | } | |
257 | } | |
b1218840 | 258 | } |
b1218840 | 259 | if (code) { |
7451e5ad MM |
260 | /* |
261 | * getting default keytab name | |
262 | */ | |
b1218840 | 263 | |
7451e5ad MM |
264 | debug((char *) "%s| %s: DEBUG: Get default keytab file name\n", LogTime(), PROGRAM); |
265 | krb5_kt_default_name(kparam.context, buf, KT_PATH_MAX); | |
f53969cc | 266 | p = strchr(buf, ':'); /* Find the end if "FILE:" */ |
7451e5ad | 267 | if (p) |
f53969cc | 268 | ++p; /* step past : */ |
7451e5ad MM |
269 | keytab_name = xstrdup(p ? p : buf); |
270 | debug((char *) "%s| %s: DEBUG: Got default keytab file name %s\n", LogTime(), PROGRAM, keytab_name); | |
b1218840 | 271 | |
7451e5ad MM |
272 | code = krb5_kt_resolve(kparam.context, keytab_name, &keytab); |
273 | if (code) { | |
40f1fd09 | 274 | k5_error2("Error while resolving keytab ", keytab_name,code); |
7451e5ad MM |
275 | retval = 1; |
276 | goto cleanup; | |
277 | } | |
278 | code = krb5_kt_start_seq_get(kparam.context, keytab, &cursor); | |
279 | if (code) { | |
40f1fd09 | 280 | k5_error("Error while starting keytab scan", code); |
7451e5ad MM |
281 | retval = 1; |
282 | goto cleanup; | |
283 | } | |
284 | debug((char *) "%s| %s: DEBUG: Get principal name from keytab %s\n", LogTime(), PROGRAM, keytab_name); | |
285 | ||
286 | nprinc = 0; | |
287 | while ((code = krb5_kt_next_entry(kparam.context, keytab, &entry, &cursor)) == 0) { | |
288 | int found = 0; | |
289 | ||
290 | principal_list = (krb5_principal *) xrealloc(principal_list, sizeof(krb5_principal) * (nprinc + 1)); | |
291 | krb5_copy_principal(kparam.context, entry.principal, &principal_list[nprinc++]); | |
adcdd245 | 292 | #if HAVE_LIBHEIMDAL_KRB5 |
7451e5ad | 293 | debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, entry.principal->realm); |
b1218840 | 294 | #else |
7451e5ad | 295 | debug((char *) "%s| %s: DEBUG: Keytab entry has realm name: %s\n", LogTime(), PROGRAM, krb5_princ_realm(kparam.context, entry.principal)->data); |
b1218840 | 296 | #endif |
adcdd245 | 297 | #if HAVE_LIBHEIMDAL_KRB5 |
7451e5ad | 298 | if (!strcasecmp(domain, entry.principal->realm)) |
b1218840 | 299 | #else |
7451e5ad | 300 | if (!strcasecmp(domain, krb5_princ_realm(kparam.context, entry.principal)->data)) |
b1218840 | 301 | #endif |
7451e5ad MM |
302 | { |
303 | code = krb5_unparse_name(kparam.context, entry.principal, &principal_name); | |
304 | if (code) { | |
40f1fd09 | 305 | k5_error("Error while unparsing principal name", code); |
7451e5ad MM |
306 | } else { |
307 | debug((char *) "%s| %s: DEBUG: Found principal name: %s\n", LogTime(), PROGRAM, principal_name); | |
308 | found = 1; | |
40f1fd09 | 309 | if (service_principal_name && strcasecmp(principal_name,service_principal_name) != 0 ) { |
310 | debug((char *) "%s| %s: DEBUG: principal name does not match parameter: %s\n", LogTime(), PROGRAM, service_principal_name); | |
311 | safe_free(principal_name); | |
312 | found = 0; | |
313 | } | |
7451e5ad | 314 | } |
2e881a6f | 315 | } |
adcdd245 | 316 | #if HAVE_LIBHEIMDAL_KRB5 || ( HAVE_KRB5_KT_FREE_ENTRY && HAVE_DECL_KRB5_KT_FREE_ENTRY ) |
7451e5ad | 317 | code = krb5_kt_free_entry(kparam.context, &entry); |
b1218840 | 318 | #else |
7451e5ad | 319 | code = krb5_free_keytab_entry_contents(kparam.context, &entry); |
b1218840 | 320 | #endif |
b2bdde72 | 321 | if (code) { |
40f1fd09 | 322 | k5_error("Error while freeing keytab entry", code); |
7451e5ad MM |
323 | retval = 1; |
324 | break; | |
b2bdde72 | 325 | } |
7451e5ad MM |
326 | if (found) { |
327 | debug((char *) "%s| %s: DEBUG: Got principal name %s\n", LogTime(), PROGRAM, principal_name); | |
328 | /* | |
329 | * build principal | |
330 | */ | |
331 | code = krb5_parse_name(kparam.context, principal_name, &principal); | |
332 | if (code) { | |
f95eb8d8 | 333 | k5_error2("Error while parsing name ", principal_name,code); |
7451e5ad MM |
334 | safe_free(principal_name); |
335 | if (principal) | |
336 | krb5_free_principal(kparam.context, principal); | |
337 | found = 0; | |
338 | continue; | |
339 | } | |
340 | creds = (krb5_creds *) xcalloc(1,sizeof(*creds)); | |
b2bdde72 | 341 | |
7451e5ad MM |
342 | /* |
343 | * get credentials | |
344 | */ | |
b2bdde72 | 345 | #if HAVE_GET_INIT_CREDS_KEYTAB |
aee3523a | 346 | code = krb5_get_init_creds_keytab(kparam.context, creds, principal, keytab, 0, nullptr, nullptr); |
b2bdde72 | 347 | #else |
7451e5ad MM |
348 | service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3); |
349 | snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain); | |
350 | creds->client = principal; | |
351 | code = krb5_parse_name(kparam.context, service, &creds->server); | |
352 | xfree(service); | |
a1b1756c | 353 | code = krb5_get_in_tkt_with_keytab(kparam.context, 0, nullptr, nullptr, nullptr, keytab, nullptr, creds, 0); |
b2bdde72 MM |
354 | #endif |
355 | ||
7451e5ad | 356 | if (code) { |
40f1fd09 | 357 | k5_error("Error while initialising credentials from keytab", code); |
7451e5ad MM |
358 | safe_free(principal_name); |
359 | if (principal) | |
360 | krb5_free_principal(kparam.context, principal); | |
361 | if (creds) | |
362 | krb5_free_creds(kparam.context, creds); | |
aee3523a | 363 | creds = nullptr; |
7451e5ad MM |
364 | found = 0; |
365 | continue; | |
366 | } | |
367 | code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal); | |
368 | if (code) { | |
40f1fd09 | 369 | k5_error("Error while initialising cache", code); |
7451e5ad MM |
370 | safe_free(principal_name); |
371 | if (principal) | |
372 | krb5_free_principal(kparam.context, principal); | |
373 | if (creds) | |
374 | krb5_free_creds(kparam.context, creds); | |
aee3523a | 375 | creds = nullptr; |
7451e5ad MM |
376 | found = 0; |
377 | continue; | |
378 | } | |
379 | code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds); | |
380 | if (code) { | |
40f1fd09 | 381 | k5_error("Error while storing credentials", code); |
7451e5ad MM |
382 | if (principal) |
383 | krb5_free_principal(kparam.context, principal); | |
384 | safe_free(principal_name); | |
385 | if (creds) | |
386 | krb5_free_creds(kparam.context, creds); | |
aee3523a | 387 | creds = nullptr; |
7451e5ad MM |
388 | found = 0; |
389 | continue; | |
390 | } | |
391 | debug((char *) "%s| %s: DEBUG: Stored credentials\n", LogTime(), PROGRAM); | |
392 | break; | |
b2bdde72 | 393 | } |
b2bdde72 | 394 | } |
b1218840 | 395 | |
7451e5ad | 396 | if (code && code != KRB5_KT_END) { |
40f1fd09 | 397 | k5_error("Error while scanning keytab", code); |
7451e5ad MM |
398 | retval = 1; |
399 | goto cleanup; | |
400 | } | |
401 | code = krb5_kt_end_seq_get(kparam.context, keytab, &cursor); | |
402 | if (code) { | |
40f1fd09 | 403 | k5_error("Error while ending keytab scan", code); |
7451e5ad MM |
404 | retval = 1; |
405 | goto cleanup; | |
406 | } | |
b1218840 | 407 | |
7451e5ad MM |
408 | /* |
409 | * if no principal name found in keytab for domain use the prinipal name which can get a TGT | |
410 | */ | |
40f1fd09 | 411 | if (!principal_name && !service_principal_name) { |
7451e5ad MM |
412 | size_t i; |
413 | debug((char *) "%s| %s: DEBUG: Did not find a principal in keytab for domain %s.\n", LogTime(), PROGRAM, domain); | |
414 | debug((char *) "%s| %s: DEBUG: Try to get principal of trusted domain.\n", LogTime(), PROGRAM); | |
b1218840 | 415 | |
7451e5ad | 416 | for (i = 0; i < nprinc; ++i) { |
aee3523a | 417 | krb5_creds *tgt_creds = nullptr; |
7451e5ad MM |
418 | creds = (krb5_creds *) xmalloc(sizeof(*creds)); |
419 | memset(creds, 0, sizeof(*creds)); | |
420 | /* | |
421 | * get credentials | |
422 | */ | |
423 | code = krb5_unparse_name(kparam.context, principal_list[i], &principal_name); | |
424 | if (code) { | |
40f1fd09 | 425 | k5_error("Error while unparsing principal name", code); |
7451e5ad MM |
426 | goto loop_end; |
427 | } | |
428 | debug((char *) "%s| %s: DEBUG: Keytab entry has principal: %s\n", LogTime(), PROGRAM, principal_name); | |
b1218840 AJ |
429 | |
430 | #if HAVE_GET_INIT_CREDS_KEYTAB | |
aee3523a | 431 | code = krb5_get_init_creds_keytab(kparam.context, creds, principal_list[i], keytab, 0, nullptr, nullptr); |
b1218840 | 432 | #else |
7451e5ad MM |
433 | service = (char *) xmalloc(strlen("krbtgt") + 2 * strlen(domain) + 3); |
434 | snprintf(service, strlen("krbtgt") + 2 * strlen(domain) + 3, "krbtgt/%s@%s", domain, domain); | |
435 | creds->client = principal_list[i]; | |
436 | code = krb5_parse_name(kparam.context, service, &creds->server); | |
437 | xfree(service); | |
a1b1756c | 438 | code = krb5_get_in_tkt_with_keytab(kparam.context, 0, nullptr, nullptr, nullptr, keytab, nullptr, creds, 0); |
b1218840 | 439 | #endif |
7451e5ad | 440 | if (code) { |
40f1fd09 | 441 | k5_error("Error while initialising credentials from keytab", code); |
7451e5ad MM |
442 | goto loop_end; |
443 | } | |
444 | code = krb5_cc_initialize(kparam.context, kparam.cc[ccindex], principal_list[i]); | |
445 | if (code) { | |
40f1fd09 | 446 | k5_error("Error while initialising memory caches", code); |
7451e5ad MM |
447 | goto loop_end; |
448 | } | |
449 | code = krb5_cc_store_cred(kparam.context, kparam.cc[ccindex], creds); | |
450 | if (code) { | |
40f1fd09 | 451 | k5_error("Error while storing credentials", code); |
7451e5ad MM |
452 | goto loop_end; |
453 | } | |
454 | if (creds->server) | |
455 | krb5_free_principal(kparam.context, creds->server); | |
adcdd245 | 456 | #if HAVE_LIBHEIMDAL_KRB5 |
7451e5ad MM |
457 | service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3); |
458 | snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(principal_list[i]->realm) + 3, "krbtgt/%s@%s", domain, principal_list[i]->realm); | |
b1218840 | 459 | #else |
7451e5ad MM |
460 | service = (char *) xmalloc(strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3); |
461 | snprintf(service, strlen("krbtgt") + strlen(domain) + strlen(krb5_princ_realm(kparam.context, principal_list[i])->data) + 3, "krbtgt/%s@%s", domain, krb5_princ_realm(kparam.context, principal_list[i])->data); | |
b1218840 | 462 | #endif |
7451e5ad MM |
463 | code = krb5_parse_name(kparam.context, service, &creds->server); |
464 | xfree(service); | |
465 | if (code) { | |
40f1fd09 | 466 | k5_error("Error while initialising TGT credentials", code); |
7451e5ad MM |
467 | goto loop_end; |
468 | } | |
b4548e78 | 469 | |
470 | // overwrite limitation of enctypes | |
adcdd245 | 471 | #if HAVE_LIBHEIMDAL_KRB5 |
bcc5a637 | 472 | creds->session.keytype = 0; |
473 | if (creds->session.keyvalue.length > 0) | |
474 | krb5_free_keyblock_contents(kparam.context, &creds->session); | |
475 | #else | |
b4548e78 | 476 | creds->keyblock.enctype = 0; |
477 | if (creds->keyblock.contents) | |
478 | krb5_free_keyblock_contents(kparam.context, &creds->keyblock); | |
bcc5a637 | 479 | #endif |
7451e5ad MM |
480 | code = krb5_get_credentials(kparam.context, 0, kparam.cc[ccindex], creds, &tgt_creds); |
481 | if (code) { | |
40f1fd09 | 482 | k5_error("Error while getting tgt", code); |
7451e5ad MM |
483 | goto loop_end; |
484 | } else { | |
485 | debug((char *) "%s| %s: DEBUG: Found trusted principal name: %s\n", LogTime(), PROGRAM, principal_name); | |
486 | if (tgt_creds) | |
487 | krb5_free_creds(kparam.context, tgt_creds); | |
aee3523a | 488 | tgt_creds = nullptr; |
7451e5ad MM |
489 | break; |
490 | } | |
491 | ||
492 | loop_end: | |
493 | safe_free(principal_name); | |
b2bdde72 MM |
494 | if (tgt_creds) |
495 | krb5_free_creds(kparam.context, tgt_creds); | |
aee3523a | 496 | tgt_creds = nullptr; |
7451e5ad MM |
497 | if (creds) |
498 | krb5_free_creds(kparam.context, creds); | |
aee3523a | 499 | creds = nullptr; |
7451e5ad | 500 | |
2e881a6f | 501 | } |
b1218840 | 502 | |
4ebcf1ce MM |
503 | if (creds) |
504 | krb5_free_creds(kparam.context, creds); | |
aee3523a | 505 | creds = nullptr; |
2e881a6f | 506 | } |
7451e5ad MM |
507 | } else { |
508 | debug((char *) "%s| %s: DEBUG: Got principal from ccache\n", LogTime(), PROGRAM); | |
509 | /* | |
510 | * get credentials | |
511 | */ | |
512 | code = krb5_unparse_name(kparam.context, principal, &principal_name); | |
513 | if (code) { | |
40f1fd09 | 514 | k5_error("Error while unparsing principal name", code); |
7451e5ad MM |
515 | retval = 1; |
516 | goto cleanup; | |
517 | } | |
518 | debug((char *) "%s| %s: DEBUG: ccache has principal: %s\n", LogTime(), PROGRAM, principal_name); | |
b1218840 | 519 | } |
7451e5ad | 520 | |
b2bdde72 | 521 | if (!principal_name) { |
2e881a6f A |
522 | debug((char *) "%s| %s: DEBUG: Got no principal name\n", LogTime(), PROGRAM); |
523 | retval = 1; | |
b1218840 | 524 | } |
2e881a6f | 525 | cleanup: |
b1218840 | 526 | if (keytab) |
2e881a6f | 527 | krb5_kt_close(kparam.context, keytab); |
4ebcf1ce MM |
528 | xfree(keytab_name); |
529 | xfree(principal_name); | |
530 | xfree(mem_cache); | |
b1218840 | 531 | if (principal) |
2e881a6f | 532 | krb5_free_principal(kparam.context, principal); |
4ebcf1ce MM |
533 | for (j = 0; j < nprinc; ++j) { |
534 | if (principal_list[j]) | |
535 | krb5_free_principal(kparam.context, principal_list[j]); | |
b1218840 | 536 | } |
4ebcf1ce | 537 | xfree(principal_list); |
b1218840 | 538 | if (creds) |
2e881a6f | 539 | krb5_free_creds(kparam.context, creds); |
b1218840 AJ |
540 | return (retval); |
541 | } | |
542 | #endif | |
f53969cc | 543 |