blob: d8898a66290544175311a78e3dd3dc544d95b5bd [file] [log] [blame]
Lutz Justen09cd1c32019-02-15 14:31:49 +01001// Copyright 2019 The Chromium OS Authors. All rights reserved.
2// Use of this source code is governed by a BSD-style license that can be
3// found in the LICENSE file.
4
Lutz Justene39cbd42019-05-14 14:52:24 +02005#include "kerberos/krb5_interface_impl.h"
Lutz Justen09cd1c32019-02-15 14:31:49 +01006
Lutz Justencb8399d2019-03-08 14:30:17 +01007#include <algorithm>
Lutz Justen09cd1c32019-02-15 14:31:49 +01008#include <utility>
9
Qijiang Fan713061e2021-03-08 15:45:12 +090010#include <base/check.h>
Lutz Justenb79da832019-03-08 14:52:53 +010011#include <base/files/file_path.h>
Lutz Justen90281402019-07-05 15:14:37 +020012#include <base/files/file_util.h>
Lutz Justen09cd1c32019-02-15 14:31:49 +010013#include <base/logging.h>
14#include <base/strings/stringprintf.h>
15#include <krb5.h>
Lutz Justen70496c12019-07-24 11:11:55 +020016#include <profile.h>
Lutz Justen09cd1c32019-02-15 14:31:49 +010017
Lutz Justen90281402019-07-05 15:14:37 +020018#include "kerberos/error_strings.h"
19
Lutz Justen09cd1c32019-02-15 14:31:49 +010020namespace kerberos {
21
22namespace {
23
24// Environment variable for the Kerberos configuration (krb5.conf).
25constexpr char kKrb5ConfigEnvVar[] = "KRB5_CONFIG";
26
Lutz Justencb8399d2019-03-08 14:30:17 +010027// Wrapper classes for safe construction and destruction.
28struct ScopedKrb5Context {
29 ScopedKrb5Context() = default;
30 ~ScopedKrb5Context() {
31 if (ctx) {
32 krb5_free_context(ctx);
33 ctx = nullptr;
34 }
35 }
36
37 // Converts the krb5 |code| to a human readable error message.
38 std::string GetErrorMessage(errcode_t code) {
Lutz Justene5238762019-06-06 14:09:21 +020039 // Fallback if error happens during ctx initialization (e.g. bad config).
40 if (!ctx)
41 return base::StringPrintf("Error %ld", code);
42
Lutz Justencb8399d2019-03-08 14:30:17 +010043 const char* emsg = krb5_get_error_message(ctx, code);
44 std::string msg = base::StringPrintf("%s (%ld)", emsg, code);
45 krb5_free_error_message(ctx, emsg);
46 return msg;
47 }
48
49 krb5_context get() const { return ctx; }
50 krb5_context* get_mutable_ptr() { return &ctx; }
51
52 private:
53 krb5_context ctx = nullptr;
54};
55
56struct ScopedKrb5CCache {
Lutz Justen1cb62412019-05-09 10:09:45 +020057 // Prefer the constructor taking a context if possible.
58 ScopedKrb5CCache() {}
59 explicit ScopedKrb5CCache(krb5_context _ctx) { set_ctx(_ctx); }
60
Lutz Justencb8399d2019-03-08 14:30:17 +010061 ~ScopedKrb5CCache() {
62 if (ccache) {
Lutz Justen1cb62412019-05-09 10:09:45 +020063 DCHECK(ctx);
64 krb5_cc_close(ctx, ccache);
Lutz Justencb8399d2019-03-08 14:30:17 +010065 ccache = nullptr;
66 }
67 }
68
Lutz Justen1cb62412019-05-09 10:09:45 +020069 // The context must be set if |ccache| is set (though get_mutable_ptr())
70 // before this object is destroyed.
71 void set_ctx(krb5_context _ctx) {
72 ctx = _ctx;
73 DCHECK(ctx);
74 }
75
Lutz Justencb8399d2019-03-08 14:30:17 +010076 krb5_ccache get() const { return ccache; }
77 krb5_ccache* get_mutable_ptr() { return &ccache; }
78
79 private:
80 // Pointer to parent data, not owned.
Lutz Justen1cb62412019-05-09 10:09:45 +020081 krb5_context ctx = nullptr;
Lutz Justencb8399d2019-03-08 14:30:17 +010082 krb5_ccache ccache = nullptr;
83};
84
85// Maps some common krb5 error codes to our internal codes. If something is not
86// reported properly, add more cases here.
87ErrorType TranslateErrorCode(errcode_t code) {
88 switch (code) {
89 case KRB5KDC_ERR_NONE:
90 return ERROR_NONE;
91
92 case KRB5_KDC_UNREACH:
93 return ERROR_NETWORK_PROBLEM;
94
Lutz Justene5238762019-06-06 14:09:21 +020095 case KRB5_CONFIG_BADFORMAT:
Lutz Justen70496c12019-07-24 11:11:55 +020096 case PROF_BAD_BOOLEAN:
97 case PROF_BAD_INTEGER:
Lutz Justene5238762019-06-06 14:09:21 +020098 return ERROR_BAD_CONFIG;
99
Lutz Justencb8399d2019-03-08 14:30:17 +0100100 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
101 return ERROR_BAD_PRINCIPAL;
102
103 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
104 case KRB5KDC_ERR_PREAUTH_FAILED:
105 return ERROR_BAD_PASSWORD;
106
107 case KRB5KDC_ERR_KEY_EXP:
108 return ERROR_PASSWORD_EXPIRED;
109
110 // TODO(https://crbug.com/951741): Verify
111 case KRB5_KPASSWD_SOFTERROR:
112 return ERROR_PASSWORD_REJECTED;
113
114 // TODO(https://crbug.com/951741): Verify
115 case KRB5_FCC_NOFILE:
116 return ERROR_NO_CREDENTIALS_CACHE_FOUND;
117
118 // TODO(https://crbug.com/951741): Verify
119 case KRB5KRB_AP_ERR_TKT_EXPIRED:
120 return ERROR_KERBEROS_TICKET_EXPIRED;
121
122 case KRB5KDC_ERR_ETYPE_NOSUPP:
123 return ERROR_KDC_DOES_NOT_SUPPORT_ENCRYPTION_TYPE;
124
125 case KRB5_REALM_UNKNOWN:
126 return ERROR_CONTACTING_KDC_FAILED;
127
128 default:
129 return ERROR_UNKNOWN_KRB5_ERROR;
130 }
131}
132
133// Returns true if the string contained in |data| matches |str_to_match|.
134bool DataMatches(const krb5_data& data, const char* str_to_match) {
135 // It is not clear whether data.data is null terminated, so a strcmp might
136 // not work.
137 return strlen(str_to_match) == data.length &&
138 memcmp(str_to_match, data.data, data.length) == 0;
139}
140
141// Returns true if |creds| has a server that starts with "krbtgt".
142bool IsTgt(const krb5_creds& creds) {
143 return creds.server && creds.server->length > 0 &&
144 DataMatches(creds.server->data[0], "krbtgt");
145}
146
Lutz Justen09cd1c32019-02-15 14:31:49 +0100147enum class Action { AcquireTgt, RenewTgt };
148
149struct Options {
150 std::string principal_name;
151 std::string password;
152 std::string krb5cc_path;
153 std::string config_path;
154 Action action = Action::AcquireTgt;
155};
156
157// Encapsulates krb5 context data required for kinit.
158class KinitContext {
159 public:
160 explicit KinitContext(Options options) : options_(std::move(options)) {
161 memset(&k5_, 0, sizeof(k5_));
162 }
163
164 // Runs kinit with the options passed to the constructor. Only call once per
165 // context. While in principle it should be fine to run multiple times, the
166 // code path probably hasn't been tested (kinit does not call this multiple
167 // times).
168 ErrorType Run() {
169 DCHECK(!did_run_);
170 did_run_ = true;
171
172 ErrorType error = Initialize();
173 if (error == ERROR_NONE)
174 error = RunKinit();
175 Finalize();
176 return error;
177 }
178
179 private:
180 // The following code has been adapted from kinit.c in the mit-krb5 code base.
181 // It has been formatted to fit this screen.
182
183 struct Krb5Data {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100184 krb5_principal me;
185 char* name;
186 };
187
188 // Wrapper around krb5 data to get rid of the gotos in the original code.
189 struct KInitData {
190 // Pointer to parent data, not owned.
Lutz Justencb8399d2019-03-08 14:30:17 +0100191 const krb5_context ctx = nullptr;
192 // Pointer to parent data, not owned.
Lutz Justen09cd1c32019-02-15 14:31:49 +0100193 const Krb5Data* k5 = nullptr;
194 krb5_creds my_creds;
195 krb5_get_init_creds_opt* options = nullptr;
196
197 // The lifetime of the |k5| pointer must exceed the lifetime of this object.
Lutz Justencb8399d2019-03-08 14:30:17 +0100198 explicit KInitData(const krb5_context ctx, const Krb5Data* k5)
199 : ctx(ctx), k5(k5) {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100200 memset(&my_creds, 0, sizeof(my_creds));
201 }
202
203 ~KInitData() {
204 if (options)
Lutz Justencb8399d2019-03-08 14:30:17 +0100205 krb5_get_init_creds_opt_free(ctx, options);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100206 if (my_creds.client == k5->me)
207 my_creds.client = nullptr;
Lutz Justencb8399d2019-03-08 14:30:17 +0100208 krb5_free_cred_contents(ctx, &my_creds);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100209 }
210 };
211
Lutz Justen09cd1c32019-02-15 14:31:49 +0100212 // Initializes krb5 data.
213 ErrorType Initialize() {
Lutz Justencb8399d2019-03-08 14:30:17 +0100214 krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
Lutz Justen09cd1c32019-02-15 14:31:49 +0100215 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100216 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100217 return TranslateErrorCode(ret);
218 }
219
Lutz Justen1cb62412019-05-09 10:09:45 +0200220 out_cc.set_ctx(ctx.get());
221 ret = krb5_cc_resolve(ctx.get(), options_.krb5cc_path.c_str(),
222 out_cc.get_mutable_ptr());
Lutz Justen09cd1c32019-02-15 14:31:49 +0100223 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100224 LOG(ERROR) << ctx.GetErrorMessage(ret) << " resolving ccache";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100225 return TranslateErrorCode(ret);
226 }
227
Lutz Justencb8399d2019-03-08 14:30:17 +0100228 ret = krb5_parse_name_flags(ctx.get(), options_.principal_name.c_str(),
Lutz Justen09cd1c32019-02-15 14:31:49 +0100229 0 /* flags */, &k5_.me);
230 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100231 LOG(ERROR) << ctx.GetErrorMessage(ret) << " when parsing name";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100232 return TranslateErrorCode(ret);
233 }
234
Lutz Justencb8399d2019-03-08 14:30:17 +0100235 ret = krb5_unparse_name(ctx.get(), k5_.me, &k5_.name);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100236 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100237 LOG(ERROR) << ctx.GetErrorMessage(ret) << " when unparsing name";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100238 return TranslateErrorCode(ret);
239 }
240
241 options_.principal_name = k5_.name;
242 return ERROR_NONE;
243 }
244
245 // Finalizes krb5 data.
246 void Finalize() {
Lutz Justencb8399d2019-03-08 14:30:17 +0100247 krb5_free_unparsed_name(ctx.get(), k5_.name);
248 krb5_free_principal(ctx.get(), k5_.me);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100249 memset(&k5_, 0, sizeof(k5_));
250 }
251
252 // Runs the actual kinit code and acquires/renews tickets.
253 ErrorType RunKinit() {
254 krb5_error_code ret;
Lutz Justencb8399d2019-03-08 14:30:17 +0100255 KInitData d(ctx.get(), &k5_);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100256
Lutz Justencb8399d2019-03-08 14:30:17 +0100257 ret = krb5_get_init_creds_opt_alloc(ctx.get(), &d.options);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100258 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100259 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while getting options";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100260 return TranslateErrorCode(ret);
261 }
262
Lutz Justencb8399d2019-03-08 14:30:17 +0100263 ret = krb5_get_init_creds_opt_set_out_ccache(ctx.get(), d.options,
Lutz Justen1cb62412019-05-09 10:09:45 +0200264 out_cc.get());
Lutz Justen09cd1c32019-02-15 14:31:49 +0100265 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100266 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while getting options";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100267 return TranslateErrorCode(ret);
268 }
269
270 // To get notified of expiry, see
271 // krb5_get_init_creds_opt_set_expire_callback
272
273 switch (options_.action) {
274 case Action::AcquireTgt:
275 ret = krb5_get_init_creds_password(
Lutz Justencb8399d2019-03-08 14:30:17 +0100276 ctx.get(), &d.my_creds, k5_.me, options_.password.c_str(),
Lutz Justen09cd1c32019-02-15 14:31:49 +0100277 nullptr /* prompter */, nullptr /* data */, 0 /* start_time */,
278 nullptr /* in_tkt_service */, d.options);
279 break;
280 case Action::RenewTgt:
Lutz Justen1cb62412019-05-09 10:09:45 +0200281 ret =
282 krb5_get_renewed_creds(ctx.get(), &d.my_creds, k5_.me, out_cc.get(),
283 nullptr /* options_.in_tkt_service */);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100284 break;
285 }
286
287 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100288 LOG(ERROR) << ctx.GetErrorMessage(ret);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100289 return TranslateErrorCode(ret);
290 }
291
292 if (options_.action != Action::AcquireTgt) {
Lutz Justen1cb62412019-05-09 10:09:45 +0200293 ret = krb5_cc_initialize(ctx.get(), out_cc.get(), k5_.me);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100294 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100295 LOG(ERROR) << ctx.GetErrorMessage(ret) << " when initializing cache";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100296 return TranslateErrorCode(ret);
297 }
298
Lutz Justen1cb62412019-05-09 10:09:45 +0200299 ret = krb5_cc_store_cred(ctx.get(), out_cc.get(), &d.my_creds);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100300 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100301 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while storing credentials";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100302 return TranslateErrorCode(ret);
303 }
304 }
305
306 return ERROR_NONE;
307 }
308
Lutz Justencb8399d2019-03-08 14:30:17 +0100309 ScopedKrb5Context ctx;
Lutz Justen1cb62412019-05-09 10:09:45 +0200310 ScopedKrb5CCache out_cc;
Lutz Justen09cd1c32019-02-15 14:31:49 +0100311 Krb5Data k5_;
312 Options options_;
313 bool did_run_ = false;
314};
315
Lutz Justen90281402019-07-05 15:14:37 +0200316// Runs the Kerberos configuration |krb5conf| through the krb5 code to see if it
317// can be parsed.
318ErrorType ValidateConfigViaKrb5(const std::string& krb5conf) {
319 // Since krb5 doesn't accept config passed as string, write it to disk.
320 base::FilePath krb5conf_path;
321 if (!base::CreateTemporaryFile(&krb5conf_path)) {
322 LOG(ERROR) << "Failed to create temp file for validating config";
323 return ERROR_LOCAL_IO;
324 }
325
326 const int size = static_cast<int>(krb5conf.size());
327 if (base::WriteFile(krb5conf_path, krb5conf.data(), size) != size) {
328 LOG(ERROR) << "Failed to write config to disk at " << krb5conf_path.value()
329 << " for validating config";
330 return ERROR_LOCAL_IO;
331 }
332
333 // krb5_init_context parses the config file.
334 setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
335 ScopedKrb5Context ctx;
336 krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
337 unsetenv(kKrb5ConfigEnvVar);
hscham53cf73a2020-11-30 15:58:42 +0900338 base::DeleteFile(krb5conf_path);
Lutz Justen90281402019-07-05 15:14:37 +0200339
340 if (ret) {
341 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
342 return TranslateErrorCode(ret);
343 }
344
345 return ERROR_NONE;
346}
347
Lutz Justen09cd1c32019-02-15 14:31:49 +0100348} // namespace
349
Lutz Justene39cbd42019-05-14 14:52:24 +0200350Krb5InterfaceImpl::Krb5InterfaceImpl() = default;
Lutz Justen09cd1c32019-02-15 14:31:49 +0100351
Lutz Justene39cbd42019-05-14 14:52:24 +0200352Krb5InterfaceImpl::~Krb5InterfaceImpl() = default;
Lutz Justen09cd1c32019-02-15 14:31:49 +0100353
Lutz Justene39cbd42019-05-14 14:52:24 +0200354ErrorType Krb5InterfaceImpl::AcquireTgt(const std::string& principal_name,
355 const std::string& password,
356 const base::FilePath& krb5cc_path,
357 const base::FilePath& krb5conf_path) {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100358 Options options;
359 options.action = Action::AcquireTgt;
360 options.principal_name = principal_name;
361 options.password = password;
Lutz Justenb79da832019-03-08 14:52:53 +0100362 options.krb5cc_path = krb5cc_path.value();
363 setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100364 ErrorType error = KinitContext(std::move(options)).Run();
365 unsetenv(kKrb5ConfigEnvVar);
366 return error;
367}
368
Lutz Justene39cbd42019-05-14 14:52:24 +0200369ErrorType Krb5InterfaceImpl::RenewTgt(const std::string& principal_name,
370 const base::FilePath& krb5cc_path,
Lutz Justene6784c02019-07-03 14:08:43 +0200371 const base::FilePath& krb5conf_path) {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100372 Options options;
373 options.action = Action::RenewTgt;
374 options.principal_name = principal_name;
Lutz Justenb79da832019-03-08 14:52:53 +0100375 options.krb5cc_path = krb5cc_path.value();
Lutz Justene6784c02019-07-03 14:08:43 +0200376 setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100377 ErrorType error = KinitContext(std::move(options)).Run();
378 unsetenv(kKrb5ConfigEnvVar);
379 return error;
380}
381
Lutz Justene39cbd42019-05-14 14:52:24 +0200382ErrorType Krb5InterfaceImpl::GetTgtStatus(const base::FilePath& krb5cc_path,
383 TgtStatus* status) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100384 DCHECK(status);
385
386 ScopedKrb5Context ctx;
387 krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
388 if (ret) {
389 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
390 return TranslateErrorCode(ret);
391 }
392
Lutz Justen1cb62412019-05-09 10:09:45 +0200393 ScopedKrb5CCache ccache(ctx.get());
Lutz Justencb8399d2019-03-08 14:30:17 +0100394 std::string prefixed_krb5cc_path = "FILE:" + krb5cc_path.value();
395 ret = krb5_cc_resolve(ctx.get(), prefixed_krb5cc_path.c_str(),
Lutz Justen1cb62412019-05-09 10:09:45 +0200396 ccache.get_mutable_ptr());
Lutz Justencb8399d2019-03-08 14:30:17 +0100397 if (ret) {
Lutz Justen1cb62412019-05-09 10:09:45 +0200398 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while resolving cache";
Lutz Justencb8399d2019-03-08 14:30:17 +0100399 return TranslateErrorCode(ret);
400 }
401
402 krb5_cc_cursor cur;
Lutz Justen1cb62412019-05-09 10:09:45 +0200403 ret = krb5_cc_start_seq_get(ctx.get(), ccache.get(), &cur);
Lutz Justencb8399d2019-03-08 14:30:17 +0100404 if (ret) {
405 LOG(ERROR) << ctx.GetErrorMessage(ret)
406 << " while starting to retrieve tickets";
407 return TranslateErrorCode(ret);
408 }
409
410 krb5_timestamp now = time(nullptr);
411
412 krb5_creds creds;
413 bool found_tgt = false;
Lutz Justen1cb62412019-05-09 10:09:45 +0200414 while ((ret = krb5_cc_next_cred(ctx.get(), ccache.get(), &cur, &creds)) ==
415 0) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100416 if (IsTgt(creds)) {
417 if (creds.times.endtime)
418 status->validity_seconds =
419 std::max<int64_t>(creds.times.endtime - now, 0);
420
421 if (creds.times.renew_till) {
422 status->renewal_seconds =
423 std::max<int64_t>(creds.times.renew_till - now, 0);
424 }
425
426 if (found_tgt) {
427 LOG(WARNING) << "More than one TGT found in credential cache '"
428 << krb5cc_path.value() << ".";
429 }
430 found_tgt = true;
431 }
432 krb5_free_cred_contents(ctx.get(), &creds);
433 }
434 if (!found_tgt) {
435 LOG(WARNING) << "No TGT found in credential cache '" << krb5cc_path.value()
436 << ".";
437 }
438
439 if (ret != KRB5_CC_END) {
440 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while retrieving a ticket";
441 return TranslateErrorCode(ret);
442 }
443
Lutz Justen1cb62412019-05-09 10:09:45 +0200444 ret = krb5_cc_end_seq_get(ctx.get(), ccache.get(), &cur);
Lutz Justencb8399d2019-03-08 14:30:17 +0100445 if (ret) {
446 LOG(ERROR) << ctx.GetErrorMessage(ret)
447 << " while finishing ticket retrieval";
448 return TranslateErrorCode(ret);
449 }
450
451 return ERROR_NONE;
452}
453
Lutz Justen90281402019-07-05 15:14:37 +0200454ErrorType Krb5InterfaceImpl::ValidateConfig(const std::string& krb5conf,
455 ConfigErrorInfo* error_info) {
Felipe Andradea0cbde72020-04-01 15:40:10 +0200456 *error_info = config_parser_.Validate(krb5conf);
Lutz Justen70496c12019-07-24 11:11:55 +0200457 if (error_info->code() != CONFIG_ERROR_NONE)
458 return ERROR_BAD_CONFIG;
Lutz Justen90281402019-07-05 15:14:37 +0200459
460 // Also try the mit krb5 code to parse the config.
461 error_info->Clear();
462 ErrorType error = ValidateConfigViaKrb5(krb5conf);
463 if (error == ERROR_BAD_CONFIG) {
464 error_info->set_code(CONFIG_ERROR_KRB5_FAILED_TO_PARSE);
465 return error;
466 }
467
468 // Ignore all other errors, they're most likely unrelated. The
Felipe Andradea0cbde72020-04-01 15:40:10 +0200469 // |config_parser_| should already cover pretty much everything, anyway.
Lutz Justen90281402019-07-05 15:14:37 +0200470 error_info->set_code(CONFIG_ERROR_NONE);
471 if (error != ERROR_NONE) {
472 LOG(WARNING) << "Ignoring unrelated error " << GetErrorString(error)
473 << " while validating config";
474 }
475 return error;
476}
477
Lutz Justen09cd1c32019-02-15 14:31:49 +0100478} // namespace kerberos