blob: 28a3807e1f3b47d131fb02e43449aca5b616c7a7 [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
Lutz Justenb79da832019-03-08 14:52:53 +010010#include <base/files/file_path.h>
Lutz Justen90281402019-07-05 15:14:37 +020011#include <base/files/file_util.h>
Lutz Justen09cd1c32019-02-15 14:31:49 +010012#include <base/logging.h>
13#include <base/strings/stringprintf.h>
14#include <krb5.h>
Lutz Justen70496c12019-07-24 11:11:55 +020015#include <profile.h>
Lutz Justen09cd1c32019-02-15 14:31:49 +010016
Lutz Justen90281402019-07-05 15:14:37 +020017#include "kerberos/error_strings.h"
18
Lutz Justen09cd1c32019-02-15 14:31:49 +010019namespace kerberos {
20
21namespace {
22
23// Environment variable for the Kerberos configuration (krb5.conf).
24constexpr char kKrb5ConfigEnvVar[] = "KRB5_CONFIG";
25
Lutz Justencb8399d2019-03-08 14:30:17 +010026// Wrapper classes for safe construction and destruction.
27struct ScopedKrb5Context {
28 ScopedKrb5Context() = default;
29 ~ScopedKrb5Context() {
30 if (ctx) {
31 krb5_free_context(ctx);
32 ctx = nullptr;
33 }
34 }
35
36 // Converts the krb5 |code| to a human readable error message.
37 std::string GetErrorMessage(errcode_t code) {
Lutz Justene5238762019-06-06 14:09:21 +020038 // Fallback if error happens during ctx initialization (e.g. bad config).
39 if (!ctx)
40 return base::StringPrintf("Error %ld", code);
41
Lutz Justencb8399d2019-03-08 14:30:17 +010042 const char* emsg = krb5_get_error_message(ctx, code);
43 std::string msg = base::StringPrintf("%s (%ld)", emsg, code);
44 krb5_free_error_message(ctx, emsg);
45 return msg;
46 }
47
48 krb5_context get() const { return ctx; }
49 krb5_context* get_mutable_ptr() { return &ctx; }
50
51 private:
52 krb5_context ctx = nullptr;
53};
54
55struct ScopedKrb5CCache {
Lutz Justen1cb62412019-05-09 10:09:45 +020056 // Prefer the constructor taking a context if possible.
57 ScopedKrb5CCache() {}
58 explicit ScopedKrb5CCache(krb5_context _ctx) { set_ctx(_ctx); }
59
Lutz Justencb8399d2019-03-08 14:30:17 +010060 ~ScopedKrb5CCache() {
61 if (ccache) {
Lutz Justen1cb62412019-05-09 10:09:45 +020062 DCHECK(ctx);
63 krb5_cc_close(ctx, ccache);
Lutz Justencb8399d2019-03-08 14:30:17 +010064 ccache = nullptr;
65 }
66 }
67
Lutz Justen1cb62412019-05-09 10:09:45 +020068 // The context must be set if |ccache| is set (though get_mutable_ptr())
69 // before this object is destroyed.
70 void set_ctx(krb5_context _ctx) {
71 ctx = _ctx;
72 DCHECK(ctx);
73 }
74
Lutz Justencb8399d2019-03-08 14:30:17 +010075 krb5_ccache get() const { return ccache; }
76 krb5_ccache* get_mutable_ptr() { return &ccache; }
77
78 private:
79 // Pointer to parent data, not owned.
Lutz Justen1cb62412019-05-09 10:09:45 +020080 krb5_context ctx = nullptr;
Lutz Justencb8399d2019-03-08 14:30:17 +010081 krb5_ccache ccache = nullptr;
82};
83
84// Maps some common krb5 error codes to our internal codes. If something is not
85// reported properly, add more cases here.
86ErrorType TranslateErrorCode(errcode_t code) {
87 switch (code) {
88 case KRB5KDC_ERR_NONE:
89 return ERROR_NONE;
90
91 case KRB5_KDC_UNREACH:
92 return ERROR_NETWORK_PROBLEM;
93
Lutz Justene5238762019-06-06 14:09:21 +020094 case KRB5_CONFIG_BADFORMAT:
Lutz Justen70496c12019-07-24 11:11:55 +020095 case PROF_BAD_BOOLEAN:
96 case PROF_BAD_INTEGER:
Lutz Justene5238762019-06-06 14:09:21 +020097 return ERROR_BAD_CONFIG;
98
Lutz Justencb8399d2019-03-08 14:30:17 +010099 case KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN:
100 return ERROR_BAD_PRINCIPAL;
101
102 case KRB5KRB_AP_ERR_BAD_INTEGRITY:
103 case KRB5KDC_ERR_PREAUTH_FAILED:
104 return ERROR_BAD_PASSWORD;
105
106 case KRB5KDC_ERR_KEY_EXP:
107 return ERROR_PASSWORD_EXPIRED;
108
109 // TODO(https://crbug.com/951741): Verify
110 case KRB5_KPASSWD_SOFTERROR:
111 return ERROR_PASSWORD_REJECTED;
112
113 // TODO(https://crbug.com/951741): Verify
114 case KRB5_FCC_NOFILE:
115 return ERROR_NO_CREDENTIALS_CACHE_FOUND;
116
117 // TODO(https://crbug.com/951741): Verify
118 case KRB5KRB_AP_ERR_TKT_EXPIRED:
119 return ERROR_KERBEROS_TICKET_EXPIRED;
120
121 case KRB5KDC_ERR_ETYPE_NOSUPP:
122 return ERROR_KDC_DOES_NOT_SUPPORT_ENCRYPTION_TYPE;
123
124 case KRB5_REALM_UNKNOWN:
125 return ERROR_CONTACTING_KDC_FAILED;
126
127 default:
128 return ERROR_UNKNOWN_KRB5_ERROR;
129 }
130}
131
132// Returns true if the string contained in |data| matches |str_to_match|.
133bool DataMatches(const krb5_data& data, const char* str_to_match) {
134 // It is not clear whether data.data is null terminated, so a strcmp might
135 // not work.
136 return strlen(str_to_match) == data.length &&
137 memcmp(str_to_match, data.data, data.length) == 0;
138}
139
140// Returns true if |creds| has a server that starts with "krbtgt".
141bool IsTgt(const krb5_creds& creds) {
142 return creds.server && creds.server->length > 0 &&
143 DataMatches(creds.server->data[0], "krbtgt");
144}
145
Lutz Justen09cd1c32019-02-15 14:31:49 +0100146enum class Action { AcquireTgt, RenewTgt };
147
148struct Options {
149 std::string principal_name;
150 std::string password;
151 std::string krb5cc_path;
152 std::string config_path;
153 Action action = Action::AcquireTgt;
154};
155
156// Encapsulates krb5 context data required for kinit.
157class KinitContext {
158 public:
159 explicit KinitContext(Options options) : options_(std::move(options)) {
160 memset(&k5_, 0, sizeof(k5_));
161 }
162
163 // Runs kinit with the options passed to the constructor. Only call once per
164 // context. While in principle it should be fine to run multiple times, the
165 // code path probably hasn't been tested (kinit does not call this multiple
166 // times).
167 ErrorType Run() {
168 DCHECK(!did_run_);
169 did_run_ = true;
170
171 ErrorType error = Initialize();
172 if (error == ERROR_NONE)
173 error = RunKinit();
174 Finalize();
175 return error;
176 }
177
178 private:
179 // The following code has been adapted from kinit.c in the mit-krb5 code base.
180 // It has been formatted to fit this screen.
181
182 struct Krb5Data {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100183 krb5_principal me;
184 char* name;
185 };
186
187 // Wrapper around krb5 data to get rid of the gotos in the original code.
188 struct KInitData {
189 // Pointer to parent data, not owned.
Lutz Justencb8399d2019-03-08 14:30:17 +0100190 const krb5_context ctx = nullptr;
191 // Pointer to parent data, not owned.
Lutz Justen09cd1c32019-02-15 14:31:49 +0100192 const Krb5Data* k5 = nullptr;
193 krb5_creds my_creds;
194 krb5_get_init_creds_opt* options = nullptr;
195
196 // The lifetime of the |k5| pointer must exceed the lifetime of this object.
Lutz Justencb8399d2019-03-08 14:30:17 +0100197 explicit KInitData(const krb5_context ctx, const Krb5Data* k5)
198 : ctx(ctx), k5(k5) {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100199 memset(&my_creds, 0, sizeof(my_creds));
200 }
201
202 ~KInitData() {
203 if (options)
Lutz Justencb8399d2019-03-08 14:30:17 +0100204 krb5_get_init_creds_opt_free(ctx, options);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100205 if (my_creds.client == k5->me)
206 my_creds.client = nullptr;
Lutz Justencb8399d2019-03-08 14:30:17 +0100207 krb5_free_cred_contents(ctx, &my_creds);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100208 }
209 };
210
Lutz Justen09cd1c32019-02-15 14:31:49 +0100211 // Initializes krb5 data.
212 ErrorType Initialize() {
Lutz Justencb8399d2019-03-08 14:30:17 +0100213 krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
Lutz Justen09cd1c32019-02-15 14:31:49 +0100214 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100215 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100216 return TranslateErrorCode(ret);
217 }
218
Lutz Justen1cb62412019-05-09 10:09:45 +0200219 out_cc.set_ctx(ctx.get());
220 ret = krb5_cc_resolve(ctx.get(), options_.krb5cc_path.c_str(),
221 out_cc.get_mutable_ptr());
Lutz Justen09cd1c32019-02-15 14:31:49 +0100222 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100223 LOG(ERROR) << ctx.GetErrorMessage(ret) << " resolving ccache";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100224 return TranslateErrorCode(ret);
225 }
226
Lutz Justencb8399d2019-03-08 14:30:17 +0100227 ret = krb5_parse_name_flags(ctx.get(), options_.principal_name.c_str(),
Lutz Justen09cd1c32019-02-15 14:31:49 +0100228 0 /* flags */, &k5_.me);
229 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100230 LOG(ERROR) << ctx.GetErrorMessage(ret) << " when parsing name";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100231 return TranslateErrorCode(ret);
232 }
233
Lutz Justencb8399d2019-03-08 14:30:17 +0100234 ret = krb5_unparse_name(ctx.get(), k5_.me, &k5_.name);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100235 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100236 LOG(ERROR) << ctx.GetErrorMessage(ret) << " when unparsing name";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100237 return TranslateErrorCode(ret);
238 }
239
240 options_.principal_name = k5_.name;
241 return ERROR_NONE;
242 }
243
244 // Finalizes krb5 data.
245 void Finalize() {
Lutz Justencb8399d2019-03-08 14:30:17 +0100246 krb5_free_unparsed_name(ctx.get(), k5_.name);
247 krb5_free_principal(ctx.get(), k5_.me);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100248 memset(&k5_, 0, sizeof(k5_));
249 }
250
251 // Runs the actual kinit code and acquires/renews tickets.
252 ErrorType RunKinit() {
253 krb5_error_code ret;
Lutz Justencb8399d2019-03-08 14:30:17 +0100254 KInitData d(ctx.get(), &k5_);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100255
Lutz Justencb8399d2019-03-08 14:30:17 +0100256 ret = krb5_get_init_creds_opt_alloc(ctx.get(), &d.options);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100257 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100258 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while getting options";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100259 return TranslateErrorCode(ret);
260 }
261
Lutz Justencb8399d2019-03-08 14:30:17 +0100262 ret = krb5_get_init_creds_opt_set_out_ccache(ctx.get(), d.options,
Lutz Justen1cb62412019-05-09 10:09:45 +0200263 out_cc.get());
Lutz Justen09cd1c32019-02-15 14:31:49 +0100264 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100265 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while getting options";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100266 return TranslateErrorCode(ret);
267 }
268
269 // To get notified of expiry, see
270 // krb5_get_init_creds_opt_set_expire_callback
271
272 switch (options_.action) {
273 case Action::AcquireTgt:
274 ret = krb5_get_init_creds_password(
Lutz Justencb8399d2019-03-08 14:30:17 +0100275 ctx.get(), &d.my_creds, k5_.me, options_.password.c_str(),
Lutz Justen09cd1c32019-02-15 14:31:49 +0100276 nullptr /* prompter */, nullptr /* data */, 0 /* start_time */,
277 nullptr /* in_tkt_service */, d.options);
278 break;
279 case Action::RenewTgt:
Lutz Justen1cb62412019-05-09 10:09:45 +0200280 ret =
281 krb5_get_renewed_creds(ctx.get(), &d.my_creds, k5_.me, out_cc.get(),
282 nullptr /* options_.in_tkt_service */);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100283 break;
284 }
285
286 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100287 LOG(ERROR) << ctx.GetErrorMessage(ret);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100288 return TranslateErrorCode(ret);
289 }
290
291 if (options_.action != Action::AcquireTgt) {
Lutz Justen1cb62412019-05-09 10:09:45 +0200292 ret = krb5_cc_initialize(ctx.get(), out_cc.get(), k5_.me);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100293 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100294 LOG(ERROR) << ctx.GetErrorMessage(ret) << " when initializing cache";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100295 return TranslateErrorCode(ret);
296 }
297
Lutz Justen1cb62412019-05-09 10:09:45 +0200298 ret = krb5_cc_store_cred(ctx.get(), out_cc.get(), &d.my_creds);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100299 if (ret) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100300 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while storing credentials";
Lutz Justen09cd1c32019-02-15 14:31:49 +0100301 return TranslateErrorCode(ret);
302 }
303 }
304
305 return ERROR_NONE;
306 }
307
Lutz Justencb8399d2019-03-08 14:30:17 +0100308 ScopedKrb5Context ctx;
Lutz Justen1cb62412019-05-09 10:09:45 +0200309 ScopedKrb5CCache out_cc;
Lutz Justen09cd1c32019-02-15 14:31:49 +0100310 Krb5Data k5_;
311 Options options_;
312 bool did_run_ = false;
313};
314
Lutz Justen90281402019-07-05 15:14:37 +0200315// Runs the Kerberos configuration |krb5conf| through the krb5 code to see if it
316// can be parsed.
317ErrorType ValidateConfigViaKrb5(const std::string& krb5conf) {
318 // Since krb5 doesn't accept config passed as string, write it to disk.
319 base::FilePath krb5conf_path;
320 if (!base::CreateTemporaryFile(&krb5conf_path)) {
321 LOG(ERROR) << "Failed to create temp file for validating config";
322 return ERROR_LOCAL_IO;
323 }
324
325 const int size = static_cast<int>(krb5conf.size());
326 if (base::WriteFile(krb5conf_path, krb5conf.data(), size) != size) {
327 LOG(ERROR) << "Failed to write config to disk at " << krb5conf_path.value()
328 << " for validating config";
329 return ERROR_LOCAL_IO;
330 }
331
332 // krb5_init_context parses the config file.
333 setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
334 ScopedKrb5Context ctx;
335 krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
336 unsetenv(kKrb5ConfigEnvVar);
337 base::DeleteFile(krb5conf_path, false /* recursive */);
338
339 if (ret) {
340 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
341 return TranslateErrorCode(ret);
342 }
343
344 return ERROR_NONE;
345}
346
Lutz Justen09cd1c32019-02-15 14:31:49 +0100347} // namespace
348
Lutz Justene39cbd42019-05-14 14:52:24 +0200349Krb5InterfaceImpl::Krb5InterfaceImpl() = default;
Lutz Justen09cd1c32019-02-15 14:31:49 +0100350
Lutz Justene39cbd42019-05-14 14:52:24 +0200351Krb5InterfaceImpl::~Krb5InterfaceImpl() = default;
Lutz Justen09cd1c32019-02-15 14:31:49 +0100352
Lutz Justene39cbd42019-05-14 14:52:24 +0200353ErrorType Krb5InterfaceImpl::AcquireTgt(const std::string& principal_name,
354 const std::string& password,
355 const base::FilePath& krb5cc_path,
356 const base::FilePath& krb5conf_path) {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100357 Options options;
358 options.action = Action::AcquireTgt;
359 options.principal_name = principal_name;
360 options.password = password;
Lutz Justenb79da832019-03-08 14:52:53 +0100361 options.krb5cc_path = krb5cc_path.value();
362 setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100363 ErrorType error = KinitContext(std::move(options)).Run();
364 unsetenv(kKrb5ConfigEnvVar);
365 return error;
366}
367
Lutz Justene39cbd42019-05-14 14:52:24 +0200368ErrorType Krb5InterfaceImpl::RenewTgt(const std::string& principal_name,
369 const base::FilePath& krb5cc_path,
Lutz Justene6784c02019-07-03 14:08:43 +0200370 const base::FilePath& krb5conf_path) {
Lutz Justen09cd1c32019-02-15 14:31:49 +0100371 Options options;
372 options.action = Action::RenewTgt;
373 options.principal_name = principal_name;
Lutz Justenb79da832019-03-08 14:52:53 +0100374 options.krb5cc_path = krb5cc_path.value();
Lutz Justene6784c02019-07-03 14:08:43 +0200375 setenv(kKrb5ConfigEnvVar, krb5conf_path.value().c_str(), 1);
Lutz Justen09cd1c32019-02-15 14:31:49 +0100376 ErrorType error = KinitContext(std::move(options)).Run();
377 unsetenv(kKrb5ConfigEnvVar);
378 return error;
379}
380
Lutz Justene39cbd42019-05-14 14:52:24 +0200381ErrorType Krb5InterfaceImpl::GetTgtStatus(const base::FilePath& krb5cc_path,
382 TgtStatus* status) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100383 DCHECK(status);
384
385 ScopedKrb5Context ctx;
386 krb5_error_code ret = krb5_init_context(ctx.get_mutable_ptr());
387 if (ret) {
388 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while initializing context";
389 return TranslateErrorCode(ret);
390 }
391
Lutz Justen1cb62412019-05-09 10:09:45 +0200392 ScopedKrb5CCache ccache(ctx.get());
Lutz Justencb8399d2019-03-08 14:30:17 +0100393 std::string prefixed_krb5cc_path = "FILE:" + krb5cc_path.value();
394 ret = krb5_cc_resolve(ctx.get(), prefixed_krb5cc_path.c_str(),
Lutz Justen1cb62412019-05-09 10:09:45 +0200395 ccache.get_mutable_ptr());
Lutz Justencb8399d2019-03-08 14:30:17 +0100396 if (ret) {
Lutz Justen1cb62412019-05-09 10:09:45 +0200397 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while resolving cache";
Lutz Justencb8399d2019-03-08 14:30:17 +0100398 return TranslateErrorCode(ret);
399 }
400
401 krb5_cc_cursor cur;
Lutz Justen1cb62412019-05-09 10:09:45 +0200402 ret = krb5_cc_start_seq_get(ctx.get(), ccache.get(), &cur);
Lutz Justencb8399d2019-03-08 14:30:17 +0100403 if (ret) {
404 LOG(ERROR) << ctx.GetErrorMessage(ret)
405 << " while starting to retrieve tickets";
406 return TranslateErrorCode(ret);
407 }
408
409 krb5_timestamp now = time(nullptr);
410
411 krb5_creds creds;
412 bool found_tgt = false;
Lutz Justen1cb62412019-05-09 10:09:45 +0200413 while ((ret = krb5_cc_next_cred(ctx.get(), ccache.get(), &cur, &creds)) ==
414 0) {
Lutz Justencb8399d2019-03-08 14:30:17 +0100415 if (IsTgt(creds)) {
416 if (creds.times.endtime)
417 status->validity_seconds =
418 std::max<int64_t>(creds.times.endtime - now, 0);
419
420 if (creds.times.renew_till) {
421 status->renewal_seconds =
422 std::max<int64_t>(creds.times.renew_till - now, 0);
423 }
424
425 if (found_tgt) {
426 LOG(WARNING) << "More than one TGT found in credential cache '"
427 << krb5cc_path.value() << ".";
428 }
429 found_tgt = true;
430 }
431 krb5_free_cred_contents(ctx.get(), &creds);
432 }
433 if (!found_tgt) {
434 LOG(WARNING) << "No TGT found in credential cache '" << krb5cc_path.value()
435 << ".";
436 }
437
438 if (ret != KRB5_CC_END) {
439 LOG(ERROR) << ctx.GetErrorMessage(ret) << " while retrieving a ticket";
440 return TranslateErrorCode(ret);
441 }
442
Lutz Justen1cb62412019-05-09 10:09:45 +0200443 ret = krb5_cc_end_seq_get(ctx.get(), ccache.get(), &cur);
Lutz Justencb8399d2019-03-08 14:30:17 +0100444 if (ret) {
445 LOG(ERROR) << ctx.GetErrorMessage(ret)
446 << " while finishing ticket retrieval";
447 return TranslateErrorCode(ret);
448 }
449
450 return ERROR_NONE;
451}
452
Lutz Justen90281402019-07-05 15:14:37 +0200453ErrorType Krb5InterfaceImpl::ValidateConfig(const std::string& krb5conf,
454 ConfigErrorInfo* error_info) {
Felipe Andradea0cbde72020-04-01 15:40:10 +0200455 *error_info = config_parser_.Validate(krb5conf);
Lutz Justen70496c12019-07-24 11:11:55 +0200456 if (error_info->code() != CONFIG_ERROR_NONE)
457 return ERROR_BAD_CONFIG;
Lutz Justen90281402019-07-05 15:14:37 +0200458
459 // Also try the mit krb5 code to parse the config.
460 error_info->Clear();
461 ErrorType error = ValidateConfigViaKrb5(krb5conf);
462 if (error == ERROR_BAD_CONFIG) {
463 error_info->set_code(CONFIG_ERROR_KRB5_FAILED_TO_PARSE);
464 return error;
465 }
466
467 // Ignore all other errors, they're most likely unrelated. The
Felipe Andradea0cbde72020-04-01 15:40:10 +0200468 // |config_parser_| should already cover pretty much everything, anyway.
Lutz Justen90281402019-07-05 15:14:37 +0200469 error_info->set_code(CONFIG_ERROR_NONE);
470 if (error != ERROR_NONE) {
471 LOG(WARNING) << "Ignoring unrelated error " << GetErrorString(error)
472 << " while validating config";
473 }
474 return error;
475}
476
Lutz Justen09cd1c32019-02-15 14:31:49 +0100477} // namespace kerberos