Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

DNS: Add POSIX DNS implementation #334

Draft
wants to merge 14 commits into
base: develop
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions Bruce/Bruce.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,8 @@
<Product>Kerberos.NET Command Line Tool</Product>
<Description>A command line tool that manages the cross-platform, managed-code Kerberos Ticket parsing, validation, and authentication library Kerberos.NET.</Description>
<PackageTags>security kerberos</PackageTags>
<LangVersion>9</LangVersion>
<DefineConstants Condition="$([MSBuild]::IsOSPlatform('Windows'))">WINDOWS</DefineConstants>
</PropertyGroup>

<ItemGroup>
Expand All @@ -38,6 +40,9 @@

<ItemGroup>
<ProjectReference Include="..\Kerberos.NET\Kerberos.NET.csproj" />
</ItemGroup>

<ItemGroup Condition="$([MSBuild]::IsOSPlatform('Windows'))">
<ProjectReference Include="..\Samples\KerbDumpCore\KerbDumpCore.csproj" />
</ItemGroup>

Expand Down
6 changes: 6 additions & 0 deletions Bruce/CommandLine/KerberosDumpCommand.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
// -----------------------------------------------------------------------

using System.Threading.Tasks;
#if WINDOWS
using System.Windows.Forms;
using KerbDump;
#endif

namespace Kerberos.NET.CommandLine
{
Expand All @@ -14,8 +16,10 @@ public class KerberosDumpCommand : BaseCommand
{
static KerberosDumpCommand()
{
#if WINDOWS
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
#endif
}

public KerberosDumpCommand(CommandLineParameters parameters)
Expand All @@ -34,6 +38,7 @@ public override Task<bool> Execute()
return Task.FromResult(false);
}

#if WINDOWS
using (var form = new DecoderForm()
{
Ticket = this.Ticket,
Expand All @@ -42,6 +47,7 @@ public override Task<bool> Execute()
{
Application.Run(form);
}
#endif

return Task.FromResult(true);
}
Expand Down
2 changes: 2 additions & 0 deletions Bruce/Dns/PlatformIndependentDnsClient.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,8 @@ internal class PlatformIndependentDnsClient : IKerberosDnsQuery
{
private static readonly WindowsDnsQuery WindowsDns = new WindowsDnsQuery();

public bool Debug { get; set; }

public async Task<IReadOnlyCollection<DnsRecord>> Query(string query, DnsRecordType type)
{
if (WindowsDns.IsSupported)
Expand Down
7 changes: 5 additions & 2 deletions Kerberos.NET/Dns/DnsQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,16 @@ static DnsQuery()
if (OSPlatform.IsWindows)
{
QueryImplementation = new WindowsDnsQuery();
return;
}
//for now assume it's POSIX
QueryImplementation = new POSIXDnsQuery();
}

public static bool Debug
{
get => DnsQueryWin32.Debug;
set => DnsQueryWin32.Debug = value;
get => QueryImplementation.Debug;
set => QueryImplementation.Debug = value;
}

/// <summary>
Expand Down
232 changes: 232 additions & 0 deletions Kerberos.NET/Dns/DnsQueryPOSIX.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,232 @@
// -----------------------------------------------------------------------
// Licensed to The .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// -----------------------------------------------------------------------

using System;
using System.Buffers;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net;
using System.Net.NetworkInformation;
using System.Runtime.InteropServices;
using System.Text;

namespace Kerberos.NET.Dns
{
public unsafe class DnsQueryPOSIX
{
private const int NS_PACKETSZ = 512;
private const int NS_MAXDNAME = 1025;

private const string LIBC = "libc.so";

[DllImport(LIBC, EntryPoint = "res_query")]
private static extern short ResQuery(
[MarshalAs(UnmanagedType.LPStr)] string dname,
NsClass @class,
DnsRecordType type,
char[] answer,
int anslen
);

[DllImport(LIBC, EntryPoint = "ns_initparse")]
private static extern short NsInitParse(
// [MarshalAs(UnmanagedType.LPStr)] string msg,
char[] msg,
short msglen,
NsMsg* handle
);

[DllImport(LIBC, EntryPoint = "ns_msg_count")]
private static extern ushort NsMsgCount(
NsMsg handle,
NsSect section
);

[DllImport(LIBC, EntryPoint = "ns_parserr")]
private static extern short NsParserr(
NsMsg* handle,
NsSect section,
short rrnum,
NsRr* rr
);

[DllImport(LIBC, EntryPoint = "ns_rr_type")]
private static extern DnsRecordType NsRrType(
NsRr rr
);

[DllImport(LIBC, EntryPoint = "ns_msg_base")]
private static extern string NsMsgBase(
NsMsg handle
);

[DllImport(LIBC, EntryPoint = "ns_msg_end")]
private static extern string NsMsgEnd(
NsMsg handle
);

[DllImport(LIBC, EntryPoint = "ns_rr_rdata")]
private static extern string NsRrRdata(
NsRr rr
);

[DllImport(LIBC, EntryPoint = "dn_expand")]
private static extern short DnExpand(
[MarshalAs(UnmanagedType.LPStr)] string msg,
[MarshalAs(UnmanagedType.LPStr)] string eomorig,
[MarshalAs(UnmanagedType.LPStr)] string comp_dn,
StringBuilder exp_dn,
short length
);

[DllImport(LIBC, EntryPoint = "ns_rr_name")]
private static extern string NsRrName(
NsRr rr
);

[DllImport(LIBC, EntryPoint = "inet_ntoa")]
private static extern string InetNToA(
InAddr @in
);

public static IReadOnlyCollection<DnsRecord> QuerySrvRecord(
string query,
DnsRecordType type,
DnsQueryOptions options = DnsQueryOptions.BypassCache)
{
var list = new List<DnsRecord>();
var buffer = new char[NS_PACKETSZ];

short respLen = -1;
if ((respLen = ResQuery(query, NsClass.NsCIn, type, buffer, NS_PACKETSZ)) < 0)
Copy link
Collaborator

Choose a reason for hiding this comment

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

Nit: brackets

Copy link
Author

Choose a reason for hiding this comment

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

What's wrong about them?

throw new Exception($"Query for {query} failed!");

NsMsg handle;
if (NsInitParse(buffer, respLen, &handle) < 0)
throw new Exception("Failed to parse response buffer!");

var count = NsMsgCount(handle, NsSect.NsSAn);
Debug.WriteLine($"{count} records returned in the answer section.");

for (short i = 0; i < count; i++)
{
NsRr rr;
if (NsParserr(&handle, NsSect.NsSAn, i, &rr) < 0)
throw new Exception("ns_parserr: TODO strerror");

if (NsRrType(rr) != DnsRecordType.SRV) continue;

var name = new StringBuilder(1025);
short ret;
if ((ret = DnExpand(NsMsgBase(handle),
NsMsgEnd(handle),
NsRrRdata(rr) + 6,
name,
1025)) < 0)
throw new Exception($"Failed to uncompress name ({ret})");

Debug.WriteLine(name);

var p = NsRrRdata(rr);
var ip = new InAddr
{
s_addr = ((uint) p[3] << 24) | ((uint) p[2] << 16) | ((uint) p[1] << 8) | p[0]
};

list.Add(new DnsRecord
{
Target = InetNToA(ip),
Name = rr.name.ToString(),
//Port =
//Priority =
TimeToLive = (int) rr.ttl,
Type = rr.type,
//Weight = rr.
});
}

for (short i = 0; i < NsMsgCount(handle, NsSect.NsSAr); i++)
{
NsRr rr;
if (NsParserr(&handle, NsSect.NsSAr, i, &rr) < 0)
throw new Exception("ns_parserr: TODO strerror");

if (NsRrType(rr) != DnsRecordType.A) continue;

var p = NsRrRdata(rr);
var ip = new InAddr
{
s_addr = ((uint) p[3] << 24) | ((uint) p[2] << 16) | ((uint) p[1] << 8) | p[0]
};

Debug.WriteLine($"{NsRrName(rr)} has address {InetNToA(ip)}");

list.Add(new DnsRecord
{
Type = rr.type,
Name = rr.name.ToString(),
Target = InetNToA(ip)
});
}

return list;
}

private struct InAddr
{
public uint s_addr;
}

private struct NsRr
{
[MarshalAs(UnmanagedType.LPArray, SizeConst = NS_PACKETSZ)]
public char[] name;
public DnsRecordType type;
public ushort rr_class;
public uint ttl;
public ushort rdlength;
[MarshalAs(UnmanagedType.LPStr)]
public string rdata;
}

private enum NsSect
{
NsSQd = 0, /*%< Query: Question. */
NsSZn = 0, /*%< Update: Zone. */
NsSAn = 1, /*%< Query: Answer. */
NsSPr = 1, /*%< Update: Prerequisites. */
NsSNs = 2, /*%< Query: Name servers. */
NsSUd = 2, /*%< Update: Update. */
NsSAr = 3, /*%< Query|Update: Additional records. */
NsSMax = 4
}

private struct NsMsg
{
[MarshalAs(UnmanagedType.LPStr)] public string _msg, _eom;
public ushort _id, _flags;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) NsSect.NsSMax)]
public ushort[] _counts;
[MarshalAs(UnmanagedType.ByValArray, SizeConst = (int) NsSect.NsSMax)]
public string[] _sections;
public NsSect _sect;
public short _rrnum;
[MarshalAs(UnmanagedType.LPStr)]
public string _msg_ptr;
}

private enum NsClass : ushort
{
NsCInvalid,
NsCIn,
NsC2,
NsCChaos,
NsCHs,
NsCNone = 254,
NsCAny,
NsCMax = 65535
}
}
}
2 changes: 2 additions & 0 deletions Kerberos.NET/Dns/IKerberosDnsQuery.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,8 @@ namespace Kerberos.NET.Dns
/// </summary>
public interface IKerberosDnsQuery
{
public bool Debug { get; set; }

/// <summary>
/// Make a DNS lookup for the provided query and record type.
/// </summary>
Expand Down
31 changes: 31 additions & 0 deletions Kerberos.NET/Dns/POSIXDnsQuery.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
// -----------------------------------------------------------------------
// Licensed to The .NET Foundation under one or more agreements.
// The .NET Foundation licenses this file to you under the MIT license.
// -----------------------------------------------------------------------

using System;
using System.Collections.Generic;
using System.Threading.Tasks;

namespace Kerberos.NET.Dns
{
public class POSIXDnsQuery : IKerberosDnsQuery
{
public bool Debug { get; set; }

public bool IsSupported => OSPlatform.IsLinux;

public Task<IReadOnlyCollection<DnsRecord>> Query(string query, DnsRecordType type)
{
if (!IsSupported)
{
throw new InvalidOperationException(
"The POSIX DNS query implementation is not supported outside of POSIX-compliant systems");
}

var result = DnsQueryWin32.QuerySrvRecord(query, type);

return Task.FromResult(result);
}
}
}
1 change: 1 addition & 0 deletions Kerberos.NET/Kerberos.NET.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@
<Description>A cross-platform, managed-code Kerberos Ticket parsing, validation, and authentication library.</Description>
<PackageTags>security kerberos</PackageTags>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<LangVersion>9</LangVersion>
</PropertyGroup>

<PropertyGroup>
Expand Down
10 changes: 6 additions & 4 deletions Samples/KerbDumpCore/KerbDumpCore.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -4,25 +4,27 @@
<OutputType>Library</OutputType>
<TargetFramework>netcoreapp3.1</TargetFramework>
<UseWindowsForms>true</UseWindowsForms>
<EnableWindowsTargeting>true</EnableWindowsTargeting>

<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<AssemblyName>KerbDumpCore</AssemblyName>
<RootNamespace>KerbDump</RootNamespace>
<LangVersion>9</LangVersion>
</PropertyGroup>

<ItemGroup>
<Compile Include="..\KerbDump\**\*.cs" />
<EmbeddedResource Include="..\KerbDump\**\*.resx" />
</ItemGroup>

<ItemGroup>
<Compile Remove="..\KerbDump\Properties\AssemblyInfo.cs" />
</ItemGroup>

<ItemGroup>
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\..\Kerberos.NET\Kerberos.NET.csproj" />
</ItemGroup>
Expand Down
Loading