Skip to content

Commit

Permalink
Merge branch 'housekeeping'
Browse files Browse the repository at this point in the history
  • Loading branch information
oflebbe committed Apr 6, 2015
2 parents 97a4b75 + 3937af9 commit 3e06056
Show file tree
Hide file tree
Showing 4 changed files with 299 additions and 136 deletions.
56 changes: 56 additions & 0 deletions msktkrb5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -116,6 +116,62 @@ int flush_keytab(msktutil_flags *flags)
return ldap_flush_principals(flags);
}

void cleanup_keytab(msktutil_flags *flags)
{
VERBOSE("Cleaning the keytab");
KRB5Keytab keytab(flags->keytab_writename);

// Determine max kvno
krb5_kvno max_kvno;
// Delete all entries for this host
typedef std::vector<std::pair<std::pair<std::string, krb5_kvno>, krb5_enctype> > to_delete_t;
to_delete_t to_delete;
time_t ttNow = time(NULL);
try {
max_kvno = 0;
{
KRB5Keytab::cursor cursor(keytab);
while (cursor.next()) {
if (max_kvno < cursor.kvno()) {
max_kvno = cursor.kvno();
}
}
}

KRB5Keytab::cursor cursor(keytab);
while (cursor.next()) {
if (flags->cleanup_days > 0) {
// newer than cleanup_days
if (ttNow - cursor.timestamp() < flags->cleanup_days * 60 * 60 * 24)
continue;
// Never delete latest keys
if (max_kvno == cursor.kvno())
continue;
}
if (flags->cleanup_enctypes != VALUE_IGNORE) {
if (cursor.enctype() != flags->cleanup_enctypes) {
continue;
}
}
std::string principal = cursor.principal().name();
to_delete.push_back(std::make_pair(std::make_pair(principal, cursor.kvno()),
cursor.enctype()));
}


} catch (KRB5Exception ex) {
// Ignore errors reading keytab
}

for(to_delete_t::const_iterator it = to_delete.begin(); it != to_delete.end(); ++it) {
KRB5Principal princ(it->first.first);
krb5_kvno kvno = it->first.second;
krb5_enctype enctype = it->second;
VERBOSE("Deleting %s kvno=%d, enctype=%d", it->first.first.c_str(), kvno, enctype);
keytab.removeEntry(princ, kvno, enctype);
}
}


void update_keytab(msktutil_flags *flags)
{
Expand Down
217 changes: 126 additions & 91 deletions msktutil.M
Original file line number Diff line number Diff line change
Expand Up @@ -3,11 +3,11 @@
REPLACE_PROGNAME \- fetches and manages kerberos keytabs in an Active Directory environment
.SH SYNOPSIS
.B REPLACE_PROGNAME
[command 1] [command 2] [command 3] ...
[mode] [parameter 1] [parameter 2] ...
.SH DESCRIPTION
REPLACE_PROGNAME is a Unix/Linux keytab client for Microsoft Active Directory environments. This program is
REPLACE_PROGNAME is a Unix/Linux keytab utility for Microsoft Active Directory environments. This program is
capable of creating accounts in Active Directory, adding service principals to those accounts, and
creating local keytab files so that kerberizied services can utilize Active directory as a Kerberos realm.
creating local keytab files so that kerberizied services can utilize Active Directory as a Kerberos infrastructure.
REPLACE_PROGNAME will create and manage machine accounts by default. The --use-service-account option
lets REPLACE_PROGNAME operate on service accounts. REPLACE_PROGNAME requires that the Kerberos client
libraries are properly installed and configured to use Active Directory as a realm.
Expand Down Expand Up @@ -36,99 +36,55 @@ many computers to the domain.
To pre-create a computer account, you may use the Active Directory Users and Computers GUI, select
"new computer" from the right click menu, and type the short DNS name, then right click on the newly
created object and select "Reset account" to set the password to the default value. Another
alternative is to invoke REPLACE_PROGNAME with the --precreate argument. Both methods accomplish the
alternative is to run REPLACE_PROGNAME in the precreate mode. Both methods accomplish the
same thing.
.PP
To pre-create a service account, you may use the Active Directory Users and Computers GUI, select
"new user" from the right click menu, fill in all required data, set the password to a specific
value and use setspn.exe to set the desired servicePrincipalName(s). You may also select "must change
password at next logon".
.SH PASSWORD EXPIRY
.PP
Be aware that Windows machines will, by default, automatically change their account password every
30 days, and thus many domains have a 90-day password expiry window, after which your keytab will
stop working. There are two ways to deal with this:
.PP
a) (Preferred): Make sure you're running a daily cron job to run REPLACE_PROGNAME --auto-update, which
will change the password automatically 30 days after it was last changed and update the keytab.
.PP
b) (Not preferred): disable password expiry for the account via the --dont-expire-password option (or
otherwise setting DONT_EXPIRE_PASSWORD flag in userAccountControl in AD).
.SH PASSWORD POLICY ISSUES
.PP
This section only applies to REPLACE_PROGNAME --use-service-account.
.PP
While machine account passwords may be changed at any time, service accounts are user accounts and
your Active Directory domain may have special password policies for those user accounts. E.g.,
"minimum password age" is typically set to 1 day, which means that you will have to wait for that
time to pass until you may invoke REPLACE_PROGNAME --update --use-service-account.
.SH OTHER NOTES
.PP
Unlike other kerberos implementations, Active Directory has only a single key for all of the
principals associated with an account. So, if you create a HTTP/hostname service principal, it will
share the same key as the host/hostname principal. If you want to isolate (security-wise) different
service principals, you may want to create a dedicated service account for them (with --use-service-account)
and a separate keytab file (with --keytab).
.PP
Also note: kinit -k 'host/computername' *will not work*, by default, even when that is a valid
service principal existing in your keytab. Active Directory does not allow you to authenticate as a
service principal, so do not use that as a test of whether the service principal is working. If you
actually want to authenticate as the computer account user, kinit -k 'computername$' instead.
.PP
If you really need to be able to authenticate as 'host/computername', you can also use the --upn
argument to set the userPrincipalName attribute (generally requires administrator credentials, not
computer account credentials). Both 'computername$' and the value of userPrincipalName are treated
as valid account names to kinit as.
.PP
REPLACE_PROGNAME will use kerberized LDAP operations to talk to domain controllers. To obtain a LDAP service
ticket, the DNS service will be used to construct the domain controllers LDAP principal name. If DNS is
mis-configured, this construction may fail. To work around this issue, you may specify the fully
qualified DNS name of your domain controller with the --server option and additionally use the
--no-reverse-lookups option.
.PP
Samba (www.samba.org) provides the net command that can be used to manage kerberos keytabs as
well. Using REPLACE_PROGNAME and commands like "net ads join" or "net ads keytab" together can lead to
trouble. With the --set-samba-secret option, REPLACE_PROGNAME can be used as a replacement for net.
.PP
Active Directory includes authorization data (e.g. information about group memberships) in Kerberos tickets.
This information is called PAC and may lead to very large ticket sizes. Especially HTTP services are
known to produce failures if that size exceeds the HTTP header size. If your service does not make use
of that PAC information (which is true for most Unix/Linux-services) you may just disable it with
the --no-pac option.
.SH MODES
.TP
-v, --version
Displays version information
.TP
--help
Displays a help message
.TP
-c, --create
Creates a keytab for the current host or a given service account. Equivalent to --update --service host.
.TP
-f, --flush
Flushes out all principals for the current accountname from the keytab, and makes corresponding changes
to the machine or service account.
.B create
Creates a keytab for the current host or a given service account. Equivalent to update --service host.
.TP
-u, --update
.B update
Forces a password change and updates all related service principal entries from the
servicePrincipalName and userPrincipalName attributes. Updates dNSHostName for machine accounts and
always updates msDS-supportedEncryptionTypes attributes with current values, and applies other changes
as specified.
.TP
--auto-update
.B auto-update
Checks if the password is at least 30 days old (from pwdLastSet attribute), and that the account
does not have password expiry disabled. If those conditions are met, acts just like --update. Will
also update if the keytab failed to authenticate but the default password did work (e.g. after
resetting the account in AD). Otherwise, exits without doing anything (even if attribute modifying
does not have password expiry disabled. If those conditions are met, acts just like REPLACE_PROGNAME
update. Will also update if the keytab failed to authenticate but the default password did work (e.g.
after resetting the account in AD). Otherwise, exits without doing anything (even if attribute modifying
options are given). This option is intended for use from a daily crontab to ensure that the password
is rotated regularly.
.TP
--precreate
.B precreate
Pre-create (or update) an account for the given host with default password. Does not use or update
local keytab. Requires -h or --computer-name argument. Implies --user-creds-only. Generally
requires administrator credentials.
.SH CONNECTION/SETUP OPTIONS
.TP
.B flush
Flushes out principals for the current accountname from the keytab, and makes corresponding changes
to the machine or service account.
.TP
.B cleanup
Deletes entries from the keytab that are no longer needed.
.SH OPTIONS
.SS COMMON OPTIONS
.TP
-v, --version
Displays version information
.TP
--help
Displays a help message
.TP
--verbose
Enables verbose status messages. May be specified more then once to get LDAP debugging.
.SS CONNECTION/SETUP OPTIONS
.TP
-b, --base <base>
Specifies a relative LDAP base when creating a new account. For example, specifying '-b OU=Unix'
Expand Down Expand Up @@ -172,6 +128,7 @@ Specifies to use <file> for the keytab. This option can also be specified by se
MSKTUTIL_KEYTAB environment variable to the name of the desired keytab file. This keytab is both
read from, in order to authenticate as the given account, and written to, after updating the
account password. Default: /etc/krb5.keytab
.TP
--keytab-auth-as <name>
Specifies which principal name we should try to use, when we authenticate from a keytab. Normally,
REPLACE_PROGNAME will try to use the account name or the host principal for the current host. If
Expand Down Expand Up @@ -218,11 +175,8 @@ e.g. kinit). You may need to do this to modify certain attributes that require
credentials (description, userAccountControl, userPrincipalName, in a default AD setup).
.TP
--auto-update-interval <days>
Number of <days> when --auto-update will change the account password. Defaults to 30 days.
.TP
--verbose
Enables verbose status messages. May be specified more then once to get LDAP debugging.
.SH OBJECT TYPE/ATTRIBUTE-SETTING OPTIONS
Number of <days> when REPLACE_PROGNAME auto-update will change the account password. Defaults to 30 days.
.SS OBJECT TYPE/ATTRIBUTE-SETTING OPTIONS
.TP
--use-service-account
Create and maintain service accounts instead of machine accounts.
Expand Down Expand Up @@ -306,41 +260,100 @@ This operation requires administrator privileges.
--set-samba-secret
Use Samba's net changesecretpw command to locally set the machine account password in Samba's secrets.tdb.
$PATH need to include Samba's net command. Samba needs to be configured appropriately.
.SS CLEANUP OPTIONS
.TP
--remove-old <number>
Removes entries from the keytab that are older than <number> days.
.TP
--remove-enctype <int>
Removes entries from the keytab with given enctype. (See --enctypes for supported encryption types.)
.SH NOTES
.SS PASSWORD EXPIRY
.PP
Be aware that Windows machines will, by default, automatically change their account password every
30 days, and thus many domains have a 90-day password expiry window, after which your keytab will
stop working. There are two ways to deal with this:
.PP
a) (Preferred): Make sure you're running a daily cron job to run REPLACE_PROGNAME auto-update, which
will change the password automatically 30 days after it was last changed and update the keytab.
.PP
b) (Not preferred): disable password expiry for the account via the --dont-expire-password option (or
otherwise setting DONT_EXPIRE_PASSWORD flag in userAccountControl in AD).
.SS PASSWORD POLICY ISSUES
.PP
This section only applies to REPLACE_PROGNAME --use-service-account.
.PP
While machine account passwords may be changed at any time, service accounts are user accounts and
your Active Directory domain may have special password policies for those user accounts. E.g.,
"minimum password age" is typically set to 1 day, which means that you will have to wait for that
time to pass until you may invoke REPLACE_PROGNAME update --use-service-account.
.SS OTHER NOTES
.PP
Unlike other kerberos implementations, Active Directory has only a single key for all of the
principals associated with an account. So, if you create a HTTP/hostname service principal, it will
share the same key as the host/hostname principal. If you want to isolate (security-wise) different
service principals, you may want to create a dedicated service account for them (with --use-service-account)
and a separate keytab file (with --keytab).
.PP
Also note: kinit -k 'host/computername' *will not work*, by default, even when that is a valid
service principal existing in your keytab. Active Directory does not allow you to authenticate as a
service principal, so do not use that as a test of whether the service principal is working. If you
actually want to authenticate as the computer account user, kinit -k 'computername$' instead.
.PP
If you really need to be able to authenticate as 'host/computername', you can also use the --upn
argument to set the userPrincipalName attribute (generally requires administrator credentials, not
computer account credentials). Both 'computername$' and the value of userPrincipalName are treated
as valid account names to kinit as.
.PP
REPLACE_PROGNAME will use kerberized LDAP operations to talk to domain controllers. To obtain a LDAP service
ticket, the DNS service will be used to construct the domain controllers LDAP principal name. If DNS is
mis-configured, this construction may fail. To work around this issue, you may specify the fully
qualified DNS name of your domain controller with the --server option and additionally use the
--no-reverse-lookups option.
.PP
Samba (www.samba.org) provides the net command that can be used to manage kerberos keytabs as
well. Using REPLACE_PROGNAME and commands like "net ads join" or "net ads keytab" together can lead to
trouble. With the --set-samba-secret option, REPLACE_PROGNAME can be used as a replacement for net.
.PP
Active Directory includes authorization data (e.g. information about group memberships) in Kerberos tickets.
This information is called PAC and may lead to very large ticket sizes. Especially HTTP services are
known to produce failures if that size exceeds the HTTP header size. If your service does not make use
of that PAC information (which is true for most Unix/Linux-services) you may just disable it with
the --no-pac option.
.SH EXAMPLES
For unprivileged users the most common invocations are:
.PP
.nf
REPLACE_PROGNAME --update --service host --service HTTP
REPLACE_PROGNAME update --service host --service HTTP
.fi
.PP
This will update a computer account in Active Directory with a new password, write out a new keytab,
and ensure that it has both "host" and "HTTP" service principals are on it for the hostname.
.PP
.nf
REPLACE_PROGNAME --auto-update
REPLACE_PROGNAME auto-update
.fi
.PP
This is useful in a daily cron job to check and rotate the password automatically when it's 30 days
old.


.PP
.nf
For users with admin privileges in AD, some common uses:
.PP
.nf
REPLACE_PROGNAME --create --service host --service HTTP
REPLACE_PROGNAME create --service host --service HTTP
.fi
.PP
This will create a computer account in Active Directory with a new password, write out a new keytab,
and ensure that it has both "host" and "HTTP" service principals are on it for the hostname.
.PP
.nf
REPLACE_PROGNAME --precreate --host computer1.example.com
REPLACE_PROGNAME precreate --host computer1.example.com
.fi
.PP
This will pre-create an account for computer1 with the default password using your credentials. This
can be done on a central host, e.g. to script the addition of many hosts. You can then use
REPLACE_PROGNAME --create on the hosts themselves (without special credentials) to join them to the
REPLACE_PROGNAME create on the hosts themselves (without special credentials) to join them to the
domain.
.PP
.nf
Expand All @@ -351,15 +364,15 @@ This will create an afs/cell.name@REALM principal, and associate that principal
account called 'afs'. The principal will be marked as DES-only, which is required for AFS.
.PP
.nf
REPLACE_PROGNAME --create --use-service-account --service HTTP/hostname.example.com --keytab /etc/apache/krb5.keytab --account-name srv-http --no-pac
REPLACE_PROGNAME create --use-service-account --service HTTP/hostname.example.com --keytab /etc/apache/krb5.keytab --account-name srv-http --no-pac
.fi
.PP
This will create an HTTP/hostname.example.com@REALM principal, and associate that principal with a service
account called 'srv-http'. Corresponding Kerberos keys will be written to the keytab file /etc/apache/krb5.keytab.
The size of Kerberos tickets for that service will stay small because no PAC information will be included.
.PP
.nf
REPLACE_PROGNAME --create --service host/hostname --service host/hostname.example.com --set-samba-secret --enctypes 0x4
REPLACE_PROGNAME create --service host/hostname --service host/hostname.example.com --set-samba-secret --enctypes 0x4
.fi
.PP
This will create a computer account in Active Directory that is compatible with Samba. The command creates
Expand All @@ -368,7 +381,29 @@ as service principals (which is equivalent to what setspn.exe -R would do on win
password will be stored in Samba's secrets.tdb database to provide interoperability with Samba.
As Samba (version 3) only supports arcfour-encrypted Kerberos tickets the --enctypes option must be used
to select only that encryption type.
.SH AUTHOR
.PP
.nf
REPLACE_PROGNAME cleanup --remove-old 10
.fi
.PP
Deletes all entries older than 10 days, keeping at least the last entry.
.SH ENVIRONMENT
.TP
MSKTUTIL_LDAP_BASE
Specifies a relative LDAP base when creating a new account (see --base),
.TP
MSKTUTIL_KEYTAB
Specifies the keytab. Default: /etc/krb5.keytab (see --keytab),
.TP
MSKTUTIL_SERVER
Specifies the domain controller (see --server).
.TP
MSKTUTIL_DELEGATION
Enables the account to be trusted for delegation (see --delegation).
.TP
MSKTUTIL_NO_PAC
Specifies that service tickets for this account should not contain a PAC (see --no-pac).
.SH AUTHORS
(C) 2004-2006 Dan Perry <dperry at pppl.gov>
.PP
(C) 2006 Brian Elliott Finley (finley at anl.gov)
Expand All @@ -379,6 +414,6 @@ to select only that encryption type.
.PP
(C) 2010-2013 Ken Dreyer <ktdreyer at ktdreyer.com>
.PP
(C) 2012-2014 Mark Proehl <mark at mproehl.net>
(C) 2012-2015 Mark Proehl <mark at mproehl.net>
.PP
(C) 2012-2015 Olaf Flebbe <of at oflebbe.de>
Loading

0 comments on commit 3e06056

Please sign in to comment.