Ticket #50421: patch-rename-server-keytab-backend.diff

File patch-rename-server-keytab-backend.diff, 17.1 KB (added by akkornel (A. Karl Kornel), 8 years ago)

Submit with the substitution being used upstream

  • deleted file server/keytab-backend

    + -  
    1 #!/usr/bin/perl
    2 #
    3 # Extract keytabs from the KDC without changing the key.
    4 #
    5 # This is a remctl backend that extracts existing keys from a KDC database
    6 # using kadmin.local.  It requires a patched version of kadmin.local that
    7 # supports the -norandkey option.  It expects a configuration file in
    8 # /etc/krb5kdc/allow-extract that contains a list of regexes, one per line,
    9 # matching principals that may be extracted in this fashion.  (Generally you
    10 # do not want to list user principals here.)  It also expects to be able to
    11 # write to a directory named /var/lib/keytabs; that's where it puts the
    12 # keytabs temporarily before sending them back to via remctl.
    13 #
    14 # remctl should handle authorization restrictions on this script.  It doesn't
    15 # do any additional authorization checks itself.
    16 #
    17 # The keytab for the extracted principal will be printed to standard output.
    18 
    19 use 5.008;
    20 use strict;
    21 use warnings;
    22 
    23 use Sys::Syslog qw(openlog syslog);
    24 
    25 # Path to configuration file listing principals that may be extracted.
    26 our $CONFIG = '/etc/krb5kdc/allow-extract';
    27 
    28 # The full path to a kadmin.local that supports -norandkey.
    29 our $KADMIN = '/usr/sbin/kadmin.local';
    30 
    31 # A temporary area into which keytabs should be written.
    32 our $TMP = '/var/lib/keytabs';
    33 
    34 # Set to zero to suppress syslog logging, which is used only for testing.  Set
    35 # to a reference to a string to append messages to that string instead.
    36 our $SYSLOG;
    37 $SYSLOG = 1 unless defined $SYSLOG;
    38 
    39 ##############################################################################
    40 # Logging
    41 ##############################################################################
    42 
    43 # Initialize logging.
    44 sub log_init {
    45     if (ref $SYSLOG) {
    46         $$SYSLOG = '';
    47     } elsif ($SYSLOG) {
    48         openlog ('keytab-backend', 'pid', 'auth');
    49     }
    50 }
    51 
    52 # Log a failure message to both syslog and to stderr and exit with a non-zero
    53 # status.
    54 sub error {
    55     my $message = join ('', @_);
    56     if (ref $SYSLOG) {
    57         $$SYSLOG .= $message . "\n";
    58     } elsif ($SYSLOG) {
    59         syslog ('err', '%s', $message);
    60     }
    61     die "keytab-backend: $message\n";
    62 }
    63 
    64 # Log a regular message, generally for success.
    65 sub info {
    66     my $message = join ('', @_);
    67     if (ref $SYSLOG) {
    68         $$SYSLOG .= $message . "\n";
    69     } elsif ($SYSLOG) {
    70         syslog ('info', '%s', $message);
    71     }
    72 }
    73 
    74 ##############################################################################
    75 # Implementation
    76 ##############################################################################
    77 
    78 # Check and download the keytab.  This is in a subroutine call for easier
    79 # testing.  We separately log actions unless $SYSLOG is set to 0.  remctld
    80 # keeps some logs, but it won't tell us whether the download is successful or
    81 # not.
    82 sub download {
    83     my (@args) = @_;
    84     log_init;
    85 
    86     # Set up a default identity if run from the command line.
    87     $ENV{REMOTE_USER} = getpwnam ($<) || 'UNKNOWN' unless $ENV{REMOTE_USER};
    88 
    89     # Read the regexes of valid principals into memory.
    90     open (CONFIG, '<', $CONFIG) or error "cannot open $CONFIG: $!";
    91     my @valid;
    92     while (<CONFIG>) {
    93         next if /^\s*\#/;
    94         next if /^\s*$/;
    95         s/^\s+//;
    96         s/\s+$//;
    97         s/\s*\#.*//;
    98         push (@valid, qr/$_/);
    99     }
    100     close CONFIG;
    101 
    102     # The first argument will be the remctl service, so skip it.
    103     if (@args == 2) {
    104         shift @args;
    105     }
    106     if (@args != 1) {
    107         error "invalid arguments: @args";
    108     }
    109     my $principal = $args[0];
    110 
    111     # Ensure that we're allowed to retrieve this principal.
    112     unless ($principal =~ m%^[\w-]+(?:/[\w.-]+)?\@[\w.-]+\z%) {
    113         error "bad principal name $principal";
    114     }
    115     my $okay;
    116     for my $regex (@valid) {
    117         if ($principal =~ /$regex/) {
    118             $okay = 1;
    119             last;
    120         }
    121     }
    122     unless ($okay) {
    123         error "permission denied: $ENV{REMOTE_USER} may not retrieve"
    124             . " $principal";
    125     }
    126 
    127     # Do the actual work.
    128     my $filename = "$TMP/keytab$$";
    129     my $command = "ktadd -k $filename -q -norandkey $principal";
    130     my $output = `$KADMIN -q '$command' 2>&1`;
    131     if ($? != 0) {
    132         my $status = ($? >> 8);
    133         warn $output;
    134         error "retrieve of $principal failed for $ENV{REMOTE_USER}:"
    135             . " kadmin.local exited with status $status";
    136     }
    137     open (KEYTAB, '<', $filename)
    138         or error "cannot open temporary keytab $filename: $!";
    139     print while <KEYTAB>;
    140     close KEYTAB;
    141     unlink $filename;
    142     info ("keytab $principal retrieved by $ENV{REMOTE_USER}");
    143 }
    144 download (@ARGV);
    145 __END__
    146 
    147 ##############################################################################
    148 # Documentation
    149 ##############################################################################
    150 
    151 =for stopwords
    152 keytab-backend keytabs KDC keytab kadmin.local -norandkey ktadd remctld
    153 auth Allbery rekeying MERCHANTABILITY NONINFRINGEMENT sublicense
    154 kadmin.local.
    155 
    156 =head1 NAME
    157 
    158 keytab-backend - Extract keytabs from the KDC without changing the key
    159 
    160 =head1 SYNOPSIS
    161 
    162 B<keytab-backend> retrieve I<principal>
    163 
    164 =head1 DESCRIPTION
    165 
    166 B<keytab-backend> retrieves a keytab for an existing principal from the
    167 KDC database without changing the current key.  It allows generation of a
    168 keytab for a service without rekeying that service.  It requires a
    169 B<kadmin.local> patched to support the B<-norandkey> option to B<ktadd>.
    170 
    171 This script is intended to run under B<remctld>.  On success, it prints
    172 the keytab to standard output, logs a success message to syslog (facility
    173 auth, priority info), and exits with status 0.  On failure, it prints out
    174 an error message, logs an error to syslog (facility auth, priority err),
    175 and exits with a non-zero status.
    176 
    177 The principal is checked for basic sanity (only accepting alphanumerics,
    178 C<_>, and C<-> with an optional instance and then only alphanumerics,
    179 C<_>, C<->, and C<.> in the realm) and then checked against a
    180 configuration file that lists regexes of principals that can be retrieved.
    181 When deploying this software, limit as tightly as possible which
    182 principals can be downloaded in this fashion.  Generally only shared
    183 service principals used on multiple systems should be made available in
    184 this way.
    185 
    186 B<keytab-backend> does not do any authorization checks.  Those should be
    187 done by B<remctld> before it is called.
    188 
    189 =head1 FILES
    190 
    191 =over 4
    192 
    193 =item F</etc/krb5kdc/allow-extract>
    194 
    195 The configuration file that controls which principals can have their
    196 keytabs retrieved.  Blank lines and lines starting with C<#>, as well as
    197 anything after C<#> on a line, are ignored.  All other lines should be
    198 Perl regular expressions, one per line, that match principals whose
    199 keytabs can be retrieved by B<keytab-backend>.  Any principal that does
    200 not match one of those regular expressions cannot be retrieved.
    201 
    202 =item F</var/lib/keytabs>
    203 
    204 The temporary directory used for creating keytabs.  B<keytab-backend> will
    205 create the keytab in this directory, make sure that was successful, and
    206 then delete the temporary file after the results have been sent to
    207 standard output.
    208 
    209 =back
    210 
    211 =head1 AUTHOR
    212 
    213 Russ Allbery <eagle@eyrie.org>
    214 
    215 =head1 COPYRIGHT AND LICENSE
    216 
    217 Copyright 2006, 2007, 2008, 2010, 2013 The Board of Trustees of the Leland
    218 Stanford Junior University
    219 
    220 Permission is hereby granted, free of charge, to any person obtaining a
    221 copy of this software and associated documentation files (the "Software"),
    222 to deal in the Software without restriction, including without limitation
    223 the rights to use, copy, modify, merge, publish, distribute, sublicense,
    224 and/or sell copies of the Software, and to permit persons to whom the
    225 Software is furnished to do so, subject to the following conditions:
    226 
    227 The above copyright notice and this permission notice shall be included in
    228 all copies or substantial portions of the Software.
    229 
    230 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
    231 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
    232 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
    233 THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
    234 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
    235 FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
    236 DEALINGS IN THE SOFTWARE.
    237 
    238 =head1 SEE ALSO
    239 
    240 kadmin.local(8), remctld(8)
    241 
    242 This program is part of the wallet system.  The current version is
    243 available from L<http://www.eyrie.org/~eagle/software/wallet/>.
    244 
    245 =cut
  • new file server/keytab-backend.in

    - +  
     1#!@PERL@
     2#
     3# Extract keytabs from the KDC without changing the key.
     4#
     5# This is a remctl backend that extracts existing keys from a KDC database
     6# using kadmin.local.  It requires a patched version of kadmin.local that
     7# supports the -norandkey option.  It expects a configuration file in
     8# /etc/krb5kdc/allow-extract that contains a list of regexes, one per line,
     9# matching principals that may be extracted in this fashion.  (Generally you
     10# do not want to list user principals here.)  It also expects to be able to
     11# write to a directory named /var/lib/keytabs; that's where it puts the
     12# keytabs temporarily before sending them back to via remctl.
     13#
     14# remctl should handle authorization restrictions on this script.  It doesn't
     15# do any additional authorization checks itself.
     16#
     17# The keytab for the extracted principal will be printed to standard output.
     18
     19use 5.008;
     20use strict;
     21use warnings;
     22
     23use Sys::Syslog qw(openlog syslog);
     24
     25# Path to configuration file listing principals that may be extracted.
     26our $CONFIG = '/etc/krb5kdc/allow-extract';
     27
     28# The full path to a kadmin.local that supports -norandkey.
     29our $KADMIN = '/usr/sbin/kadmin.local';
     30
     31# A temporary area into which keytabs should be written.
     32our $TMP = '/var/lib/keytabs';
     33
     34# Set to zero to suppress syslog logging, which is used only for testing.  Set
     35# to a reference to a string to append messages to that string instead.
     36our $SYSLOG;
     37$SYSLOG = 1 unless defined $SYSLOG;
     38
     39##############################################################################
     40# Logging
     41##############################################################################
     42
     43# Initialize logging.
     44sub log_init {
     45    if (ref $SYSLOG) {
     46        $$SYSLOG = '';
     47    } elsif ($SYSLOG) {
     48        openlog ('keytab-backend', 'pid', 'auth');
     49    }
     50}
     51
     52# Log a failure message to both syslog and to stderr and exit with a non-zero
     53# status.
     54sub error {
     55    my $message = join ('', @_);
     56    if (ref $SYSLOG) {
     57        $$SYSLOG .= $message . "\n";
     58    } elsif ($SYSLOG) {
     59        syslog ('err', '%s', $message);
     60    }
     61    die "keytab-backend: $message\n";
     62}
     63
     64# Log a regular message, generally for success.
     65sub info {
     66    my $message = join ('', @_);
     67    if (ref $SYSLOG) {
     68        $$SYSLOG .= $message . "\n";
     69    } elsif ($SYSLOG) {
     70        syslog ('info', '%s', $message);
     71    }
     72}
     73
     74##############################################################################
     75# Implementation
     76##############################################################################
     77
     78# Check and download the keytab.  This is in a subroutine call for easier
     79# testing.  We separately log actions unless $SYSLOG is set to 0.  remctld
     80# keeps some logs, but it won't tell us whether the download is successful or
     81# not.
     82sub download {
     83    my (@args) = @_;
     84    log_init;
     85
     86    # Set up a default identity if run from the command line.
     87    $ENV{REMOTE_USER} = getpwnam ($<) || 'UNKNOWN' unless $ENV{REMOTE_USER};
     88
     89    # Read the regexes of valid principals into memory.
     90    open (CONFIG, '<', $CONFIG) or error "cannot open $CONFIG: $!";
     91    my @valid;
     92    while (<CONFIG>) {
     93        next if /^\s*\#/;
     94        next if /^\s*$/;
     95        s/^\s+//;
     96        s/\s+$//;
     97        s/\s*\#.*//;
     98        push (@valid, qr/$_/);
     99    }
     100    close CONFIG;
     101
     102    # The first argument will be the remctl service, so skip it.
     103    if (@args == 2) {
     104        shift @args;
     105    }
     106    if (@args != 1) {
     107        error "invalid arguments: @args";
     108    }
     109    my $principal = $args[0];
     110
     111    # Ensure that we're allowed to retrieve this principal.
     112    unless ($principal =~ m%^[\w-]+(?:/[\w.-]+)?\@[\w.-]+\z%) {
     113        error "bad principal name $principal";
     114    }
     115    my $okay;
     116    for my $regex (@valid) {
     117        if ($principal =~ /$regex/) {
     118            $okay = 1;
     119            last;
     120        }
     121    }
     122    unless ($okay) {
     123        error "permission denied: $ENV{REMOTE_USER} may not retrieve"
     124            . " $principal";
     125    }
     126
     127    # Do the actual work.
     128    my $filename = "$TMP/keytab$$";
     129    my $command = "ktadd -k $filename -q -norandkey $principal";
     130    my $output = `$KADMIN -q '$command' 2>&1`;
     131    if ($? != 0) {
     132        my $status = ($? >> 8);
     133        warn $output;
     134        error "retrieve of $principal failed for $ENV{REMOTE_USER}:"
     135            . " kadmin.local exited with status $status";
     136    }
     137    open (KEYTAB, '<', $filename)
     138        or error "cannot open temporary keytab $filename: $!";
     139    print while <KEYTAB>;
     140    close KEYTAB;
     141    unlink $filename;
     142    info ("keytab $principal retrieved by $ENV{REMOTE_USER}");
     143}
     144download (@ARGV);
     145__END__
     146
     147##############################################################################
     148# Documentation
     149##############################################################################
     150
     151=for stopwords
     152keytab-backend keytabs KDC keytab kadmin.local -norandkey ktadd remctld
     153auth Allbery rekeying MERCHANTABILITY NONINFRINGEMENT sublicense
     154kadmin.local.
     155
     156=head1 NAME
     157
     158keytab-backend - Extract keytabs from the KDC without changing the key
     159
     160=head1 SYNOPSIS
     161
     162B<keytab-backend> retrieve I<principal>
     163
     164=head1 DESCRIPTION
     165
     166B<keytab-backend> retrieves a keytab for an existing principal from the
     167KDC database without changing the current key.  It allows generation of a
     168keytab for a service without rekeying that service.  It requires a
     169B<kadmin.local> patched to support the B<-norandkey> option to B<ktadd>.
     170
     171This script is intended to run under B<remctld>.  On success, it prints
     172the keytab to standard output, logs a success message to syslog (facility
     173auth, priority info), and exits with status 0.  On failure, it prints out
     174an error message, logs an error to syslog (facility auth, priority err),
     175and exits with a non-zero status.
     176
     177The principal is checked for basic sanity (only accepting alphanumerics,
     178C<_>, and C<-> with an optional instance and then only alphanumerics,
     179C<_>, C<->, and C<.> in the realm) and then checked against a
     180configuration file that lists regexes of principals that can be retrieved.
     181When deploying this software, limit as tightly as possible which
     182principals can be downloaded in this fashion.  Generally only shared
     183service principals used on multiple systems should be made available in
     184this way.
     185
     186B<keytab-backend> does not do any authorization checks.  Those should be
     187done by B<remctld> before it is called.
     188
     189=head1 FILES
     190
     191=over 4
     192
     193=item F</etc/krb5kdc/allow-extract>
     194
     195The configuration file that controls which principals can have their
     196keytabs retrieved.  Blank lines and lines starting with C<#>, as well as
     197anything after C<#> on a line, are ignored.  All other lines should be
     198Perl regular expressions, one per line, that match principals whose
     199keytabs can be retrieved by B<keytab-backend>.  Any principal that does
     200not match one of those regular expressions cannot be retrieved.
     201
     202=item F</var/lib/keytabs>
     203
     204The temporary directory used for creating keytabs.  B<keytab-backend> will
     205create the keytab in this directory, make sure that was successful, and
     206then delete the temporary file after the results have been sent to
     207standard output.
     208
     209=back
     210
     211=head1 AUTHOR
     212
     213Russ Allbery <eagle@eyrie.org>
     214
     215=head1 COPYRIGHT AND LICENSE
     216
     217Copyright 2006, 2007, 2008, 2010, 2013 The Board of Trustees of the Leland
     218Stanford Junior University
     219
     220Permission is hereby granted, free of charge, to any person obtaining a
     221copy of this software and associated documentation files (the "Software"),
     222to deal in the Software without restriction, including without limitation
     223the rights to use, copy, modify, merge, publish, distribute, sublicense,
     224and/or sell copies of the Software, and to permit persons to whom the
     225Software is furnished to do so, subject to the following conditions:
     226
     227The above copyright notice and this permission notice shall be included in
     228all copies or substantial portions of the Software.
     229
     230THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     231IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     232FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
     233THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     234LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
     235FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
     236DEALINGS IN THE SOFTWARE.
     237
     238=head1 SEE ALSO
     239
     240kadmin.local(8), remctld(8)
     241
     242This program is part of the wallet system.  The current version is
     243available from L<http://www.eyrie.org/~eagle/software/wallet/>.
     244
     245=cut