Skip to content

Conversation

@petrsnd
Copy link
Contributor

@petrsnd petrsnd commented Sep 10, 2025

What's the problem?

The primary goal of this PR is to address issue #185 - Add support for DNS in non-Windows environments

which I am characterizing as a new feature. I didn't find a way to wire an alternative implementation in via NuGet package and didn't want to use Fody or anything magic during assembly load to do it.

A secondary goal was to improve Kerberos.NET and Bruce support for non-Windows operating systems, which I'm saying are bugfixes, so I've checked both boxes below.

Before this PR, Bruce couldn't be run on Linux (or macOS) because of the KerbDumpCore dependency.

image

Additional challenges included default path handling on the non-Windows platforms and making the AsnXml generation work there as well.

  • Bugfix
  • New Feature

What's the solution?

Portable DNS

I added a separate project to the solution called Kerberos.NET.PortableDns and I made Bruce depend on both Kerberos.NET and the new project. I could have made the dependency conditional depending on the platform in Bruce, but I didn't feel it was worth the effort. I also wanted to maintain the behavior where Bruce uses Windows built-in DNS unless it was running a non-Windows platform, so I just did that by checking the OS in code.

Much of the code for Kerberos.NET.PortableDns is pulled over from the implementation previously written directly in Bruce. It also relies on DnsClient.

To use this implementation instead of the Windows built-in DNS,

  1. Add the NuGet package to your project, and
  2. Call the PortableDnsClient.Configure() method or one of its overloads which will allow you to specify an alternate DNS server.

The PortableDnsClient class includes a static constructor that registers the DNS implementation with Kerberos.NET, which gets called the first time the class gets referenced. That happens when you call the Configure() method. This one-liner approach seemed like a simple way to allow use of a platform-independent, pure-.NET DNS implementation with ability to override DNS server in code at runtime. That is what I needed for my project.

Bruce on non-Windows

To fix up Bruce for non-Windows platforms, I made sure that all of the framework targeting and OS detection was in place. The default location of krb5.conf was mostly working, but the libdefaults were not without conditional code, which I used preprocessor directives to fix because of how the defaults are implemented in Krb5ConfigDefaults.cs. It would have taken a major overhaul to do that a different way.

I made the decision to go with XDG_CONFIG_HOME of the current user rather than defaulting to the system-wide krb5.conf on Linux. That seemed more appropriate to use this value for the current user like we were on Windows and macOS. For more
information, see https://specifications.freedesktop.org/basedir-spec/latest/. macOS uses ~/Library/Preferences/Kerberos.NET/ just as it used to.

I also made a change to allow for variable substitution of environment variables on all platforms, but the syntax needs to continue with the Windows style of %VAR%, but this made it possible to set good defaults for a current user Kerberos client implementation on Linux and macOS.

Anyway, the result is that Bruce now works great in Linux, WSL, or on macOS.
image

And, libdefaults config uses the same location as the default krb5.conf.
image

image
  • Includes unit tests
  • Requires manual test

What issue is this related to, if any?

#185 - Add support for DNS in non-Windows environments

The goal is to get Bruce working on Linux with platform-agnostic DNS
resolution out-of-the-box, but Bruce refs the Windows forms project
for KerbDumpCommand, although code is short-circuited for non-Windows
Code written prior to C# 8 generally has warnings related to nullable
reference type warnings. Setting nullable as diabled for the projects
and just enabling it for the one place it is used in a more recent
update makes the warnings go away.

Generating assembly info allows the target for net8.0-windows to set
runtime versioning to Windows which avoids a bunch of CA1416 errors.
Windows Forms code does not build on Linux so I changed this to use
precompiler directives. Moved to more up-to-date version of C# to avoid
additional issues with nullable.
XslTransform is running on Linux, but it is reporting everything as
changed. Added support to use diff on Unix to properly detect whether
something has actually changed.
Rather than defaulting to the system-wide krb5.conf on Linux, it seemed
more appropriate to use this value for a CurrentUser krb5.conf. For more
information see
https://specifications.freedesktop.org/basedir-spec/latest/
Krb5Config dynamically builds paths using the GetFilePath() method to
deal with differing operating system defaults. Krb5ConfigDefaults cannot
use that because it relies on DefaultValueAttribute. The default
ccache name crashes immediately with an illegal Mutex name. Conditional
compilation is the only solution without rewriting a lot of krb5.conf
handling code.
If we want Kerberos.NET to be completely compliant with MIT Kerberos
defaults, then we can change some of the paths. The location of
krb5.conf is usually system-wide (/etc/krb5.conf) and the kdc.conf is in
the $LOCALSTATEDIR/krb5kdc. /etc isn't a user configuration location so
I changed it to $XDG_CONFIG_HOME, and I added the ability to expand
variables set in the krb5.conf. That can allow putting the krb5ccache in
the home directory with %HOME%. We should consider honoring the
%KRB5CCNAME% environment variable.
…ed platform

use .NET 8 updated OS detection
but change as little code as possible
if (string.Equals(descName, desc, StringComparison.OrdinalIgnoreCase))
{
this.WriteLine(string.Format(format, label), attr.Description, commands.Skip(1));
this.WriteLine(string.Format(format, label), attr.Description, string.Join(", ", commands.Skip(1)));
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thank you for fixing this. It's been mildly bugging me for a while now.

@SteveSyfuhs
Copy link
Collaborator

This is fantastic, thank you for doing this. I'm very happy with everything I see and have no issues or recommendations. I've tested it locally on Windows and am satisfied it hasn't regressed anything there, but the build is unhappy due to packaging. Let me see if I can sort that out. If this is ready to go, I'll merge it in as soon as the packaging is sorted.

@SteveSyfuhs
Copy link
Collaborator

Alright, well that was easier than I thought. Let me know if you have any more changes you want to make, otherwise I'm good to merge it in.

@petrsnd
Copy link
Contributor Author

petrsnd commented Sep 11, 2025

I'd like to have the Kerberos.NET.PortableDns package also published to NuGet, but I didn't even look into that.

I think the code is ready to go. I just wanted to make sure you were happy with that first. You can merge as soon as you like.

@SteveSyfuhs
Copy link
Collaborator

We can get that package set up.

@SteveSyfuhs SteveSyfuhs merged commit 1f81ec2 into dotnet:develop Sep 11, 2025
3 checks passed
@petrsnd petrsnd deleted the portable-dns-linux-support branch September 11, 2025 18:35
@petrsnd
Copy link
Contributor Author

petrsnd commented Sep 12, 2025

@SteveSyfuhs If you'd like me to help with building/versioning/packaging Kerberos.NET.PortableDns for NuGet, just let me know. I haven't looked into how you're handling those concerns with this project,. I'm happy to provide some assistance if you want it, such as adding packaging properties to the .csproj or writing a nuspec file or whatever you want depending on the pattern you're following.

@SteveSyfuhs
Copy link
Collaborator

@petrsnd I've created this package here: https://www.nuget.org/packages/Kerberos.NET.PortableDns/4.6.116

When you get a second do you want to give it a try?

@petrsnd
Copy link
Contributor Author

petrsnd commented Sep 24, 2025

@SteveSyfuhs I was able to try this out by switching over to NuGet packages from direct project integration on a project that I'm playing with. It works well. Thank you!

Just as a point of feedback... I made a coding mistake when I was working on this that caused an error inside Kerberos.NET. The exception was thrown in a perfectly acceptable way, but when I wanted to debug in to see what was going on, I found that there are no symbols packages for Kerberos.NET. To figure out what I was doing wrong, I ended up going back over to the Kerberos.NET code base to write up a quick test app that I could debug into. It took a little longer, but I was able to figure out my mistake. I would love to have debug symbols packages. I'm going to check for an enhancement issue for that and add one if it isn't there.

Thanks again!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants