Skip to content

Creating a keytab for an AES256

I had a problem with a Kerberos keytab I created with ktpass on the Windows Server after the domain doesn’t accept RC4 any more. The keyfile could be created, but any service on Linux had errors like “checksum failed” or “Request ticket server HTTP/fqdn@REALM kvno 2 enctype aes256-cts found in keytab but cannot decrypt ticket”.

After a lot of searching and combining the information, I found this:

  1. Keytabs with AES256 use a salt, which keytabs with RC4 don't. And Windows Server uses another salt than Kerberos clients on Linux. Because RC4 doesn't use a salt, this is/was no problem with RC4 keytabs. Since RC4 shouldn't be supported any more in domains, this problem arises now.
  2. The salt must be known when creating the keyfile.
  3. The salt is tied to the domain account. If a domain account has many SPNs, the salt for these SPNs stays the same.
  4. To create the keyfile, you also need to know the Domain Account password and the key version number (kvno, this is the value of the AD account's attribute msDS-KeyVersionNumber)
  5. The kvno will be incremented each time the domain account's password is changed.
With these information, we can create a keytab for all SPNs from one Domain Account:
The Domain Account password should be known and the kvno can be looked up in the account's attributes.
Let's say your SPN is HTTP/mysite.example.local and your realm name (Active Directory domain name) is EXAMPLE.LOCAL for the next examples:

We can get the salt by trying to login to Kerberos. Therefore we create a dummy-keytab with the correct SPN on the Linux command line:
$ ktutil
ktutil: addent -password -p HTTP/mysite.example.local@EXAMPLE.LOCAL -k kvno -e aes256-cts-hmac-sha1-96
Password for HTTP/mysite.example.local@EXAMPLE.LOCAL: (enter anything, for exampe "test")
ktutil: write_kt /path/to/new/keytab


Next, we try to login with the keytab. This won't work, but we will get the salt:

$ KRB5_TRACE=/dev/stdout kinit -V -k -t /path/to/new/keytab HTTP/mysite.example.local@EXAMPLE.LOCAL

Somewhere in the trace data, we will find the salt:
[...]
Selected etype info: etype aes256-cts, salt "EXAMPLE.LOCALmysite.example.local", params ""
[...]


With this salt, we can generate the keytab (add one addent-command for every SPN):
$ ktutil
ktutil: addent -password -p HTTP/mysite.example.local@EXAMPLE.LOCAL -k kvno -e aes256-cts-hmac-sha1-96 -s EXAMPLE.LOCALmysite.example.local
Password for HTTP/mysite.example.local@EXAMPLE.LOCAL: (enter the password of the domain account)

Add as many SPNs with new addent-commands as you like. Just change the SPN, the rest stays the same

ktutil: write_kt /path/to/new/keytab

Now you have a keytab with all the SPNs at /path/to/new/keytab.

Temporary workaround for AssemblyKeyName and Visual Studio 15.6

Visual Studio 2017 version 15.6 currently has a problem if a project signs an assembly with the AssemblyKeyNameAttribute: https://developercommunity.visualstudio.com/content/problem/209811/strong-name-signing-with-a-key-installed-in-a-cont.html.

One suggested workaround is to add this line in the project file:
<Features>$(Features);UseLegacyStrongNameProvider</Features>

If you have many projects and don't want to include this in every project file, you can create a system-wide configuration for all projects. Create the file %LOCALAPPDATA%\Microsoft\MSBuild\15.0\Imports\Microsoft.Common.props\ImportAfter\Sign.props (the file name can be different, but it must be at that location) with this content:

<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<PropertyGroup>
<Features>$(Features);UseLegacyStrongNameProvider</Features>
</PropertyGroup>
</Project>

The workaround will be included in every build on that machine (for the current user account). Since I don't work on .NET Core projects, I don't know whether this breaks signed .NET Core builds.

Sharing a strong name key in a key container between multiple users on the same system

Today I imported a snk file to a key container as an Administrator and wanted to give another (non-admin) user access to that key container, so that he can sign assemblies with it.

I couldn’t find an easy solution. But I couldn’t believe that Microsoft doesn’t have a native tool for this and so I tried a solution, which is meant for ASP.NET: In a console I typed

aspnet_regiis.exe -pa <Key container name> <Username>

And it worked Smiley

Changing the Network Profile in Windows Server 2012

Sometimes I have a virtual machine running Windows Server 2012 and can’t reach some of its services because I allowed their ports only for private networks in the Windows Firewall. Then I see that the network connection has the public profile. This is the easiest way I found to change the profile:

Open a PowerShell with administrator privileges and type

Get-NetConnectionProfile

You should get a list of network interfaces:

Name             : Network
InterfaceAlias   : Ethernet
InterfaceIndex   : 12
NetworkCategory  : Private
IPv4Connectivity : Internet
IPv6Connectivity : NoTraffic

Name             : Network #2
InterfaceAlias   : LAN-Connection
InterfaceIndex   : 17
NetworkCategory  : Public
IPv4Connectivity : LocalNetwork
IPv6Connectivity : NoTraffic

You see that the second network is a public network. Use the InterfaceIndex 17 and enter:

Set-NetConnectionProfile -InterfaceIndex 17 -NetworkCategory Private

Now it is a private network!

Change user password in Windows Server 2012 R2 via RDP

Today one of my colleagues wanted to change his password in Windows Server 2012 R2 via a Remote Desktop Connection.

On a local systems you can press CTRL+ALT+DEL to select “Change password”. Obviously you can’t send this key combination through a Remote Desktop Connection. Solution: Press CTRL+ALT+END!

.NET compatibility between .NET 4 and 4.5 with referenced assemblies

There aren't many breaking changes between .NET 4 and .NET 4.5, but after reading http://blogs.msdn.com/b/webdev/archive/2012/11/19/all-about-httpruntime-targetframework.aspx I was interested how the compatibility layer would react if the main assembly is compiled for .NET 4.5 and a referenced assembly for .NET 4.

I tested it with the List<T>.ForEach method in the blog post, and it acted like I thought it would: The main assembly specifies the compatibility level. If the main assembly is compiled for .NET 4.5, all referenced assemblies are also executed using .NET 4.5, even if they are compiled for .NET 4.

Disposable wrapper for WCF clients

When a WCF client calls a service and the call throws an exception (no FaultException, that's fine), then calling Close() or Dispose() on that client will throw another Exception because the client is in the faulted state. The correct way to "dispose" or cleanup a faulted client is to call Abort(). This means that we can't embed the WCF client in a using-statement because that will always dispose the client.

The correct way would be

ServiceClient myClient = new ServiceClient();
try
{
myClient.DoSomething();
myClient.Close();
}
catch
{
myClient.Abort();
// error handling or throw;
}

Because some of my projects use a lot of WCF calls, this pattern is too tedious for me. Instead I wrote a simple wrapper:

using System;
using System.ServiceModel;

public class GenericProxy<T> : ClientBase<T>, IDisposable
where T : class
{
public GenericProxy()
: base()
{
}

void IDisposable.Dispose()
{
if (State == CommunicationState.Faulted)
Abort();
else
Close();
}

public T Service
{
get
{
return Channel;
}
}
}

The only drawback is that instead of writing myClient.DoSomething() now I have to write myClient.Channel.DoSomething():

using (GenericProxy<IService> myClient = new GenericProxy<IService>())
{
myClient.Channel.DoSomething();
}

Signing assemblies with a key container

This article is a reference for me since I have to look it up all the time.

Since .NET 1.0 I prefer to sign my assemblies and to use a key container with a AssemblyKeyNameAttribute instead of having to define the path of a key file in each assembly:

[assembly: AssemblyKeyName("myKeyName")]

Starting with .NET 2.0/Visual Studio 2005 this generates the compiler warning CS1699 (or an unnumbered warning for VB.NET). For my projects I always enable "Treat warnings as errors". For C# I can add 1699 to the suppressed warnings in the project settings, but I can't find a way to suppress the warning in the VB.NET project settings.

Instead I have to edit the .vbproj-file with a text editor and add somewhere in the first PropertyGroup element the line

<KeyContainerName>myKeyName</KeyContainerName>

Unfortunately Microsoft didn't add a project setting to use assembly key containers.

Getting Serendipity to work with Windows Live Writer

After installing the XML-RPC plug-in, I couldn't get Windows Live Writer to insert or update blog entries. After a week of trying and debugging I found out that the plug-in uses a boolean where serendipity expects a string.

In the file /plugins/serendipity_event_xmlrpc/serendipity_xmlrpc.inc.php I just had to change line 1600 from

$entry['moderate_comments'] = serendipity_db_bool($serendipity['moderateCommentsDefault']);
to

$entry['moderate_comments'] = serendipity_db_bool($serendipity['moderateCommentsDefault']) ? 'true' : 'false';

Additionally I had to create the media directory "Windows-Live-Writer" in the Administration panel.


Funny, that my .NET blog starts with a PHP-related post Zwinkerndes Smiley