--- /dev/null
+Revision history for Perl extension Heimdal::Kadm5.
+
+0.01 Sun Feb 9 22:01:22 2003
+ - original version; created by h2xs 1.21 with options
+ -n Heimdal::Kadm5
+
--- /dev/null
+package Heimdal::Kadm5;
+
+use strict;
+use Carp;
+use vars qw($VERSION @ISA @EXPORT @EXPORT_OK $AUTOLOAD);
+
+require Exporter;
+require DynaLoader;
+require AutoLoader;
+
+@ISA = qw(Exporter DynaLoader);
+# Items to export into callers namespace by default. Note: do not export
+# names by default without a very good reason. Use EXPORT_OK instead.
+# Do not simply export all your public functions/methods/constants.
+@EXPORT_OK = qw(
+ KADM5_ADMIN_SERVICE
+ KADM5_API_VERSION_1
+ KADM5_API_VERSION_2
+ KADM5_ATTRIBUTES
+ KADM5_AUX_ATTRIBUTES
+ KADM5_CHANGEPW_SERVICE
+ KADM5_CONFIG_ACL_FILE
+ KADM5_CONFIG_ADBNAME
+ KADM5_CONFIG_ADB_LOCKFILE
+ KADM5_CONFIG_ADMIN_KEYTAB
+ KADM5_CONFIG_ADMIN_SERVER
+ KADM5_CONFIG_DBNAME
+ KADM5_CONFIG_DICT_FILE
+ KADM5_CONFIG_ENCTYPE
+ KADM5_CONFIG_ENCTYPES
+ KADM5_CONFIG_EXPIRATION
+ KADM5_CONFIG_FLAGS
+ KADM5_CONFIG_KADMIND_PORT
+ KADM5_CONFIG_MAX_LIFE
+ KADM5_CONFIG_MAX_RLIFE
+ KADM5_CONFIG_MKEY_FROM_KEYBOARD
+ KADM5_CONFIG_MKEY_NAME
+ KADM5_CONFIG_PROFILE
+ KADM5_CONFIG_REALM
+ KADM5_CONFIG_STASH_FILE
+ KADM5_FAIL_AUTH_COUNT
+ KADM5_HIST_PRINCIPAL
+ KADM5_KEY_DATA
+ KADM5_KVNO
+ KADM5_LAST_FAILED
+ KADM5_LAST_PWD_CHANGE
+ KADM5_LAST_SUCCESS
+ KADM5_MAX_LIFE
+ KADM5_MAX_RLIFE
+ KADM5_MKVNO
+ KADM5_MOD_NAME
+ KADM5_MOD_TIME
+ KADM5_POLICY
+ KADM5_POLICY_CLR
+ KADM5_POLICY_NORMAL_MASK
+ KADM5_PRINCIPAL
+ KADM5_PRINCIPAL_NORMAL_MASK
+ KADM5_PRINC_EXPIRE_TIME
+ KADM5_PRIV_ADD
+ KADM5_PRIV_ALL
+ KADM5_PRIV_CPW
+ KADM5_PRIV_DELETE
+ KADM5_PRIV_GET
+ KADM5_PRIV_LIST
+ KADM5_PRIV_MODIFY
+ KADM5_PW_EXPIRATION
+ KADM5_PW_HISTORY_NUM
+ KADM5_PW_MAX_LIFE
+ KADM5_PW_MIN_CLASSES
+ KADM5_PW_MIN_LENGTH
+ KADM5_PW_MIN_LIFE
+ KADM5_REF_COUNT
+ KADM5_STRUCT_VERSION
+ KADM5_TL_DATA
+ KRB5_KDB_DISALLOW_ALL_TIX
+ KRB5_KDB_DISALLOW_DUP_SKEY
+ KRB5_KDB_DISALLOW_FORWARDABLE
+ KRB5_KDB_DISALLOW_POSTDATED
+ KRB5_KDB_DISALLOW_PROXIABLE
+ KRB5_KDB_DISALLOW_RENEWABLE
+ KRB5_KDB_DISALLOW_SVR
+ KRB5_KDB_DISALLOW_TGT_BASED
+ KRB5_KDB_NEW_PRINC
+ KRB5_KDB_PWCHANGE_SERVICE
+ KRB5_KDB_REQUIRES_HW_AUTH
+ KRB5_KDB_REQUIRES_PRE_AUTH
+ KRB5_KDB_REQUIRES_PWCHANGE
+ KRB5_KDB_SUPPORT_DESMD5
+ USE_KADM5_API_VERSION
+ );
+
+$VERSION = '0.01';
+
+sub AUTOLOAD {
+ # This AUTOLOAD is used to 'autoload' constants from the constant()
+ # XS function. If a constant is not found then control is passed
+ # to the AUTOLOAD in AutoLoader.
+
+ my $constname;
+ ($constname = $AUTOLOAD) =~ s/.*:://;
+ croak "& not defined" if $constname eq 'constant';
+ my $val = constant($constname, @_ ? $_[0] : 0);
+ if ($! != 0) {
+ if ($! =~ /Invalid/) {
+ $AutoLoader::AUTOLOAD = $AUTOLOAD;
+ goto &AutoLoader::AUTOLOAD;
+ }
+ else {
+ croak "Your vendor has not defined Heimdal::Kadm5 macro $constname";
+ }
+ }
+ eval "sub $AUTOLOAD { $val } }";
+ goto &$AUTOLOAD;
+}
+
+bootstrap Heimdal::Kadm5 $VERSION;
+
+package Heimdal::Kadm5;
+
+# Preloaded methods go here.
+
+package Heimdal::Kadm5::Client;
+@Heimdal::Kadm5::Client::ISA = qw(Heimdal::Kadm5);
+use vars qw($KADMIN_SERVICE);
+
+$KADMIN_SERVICE = 'kadmin/admin';
+
+sub new
+ {
+ my $self = shift;
+ my $class = ref $self || $self;
+
+ my %opts = @_;
+ my $me = bless \%opts,$class;
+
+ my $client = $me->{'Principal'} or
+ die "[Heimdal::Kadm5] Heimdal::Kadm5::Client::new missing required \'Principal\' parameter";
+ my $keytab = $me->{'Keytab'};
+ my $password = $me->{'Password'};
+ warn %opts;
+ eval
+ {
+ $me->{'_handle'} = Heimdal::Kadm5::SHandle->new(\%opts);
+ if ($keytab)
+ {
+ $me->handle->c_init_with_skey($client,$keytab,$KADMIN_SERVICE,0,0);
+ }
+ else
+ {
+ $me->handle->c_init_with_password($client,$password,$KADMIN_SERVICE,0,0);
+ }
+ $me->{'_privs'} = $me->handle->c_get_privs();
+ };
+
+ if ($@)
+ {
+ my $err = $@;
+ if ($me->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to initialize a Heimdal::Kadm5::Client instance\n";
+ return undef;
+ }
+ $me;
+ }
+
+sub privis { $_[0]->{'_privs'}; }
+
+my %pnames = (
+ KADM5_PRIV_ADD => 'add',
+ KADM5_PRIV_CPW => 'cpw',
+ KADM5_PRIV_DELETE => 'delete',
+ KADM5_PRIV_LIST => 'list',
+ KADM5_PRIV_GET => 'get',
+ KADM5_PRIV_MODIFY => 'modify'
+ );
+
+sub getPriviledges
+ {
+ my $mask = $_[0]->privs;
+ my @p;
+
+ foreach my $bit (keys %pnames)
+ {
+ push(@p,$pnames{$bit}) if ($mask & $bit);
+ }
+ return (wantarray ? @p : join(',',@p));
+ }
+
+sub handle { $_[0]->{'_handle'}; }
+
+sub makePrincipal
+ {
+ my $principal = Heimdal::Kadm5::Principal->new($_[0]);
+ $principal->setPrincipal($_[1]);
+ $principal;
+ }
+
+sub getPrincipals
+ {
+ my $self = shift;
+ $self->handle->c_get_principals(@_);
+ }
+
+sub getPrincipal
+ {
+ my $self = shift;
+ my $princ = shift;
+ my $mask = shift;
+
+ $mask = (KADM5_PRINCIPAL_NORMAL_MASK()|KADM5_KEY_DATA()) unless $mask;
+ $self->handle->c_get_principal($princ,$mask);
+ }
+
+sub disablePrincipal
+ {
+ my $self = shift;
+ my $name = shift;
+
+ die "[Heimdal::Kadm5] Disable whom" unless $name;
+
+ eval
+ {
+ my $principal = $self->getPrincipal($name);
+ my $attrs = $principal->getAttributes;
+ $attrs |= Heimdal::Kadm5::KRB5_KDB_DISALLOW_ALL_TIX();
+ $principal->setAttributes($attrs);
+
+ $self->modifyPrincipal($principal);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to disable $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub enablePrincipal
+ {
+ my $self = shift;
+ my $name = shift;
+
+ die "[Heimdal::Kadm5] Enable whom" unless $name;
+
+ eval
+ {
+ my $principal = $self->getPrincipal($name);
+ my $attrs = $principal->getAttributes;
+ $attrs &= (~KRB5_KDB_DISALLOW_ALL_TIX());
+ $principal->setAttributes($attrs);
+
+ $self->modifyPrincipal($principal);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to enable $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub modifyPrincipal
+ {
+ my ($self,$principal,$mask) = @_;
+
+ eval
+ {
+ $self->handle->c_modify_principal($principal,$mask);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ my $name = $principal->getPrincipal;
+ warn $err;
+ warn "Unable to modify $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub changePassword
+ {
+ my ($self,$name,$password) = @_;
+
+ eval
+ {
+ $self->handle->c_chpass_principal($name,$password);
+ undef $password;
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to change password for $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub createPrincipal
+ {
+ my $self = shift;
+ my $principal = shift;
+ my $password = shift;
+ my $mask = shift;
+
+ my $name = $principal->getPrincipal;
+ die "[Heimdal::Kadm5] Create whom?" unless $name;
+
+ eval
+ {
+ $self->handle->c_create_principal($principal,$password,$mask);
+ undef $password;
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to create $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub renamePrincipal
+ {
+ my ($self,$source,$target) = @_;
+
+ eval
+ {
+ $self->handle->c_rename_principal($source,$target);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to rename $source to $target\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub deletePrincipal
+ {
+ my ($self,$name) = @_;
+
+ eval
+ {
+ $self->handle->c_delete_principal($name);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to delete $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub randKeyPricipal
+ {
+ my ($self,$name) = @_;
+
+ eval
+ {
+ $self->handle->c_randkey_principal($name);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $@;
+ }
+ warn $err;
+ warn "Unable to generate random key for $name\n";
+ return undef;
+ }
+ 1;
+ }
+
+sub extractKeytab
+ {
+ my $self = shift;
+ my $principal = shift;
+ my $keytab = shift;
+
+ my $nkeys;
+ eval
+ {
+ $self->handle->c_ext_keytab($principal,$keytab);
+ };
+ if ($@)
+ {
+ my $err = $@;
+ if ($self->{RaiseError})
+ {
+ die $err;
+ }
+ warn $err;
+ warn "Unable to extract keytab $keytab\n";
+ return undef
+ }
+ 1;
+ }
+
+package Heimdal::Kadm5::Principal;
+@Heimdal::Kadm5::Principal::ISA = qw(Heimdal::Kadm5::SPrincipal);
+
+use POSIX qw(strftime);
+
+sub _sec2date { $_[0] ? strftime "%Y-%m-%d", localtime($_[0]): 'never'; }
+
+sub dump
+ {
+ my $sp = shift;
+ my $io = (shift or \*STDOUT);
+
+ printf $io "%24s: %s\n", 'Principal',$sp->getPrincipal;
+ printf $io "%24s: %s\n", 'Principal Expires',_sec2date($sp->getPrincExpireTime);
+ printf $io "%24s: %s\n", 'Password Expires',_sec2date($sp->getPwExpiration);
+ printf $io "%24s: %s\n", 'Last Password Change',_sec2date($sp->getLastPwdChange);
+ printf $io "%24s: %d seconds\n", 'Max Ticket Life',$sp->getMaxLife;
+ printf $io "%24s: %d seconds\n", 'Max Renewable Life',$sp->getMaxRenewableLife;
+ my @keys;
+ foreach my $kt (@{$sp->getKeytypes})
+ {
+ push(@keys,"$kt->[0] ($kt->[1])");
+ }
+ printf $io "%24s: %s\n\n", 'Keytypes(salts)', join(',',@keys);
+ }
+
+# Autoload methods go after =cut, and are processed by the autosplit program.
+
+package Heimdal::Kadm5;
+
+1;
+__END__
+# Below is the stub of documentation for your module. You better edit it!
+
+=head1 NAME
+
+Heimdal::Kadm5 - Perl extension for adminstration of Heimdal Kerberos servers (kadmin)
+
+=head1 SYNOPSIS
+
+use Heimdal::Kadm5;
+
+$client = Heimdal::Kadm5::Client->new('Client'=>'you/admin@YOUR.REALM',
+ 'Password'=>'eatmyshorts');
+foreach my $name ($client->getPrincipals('*/admin'))
+ {
+ my $principal = $client->getPrincipal($name);
+ $principal->dump;
+ }
+
+=head1 DESCRIPTION
+
+Heimdal::Kadm5 is a basic XSUB perl glue to the Heimdal (http://www.pdc.kth.se/src/heimdal) kadm5clnt
+library. Heimdal is a free, slightly less export challenged implementation of Kerberos5 by Assar
+Westerlund and Johan Danielsson. Heimdal::Kadm5 allows you to perform more administration of your kdc
+than you can usually pull off with the included kadmin program. Heimdal::Kadm5 should be considered
+alpha-code and may consequently crash and burn but should not muck up your kdc any more than kadmin
+itself does.
+
+=head1 OBJECTS
+
+C<Heimdal::Kadm5::Client> represents a client connection (the truly perverse may conspire to write a kadmin
+servlet in perl and put that in C<Heimdal::Kadm5::Server>) to a kadmin server. The main object handled by
+a kadmin server is a C<kadm5_principal_ent_t> (F<kadm5/admin.h>). This type corresponds to the perl class
+C<Heimdal::Kadm5::Principal>. This object is returned by the C<getPrincipal> method of C<Heimdal::Kadm5::Client>
+and can be created (when adding principals to the kdc) using the C<makePrincipal> method of C<Heimdal::Kadm5::Client>.
+Note: B<Do not create Principals directly through C<Heimdal::Kadm5::Principal>>.
+Principals in the traditional sense of the word (i.e things of type C<krb5_principal>) are passed around
+as strings ('name/instance@REALM' or 'name@REALM');
+
+=head1 METHODS
+
+In what follows $principal denotes an instance of Heimdal::Kadm5::Principal, $name denotes a principal
+name, $bitmask denotes an (you guessed it!) integer representing a bitmask, $seconds an integer
+representing seconds since the epoch (time_t value), $client a Heimdal::Kadm5::Client instance. Other
+variables should be even more obvious or are explained in the text.
+
+
+=head2 Heimdal::Kadm5::Client
+
+Minimal use:
+
+my $client =
+ Heimdal::Kadm5::Client->new(Client=>'you');
+
+This would connect using a password for 'you@DEFREALM'. The password is
+prompted on the active tty.
+
+A more complex example:
+
+my $client =
+ Heimdal::Kadm5::Client->new(
+ RaiseErrors => 1,
+ Server => 'adm.somewhere.net',
+ Port => '8899',
+ # Required:
+ Client => 'you/admin',
+ Realm => 'OTHER.REALM',
+ # --- Either ---
+ Password => 'very secret',
+ # --- Or ---
+ Keytab => '$HOME/mysecrec.keytab'
+ );
+
+Be very careful when using the Password parameter: it implies storing the password in the
+script or reading it from commmand line arguments or through some other means. Only use
+this on secured hosts, never from NFS mounted filesystems, and B<never> using principals
+allowed to perform all operations on the kdc. In this case using a keytable (see
+L<ktutil(8)> for information on how to create keytabs) is a better way to go.
+
+Normally both the Server, Port and Realm parameters are determined from the kerberos context
+(configuration files, DNS etc etc) but you may need to override them. If you leave out the password
+or set it to undef the client library will prompt you for a password. You must include the
+Client parameter which is usually your admin or root -instance depending on your local
+system of belief. If for some reason the client connection cannot be initialized undef is
+returned and errors are sent to warn unless the RaiseError parameter is set in which case
+all errors are propagated by die.
+
+my @names = $client->getPrincipals($pattern);
+
+The getPrincipals method returns a list of principals matching $pattern which is not a
+regular expression but rather a glob-like animal. For instance '*/admin@REALM' is an
+ok pattern. The elements of the list are principal names which can be used to obtain
+Heimdal::Kadm5::Principal object using
+
+my $principal = $client->getPrincipal($name);
+
+which returns a Heimdal::Kadm5::Principal object (see the next section for details).
+
+my $principal = $client->makePrincipal($name);
+
+The makePrincipal method takes a principal name and creates an empty Heimdal::Kadm5::Principal
+object. This is intended for adding principals to the kdc. After creating the principal
+using makePrincipal use the accessor methods in Heimdal::Kadm5::Principal to set values
+before adding the principal using
+
+$client->createPrincipal($principal,$password,$mask);
+
+If $mask is set this value is used to determine which elements of the principal to include
+in the creation. Normally this value is automatically determined by tracking the uses of
+the accessor methods in the Heimdal::Kadm5::Principal class.
+
+Modifications to an existing principal is done using this method:
+
+$client->createPrincipal($principal,$mask);
+
+The $mask value works in the same way as described above for createPrincipal. It is sometimes
+useful to disable (lock) a principal, for instance when several operations must be performed.
+The following methods can be used:
+
+$client->disablePrincipal($name);
+
+$client->enablePrincipal($name);
+
+Other methods which modify the kdc are and the use of which should be obvious:
+
+$client->changePassword($name, $password);
+
+$client->deletePrincipal($name);
+
+$client->renamePrincipal($name, $newname);
+
+$client->randKeyPrincipal($name);
+
+This method creates a random set of keys for the principal named $name. This is typically
+done for service principals. When creating a new service principal it is probably a good
+idea to create the principal with some initial password, disable the principal, apply the
+randKeyPrincipal method and then enable the principal.
+
+$client->flush();
+
+This method flushes all modifications to the datastore. It is called automatically
+when the client handle is DESTROYed if any modifications (password change, create,
+rename or delete has been performed);
+
+$client->extractKeytab($principal,$keytab);
+
+This method extracts the keys belonging to the principal object to the keytab
+(optionally) specified by the second argument. If the second argument is missing
+it defaults to the standard default keytab, typically F</etc/krb5.keytab>.
+
+=head2 Heimdal::Kadm5::Principal
+
+$principal->dump($io);
+
+Dumps a representation of $principal on the $io handle (which defaults to \*STDOUT).
+This is mostly usable for debugging or simple scripts.
+
+my $name = $principal->getPrincipal();
+$principal->setPrincipal($name);
+
+Gets and sets the principal name.
+
+my $seconds = $principal->getPrincExpireTime();
+$principal->setPrincExpireTime($seconds);
+
+Gets and sets the time this principal expires.
+
+my $seconds = $principal->getLastPwdChange();
+
+Returns the last time this principals password was changed.
+
+my $seconds = $principal->getPwExpiration();
+$principal->setPwExpiration($seconds);
+
+Gets and sets the password expriation time.
+
+my $seconds = $principal->getMaxLife();
+$principal->setMaxLife($seconds);
+
+Gets and sets the maximum lifetime of a ticket.
+
+my $seconds = $principal->getMaxRenewableLife();
+$principal->setMaxRenewableLife($seconds);
+
+Gets and sets the maximum renewable ticket lifetime.
+
+my $name = $principal->getModName();
+
+Returns the principal name of the last modifier of the entry. Not currently
+(as of heimdal 0.1g) supported by heimdal and contains undef.
+
+my $seconds = $principal->getModDate();
+
+Returns the date of last modification of the entry.
+
+my $policyname = $principal->getPolicy();
+
+getPolicy returns undef if no policy is set. Policies are not currently
+supported (as of heimdal 0.1g) and always returns undef.
+
+my $seconds = $principal->getLastSuccess();
+
+Last time a successful authentication was done against this principal.
+
+my $seconds= $principal->getLastFailed();
+
+Last time a failed authentication was done against this principal.
+
+my $nfailed = $principal->getFailAuthCounts();
+
+How many failed login attempts was done against this principal.
+
+my $bitmask = $principal->getAttributes();
+
+my $arrayref = $principal->getKeyTypes();
+
+getKeyTypes returns an array reference consisting of a list of array
+references with two elements each: [keytype,salt]. The keytype and
+salt are strings which describe a key associated with the principal.
+Note that this data may not be present depending on how the principal
+was obtained.
+
+
+=head1 Exported constants
+
+ KADM5_ADMIN_SERVICE
+ KADM5_API_VERSION_1
+ KADM5_API_VERSION_2
+ KADM5_ATTRIBUTES
+ KADM5_AUX_ATTRIBUTES
+ KADM5_CHANGEPW_SERVICE
+ KADM5_CONFIG_ACL_FILE
+ KADM5_CONFIG_ADBNAME
+ KADM5_CONFIG_ADB_LOCKFILE
+ KADM5_CONFIG_ADMIN_KEYTAB
+ KADM5_CONFIG_ADMIN_SERVER
+ KADM5_CONFIG_DBNAME
+ KADM5_CONFIG_DICT_FILE
+ KADM5_CONFIG_ENCTYPE
+ KADM5_CONFIG_ENCTYPES
+ KADM5_CONFIG_EXPIRATION
+ KADM5_CONFIG_FLAGS
+ KADM5_CONFIG_KADMIND_PORT
+ KADM5_CONFIG_MAX_LIFE
+ KADM5_CONFIG_MAX_RLIFE
+ KADM5_CONFIG_MKEY_FROM_KEYBOARD
+ KADM5_CONFIG_MKEY_NAME
+ KADM5_CONFIG_PROFILE
+ KADM5_CONFIG_REALM
+ KADM5_CONFIG_STASH_FILE
+ KADM5_FAIL_AUTH_COUNT
+ KADM5_HIST_PRINCIPAL
+ KADM5_KEY_DATA
+ KADM5_KVNO
+ KADM5_LAST_FAILED
+ KADM5_LAST_PWD_CHANGE
+ KADM5_LAST_SUCCESS
+ KADM5_MAX_LIFE
+ KADM5_MAX_RLIFE
+ KADM5_MKVNO
+ KADM5_MOD_NAME
+ KADM5_MOD_TIME
+ KADM5_POLICY
+ KADM5_POLICY_CLR
+ KADM5_POLICY_NORMAL_MASK
+ KADM5_PRINCIPAL
+ KADM5_PRINCIPAL_NORMAL_MASK
+ KADM5_PRINC_EXPIRE_TIME
+ KADM5_PRIV_ADD
+ KADM5_PRIV_ALL
+ KADM5_PRIV_CPW
+ KADM5_PRIV_DELETE
+ KADM5_PRIV_GET
+ KADM5_PRIV_LIST
+ KADM5_PRIV_MODIFY
+ KADM5_PW_EXPIRATION
+ KADM5_PW_HISTORY_NUM
+ KADM5_PW_MAX_LIFE
+ KADM5_PW_MIN_CLASSES
+ KADM5_PW_MIN_LENGTH
+ KADM5_PW_MIN_LIFE
+ KADM5_REF_COUNT
+ KADM5_STRUCT_VERSION
+ KADM5_TL_DATA
+ KRB5_KDB_DISALLOW_ALL_TIX
+ KRB5_KDB_DISALLOW_DUP_SKEY
+ KRB5_KDB_DISALLOW_FORWARDABLE
+ KRB5_KDB_DISALLOW_POSTDATED
+ KRB5_KDB_DISALLOW_PROXIABLE
+ KRB5_KDB_DISALLOW_RENEWABLE
+ KRB5_KDB_DISALLOW_SVR
+ KRB5_KDB_DISALLOW_TGT_BASED
+ KRB5_KDB_NEW_PRINC
+ KRB5_KDB_PWCHANGE_SERVICE
+ KRB5_KDB_REQUIRES_HW_AUTH
+ KRB5_KDB_REQUIRES_PRE_AUTH
+ KRB5_KDB_REQUIRES_PWCHANGE
+ KRB5_KDB_SUPPORT_DESMD5
+ USE_KADM5_API_VERSION
+
+
+=head1 AUTHOR
+
+Leif Johansson, leifj@matematik.su.se
+
+=head1 SEE ALSO
+
+perl(1).
+
+=cut
--- /dev/null
+
+#include "EXTERN.h"
+#include "perl.h"
+#include "XSUB.h"
+#include <krb5.h>
+#include <kadm5/admin.h>
+#include <kadm5/kadm5_err.h>
+
+#include "consts.h"
+
+typedef struct shandle_t {
+ int modcount;
+ void *ptr;
+ kadm5_config_params params;
+ krb5_context context;
+} shandle_t;
+
+typedef struct sprincipal_t {
+ shandle_t *handle;
+ int mask;
+ kadm5_principal_ent_rec principal;
+} sprincipal_t;
+
+static sprincipal_t *
+create_sprincipal(shandle_t *handle)
+{
+ sprincipal_t *p = (sprincipal_t *)safemalloc(sizeof(sprincipal_t));
+
+ memset(p,0,sizeof(*p));
+ p->handle = handle;
+ return p;
+}
+
+static void
+destroy_sprincipal(sprincipal_t *spp)
+{
+ kadm5_free_principal_ent(spp->handle,&spp->principal);
+ safefree(spp);
+}
+
+static shandle_t *
+sv2server_handle(SV *sv)
+{
+ if (SvROK(sv) && sv_isa(sv,"Heimdal::Kadm5::SHandle"))
+ return (shandle_t *)SvIV(SvRV(sv));
+ else
+ croak("Argument to sv2server_handle not referenced in package \"Heimdal::Kadm5::SHandle\"");
+}
+
+static sprincipal_t *
+sv2sprincipal(SV *sv)
+{
+ if (SvROK(sv) && sv_isa(sv,"Heimdal::Kadm5::Principal"))
+ return (sprincipal_t *)SvIV(SvRV(sv));
+ else
+ croak("Argument to sv2kadm5_principal not referenced in package \"Heimdal::Kadm5::Principal\"");
+}
+
+static int
+set_param_strval(HV *hv, char **str, char *key)
+{
+ SV **val = hv_fetch(hv, key, strlen(key), 0);
+ //fprintf(stderr,"%s=\"%s\"\n",key,val != NULL ? SvPV_nolen(*val):"(null)");
+ if (val != NULL)
+ {
+ *str = SvPV_nolen(*val);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+set_param_intval(HV *hv, int *ival, char *key)
+{
+ SV **val = hv_fetch(hv, key, 0, 0);
+ if (val)
+ {
+ *ival = (int)SvIV(*val);
+ return 1;
+ }
+ return 0;
+}
+
+static int
+not_here(s)
+char *s;
+{
+ croak("%s not implemented on this architecture", s);
+ return -1;
+}
+
+MODULE = Heimdal::Kadm5::SHandle PACKAGE = Heimdal::Kadm5::SHandle PREFIX=kadm5_
+PROTOTYPES: ENABLE
+
+shandle_t *
+new(self,sv)
+ SV *self
+ SV *sv
+ CODE:
+ {
+ if (SvROK(sv) && SvTYPE(SvRV(sv)) == SVt_PVHV)
+ {
+ HV *hv = (HV *)SvRV(sv);
+ shandle_t *handle = (shandle_t *)safemalloc(sizeof(shandle_t));
+ kadm5_ret_t ret;
+
+ memset(handle,0,sizeof(*handle));
+ ret = krb5_init_context(&handle->context);
+ if (ret)
+ {
+ safefree(handle);
+ croak("[Heimdal::Kadm5] krb5_init_context failed: %s\n",krb5_get_err_text(handle->context, ret));
+ handle = NULL;
+ goto cleanup;
+ }
+
+ if (set_param_strval(hv,&handle->params.realm,"Realm"))
+ {
+ fprintf(stderr,"Realm=\"%s\"\n",handle->params.realm);
+ krb5_set_default_realm(handle->context, handle->params.realm);
+ handle->params.mask |= KADM5_CONFIG_REALM;
+ }
+ /* set_param_strval(hv,&handle->params.profile,"Profile"); */
+ if (set_param_intval(hv,&handle->params.kadmind_port,"Port"))
+ handle->params.mask |= KADM5_CONFIG_KADMIND_PORT;
+ if (set_param_strval(hv,&handle->params.admin_server,"Server"))
+ handle->params.mask |= KADM5_CONFIG_ADMIN_SERVER;
+
+ cleanup:
+ RETVAL = handle;
+ }
+ else
+ {
+ croak("[Heimdal::Kadm5] Argument to \"Heimdal::Kadm5::SHandle::new\" must be a hash-reference");
+ RETVAL = NULL;
+ }
+ }
+ OUTPUT:
+ RETVAL
+
+void
+DESTROY(handle)
+ shandle_t *handle
+ CODE:
+ {
+ if (handle->modcount > 0)
+ {
+ kadm5_c_flush(handle->ptr);
+ }
+ if (handle->ptr)
+ kadm5_c_destroy(handle->ptr);
+ if (handle->context)
+ krb5_free_context(handle->context);
+ safefree(handle);
+ }
+
+void
+kadm5_c_init_with_password (handle, client_name, password, service_name, struct_version, api_version)
+ shandle_t *handle
+ char *client_name
+ char *password
+ char *service_name
+ unsigned long struct_version
+ unsigned long api_version
+ CODE:
+ {
+ kadm5_ret_t ret = kadm5_c_init_with_password_ctx(handle->context,
+ client_name,
+ password,
+ KADM5_ADMIN_SERVICE,
+ &handle->params,
+ struct_version,
+ api_version,
+ &handle->ptr);
+ if(ret)
+ croak("[Heimdal::Kadm5] kadm5_c_init_with_password_ctx failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+ }
+
+void
+kadm5_c_init_with_skey (handle, client_name, keytab, service_name, struct_version, api_version)
+ shandle_t *handle
+ char *client_name
+ char *keytab
+ char *service_name
+ unsigned long struct_version
+ unsigned long api_version
+ CODE:
+ {
+ kadm5_ret_t ret = kadm5_c_init_with_skey_ctx(handle->context,
+ client_name,
+ keytab,
+ KADM5_ADMIN_SERVICE,
+ &handle->params,
+ struct_version,
+ api_version,
+ &handle->ptr);
+ if(ret)
+ croak("[Heimdal::Kadm5] kadm5_c_init_with_skey_ctx failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+ }
+
+void
+kadm5_c_flush(handle)
+ shandle_t *handle
+ CODE:
+ {
+ kadm5_ret_t ret = kadm5_c_flush(handle->ptr);
+ if (ret)
+ croak("[Heimdal::Kadm5] kadm5_c_flush failed: %s\n",krb5_get_err_text(handle->context, ret));
+ handle->modcount = 0;
+ }
+
+void
+kadm5_c_modify_principal(handle,spp,mask)
+ shandle_t *handle
+ sprincipal_t *spp
+ int mask
+ CODE:
+ {
+ kadm5_ret_t ret;
+
+ if (mask == 0)
+ mask = spp->mask;
+ ret = kadm5_c_modify_principal(handle->ptr, &spp->principal, mask);
+ if (ret)
+ {
+ if (ret)
+ croak("[Heimdal::Kadm5] kadm5_c_modify_principal failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+ }
+ handle->modcount++;
+ }
+
+int
+kadm5_c_randkey_principal(handle,name)
+ shandle_t *handle
+ char *name
+ CODE:
+ {
+ krb5_keyblock *new_keys;
+ int n_keys, i;
+ krb5_principal principal;
+ krb5_error_code err;
+ kadm5_ret_t ret;
+
+ err = krb5_parse_name(handle->context, name, &principal);
+ if (err)
+ croak("[Heimdal::Kadm5] krb5_parse_name failed on \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, err));
+
+ ret = kadm5_randkey_principal(handle->ptr, principal, &new_keys, &n_keys);
+ if(ret)
+ {
+ krb5_free_principal(handle->context, principal);
+ croak("[Heimdal::Kadm5] kadm5_c_randkey_principal failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+ }
+ for(i = 0; i < n_keys; i++)
+ krb5_free_keyblock_contents(handle->context, &new_keys[i]);
+ free(new_keys);
+ krb5_free_principal(handle->context, principal);
+ handle->modcount++;
+ RETVAL = n_keys;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+kadm5_c_chpass_principal(handle,name,password)
+ shandle_t *handle
+ char *name
+ char *password
+ CODE:
+ {
+ kadm5_ret_t ret;
+ krb5_error_code ret2;
+ krb5_principal principal;
+
+ ret2 = krb5_parse_name(handle->context, name, &principal);
+ if (ret2)
+ croak("[Heimdal::Kadm5] krb5_parse_name failed on \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, ret2));
+
+ ret = kadm5_c_chpass_principal(handle->ptr,principal,password);
+ if (ret)
+ croak("[Heimdal::Kadm5] kadm5_c_chpass_principal failed on \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, ret));
+ handle->modcount++;
+ }
+
+void
+kadm5_c_create_principal(handle,spp,password,mask)
+ shandle_t *handle
+ sprincipal_t *spp
+ char *password
+ int mask
+ CODE:
+ {
+ kadm5_ret_t ret;
+
+ if (mask == 0)
+ mask = spp->mask;
+
+ ret = kadm5_c_create_principal(handle->ptr,&spp->principal,mask,password);
+ if (ret)
+ {
+ char *p;
+ krb5_error_code ret2;
+
+ ret2 = krb5_unparse_name(handle->context,spp->principal.principal,&p);
+ if (ret2)
+ {
+ safefree(p);
+ croak("[Heimdal::Kadm5] krb5_unparse_name failed: %s\n",
+ krb5_get_err_text(spp->handle->context, ret2));
+ }
+ croak("[Heimdal::Kadm5] krb5_c_create_principal failed on \"%s\": %s\n",
+ p,krb5_get_err_text(handle->context, ret));
+ }
+ handle->modcount++;
+ }
+
+void
+kadm5_c_rename_principal(handle, src, trg)
+ shandle_t *handle
+ char *src
+ char *trg
+ CODE:
+ {
+ krb5_error_code ret;
+ krb5_principal source, target;
+ kadm5_ret_t err;
+
+ ret = krb5_parse_name(handle->context, src, &source);
+ if (ret)
+ {
+ croak("[Heimdal::Kadm5] krb5_parse_name failed on \"%s\": %s\n",
+ src,krb5_get_err_text(handle->context, ret));
+ }
+
+ ret = krb5_parse_name(handle->context, trg, &target);
+ if (ret)
+ {
+ krb5_free_principal(handle->context, target);
+ croak("[Heimdal::Kadm5] krb5_parse_name failed on \"%s\": %s\n",
+ trg,krb5_get_err_text(handle->context, ret));
+ }
+
+ err = kadm5_c_rename_principal(handle->ptr, source, target);
+ if (err)
+ {
+ krb5_free_principal(handle->context, source);
+ krb5_free_principal(handle->context, target);
+ croak("[Heimdal::Kadm5] kadm5_rename_principal \"%s\" to \"%s\" failed: %s\n",
+ src,trg,krb5_get_err_text(handle->context, err));
+ }
+ krb5_free_principal(handle->context, source);
+ krb5_free_principal(handle->context, target);
+ handle->modcount++;
+ }
+
+void
+kadm5_c_delete_principal(handle,name)
+ shandle_t *handle
+ char *name
+ CODE:
+ {
+ krb5_error_code ret;
+ krb5_principal principal;
+ kadm5_ret_t err;
+
+ ret = krb5_parse_name(handle->context, name, &principal);
+ if (ret)
+ croak("[Heimdal::Kadm5] krb5_parse_name failed on \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, ret));
+
+ err = kadm5_c_delete_principal(handle->ptr,principal);
+ if (err)
+ {
+ krb5_free_principal(handle->context, principal);
+ croak("[Heimdal::Kadm5] kadm5_c_delete_principal failed for \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, err));
+ }
+ handle->modcount++;
+ krb5_free_principal(handle->context, principal);
+ }
+
+
+sprincipal_t *
+kadm5_c_get_principal(handle, name, mask)
+ shandle_t *handle
+ char *name
+ IV mask
+ CODE:
+ {
+ krb5_principal principal;
+ krb5_error_code ret;
+ sprincipal_t *spp;
+
+ ret = krb5_parse_name(handle->context, name, &principal);
+ if (ret)
+ croak("[Heimdal::Kadm5] krb5_parse_name failed on \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, ret));
+
+ spp = create_sprincipal(handle);
+ ret = kadm5_c_get_principal(handle->ptr,
+ principal,
+ &spp->principal,
+ mask);
+ if (ret)
+ {
+ if (ret == KADM5_UNK_PRINC) {
+ destroy_sprincipal(spp);
+ spp = NULL;
+ } else {
+ krb5_free_principal(handle->context, principal);
+ destroy_sprincipal(spp);
+ croak("[Heimdal::Kadm5] kadm5_c_get_principal failed for \"%s\": %s\n",
+ name,krb5_get_err_text(handle->context, ret));
+ }
+ }
+ krb5_free_principal(handle->context,principal);
+ RETVAL = spp;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+kadm5_c_get_principals(handle,exp)
+ shandle_t *handle
+ char *exp
+ PPCODE:
+ {
+ char **princs;
+ int num_princs,i;
+ kadm5_ret_t ret;
+
+ ret = kadm5_c_get_principals(handle->ptr,exp,&princs,&num_princs);
+ if (ret)
+ {
+ croak("[Heimdal::Kadm5] kadm5_c_get_principals failed for \"%s\": %s\n",
+ exp,krb5_get_err_text(handle->context, ret));
+ }
+ EXTEND(SP,num_princs);
+ for (i = 0; i < num_princs; i++)
+ {
+ PUSHs(sv_2mortal(newSVpv(princs[i],0)));
+ }
+ kadm5_free_name_list(handle->ptr,princs,&num_princs);
+ }
+
+int
+kadm5_c_get_privs(handle)
+ shandle_t *handle
+ CODE:
+ {
+ int privs;
+ kadm5_ret_t ret = kadm5_c_get_privs(handle->ptr,&privs);
+ if (ret)
+ {
+ croak("[Heimdal::Kadm5] kadm5_c_get_privs failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+ }
+ RETVAL = privs;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+kadm5_c_ext_keytab(handle,spp,keytab)
+ shandle_t *handle
+ sprincipal_t *spp
+ char *keytab
+ CODE:
+ {
+ int i;
+ krb5_keytab kt;
+ krb5_error_code ret;
+
+ if(keytab)
+ ret = krb5_kt_resolve(handle->context, keytab, &kt);
+ else
+ ret = krb5_kt_default(handle->context, &kt);
+
+ if (ret)
+ croak("[Heimdal::Kadm5] krb5_kt_resolv failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+
+ for(i = 0; i < spp->principal.n_key_data; i++)
+ {
+ krb5_keytab_entry key;
+ krb5_key_data *k = &spp->principal.key_data[i];
+
+ key.principal = spp->principal.principal;
+ key.vno = k->key_data_kvno;
+ key.keyblock.keytype = k->key_data_type[0];
+ key.keyblock.keyvalue.length = k->key_data_length[0];
+ key.keyblock.keyvalue.data = k->key_data_contents[0];
+ ret = krb5_kt_add_entry(handle->context, kt, &key);
+ if (ret)
+ croak("[Heimdal::Kadm5] krb5_kt_add_entry failed: %s\n",
+ krb5_get_err_text(handle->context, ret));
+ }
+
+ krb5_kt_close(handle->context, kt);
+ }
+
+MODULE = Heimdal::Kadm5::Principal PACKAGE = Heimdal::Kadm5::Principal
+
+sprincipal_t *
+new(handle,name)
+ shandle_t *handle
+ char *name
+ CODE:
+ {
+ sprincipal_t *spp = create_sprincipal(handle);
+ RETVAL = spp;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+DESTROY(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ destroy_sprincipal(spp);
+ }
+
+SV *
+getPrincipal(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ char *p;
+ krb5_error_code ret;
+
+ ret = krb5_unparse_name(spp->handle->context,spp->principal.principal,&p);
+ if (ret)
+ {
+ safefree(p);
+ croak("[Heimdal::Kadm5] krb5_unparse_name failed: %s\n",
+ krb5_get_err_text(spp->handle->context, ret));
+ }
+ RETVAL = newSVpv(p,0);
+ }
+ OUTPUT:
+ RETVAL
+
+void
+setPrincipal(spp,p)
+ sprincipal_t *spp
+ char *p
+ CODE:
+ {
+ krb5_error_code ret;
+
+ ret = krb5_parse_name(spp->handle->context,p,&spp->principal.principal);
+ if (ret)
+ {
+ croak("[Heimdal::Kadm5] krb5_parse_name failed for \"%s\": %s\n",
+ p,krb5_get_err_text(spp->handle->context, ret));
+ }
+ spp->mask |= KADM5_PRINCIPAL;
+ }
+
+int
+getPrincExpireTime(spp)
+ sprincipal_t *spp
+ PPCODE:
+ {
+ XPUSHi(spp->principal.princ_expire_time);
+ }
+
+void
+setPrincExpireTime(spp,val)
+ sprincipal_t *spp
+ IV val
+ CODE:
+ {
+ spp->principal.princ_expire_time = val;
+ spp->mask |= KADM5_PRINC_EXPIRE_TIME;
+ }
+
+IV
+getLastPwdChange(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.last_pwd_change;
+ }
+ OUTPUT:
+ RETVAL
+
+IV
+getPwExpiration(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.pw_expiration;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+setPwExpiration(spp,val)
+ sprincipal_t *spp
+ IV val
+ CODE:
+ {
+ spp->principal.pw_expiration = val;
+ spp->mask |= KADM5_PW_EXPIRATION;
+ }
+
+IV
+getMaxLife(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.max_life;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+setMaxLife(spp,val)
+ sprincipal_t *spp
+ IV val
+ CODE:
+ {
+ spp->principal.max_life = val;
+ spp->mask |= KADM5_MAX_LIFE;
+ }
+
+SV *
+getModName(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ char *p;
+ krb5_error_code ret;
+
+ ret = krb5_unparse_name(spp->handle->context,spp->principal.mod_name,&p);
+ if (ret)
+ {
+ safefree(p);
+ croak("[Heimdal::Kadm5] krb5_unparse_name failed: %s\n",
+ krb5_get_err_text(spp->handle->context, ret));
+ }
+ RETVAL = newSVpv(p,0);
+ }
+ OUTPUT:
+ RETVAL
+
+IV
+getModDate(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.mod_date;
+ }
+ OUTPUT:
+ RETVAL
+
+SV *
+getPolicy(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ if (spp->principal.policy)
+ RETVAL = newSVpv(spp->principal.policy,0);
+ else
+ RETVAL = &PL_sv_undef;
+ }
+ OUTPUT:
+ RETVAL
+
+IV
+getMaxRenewableLife(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.max_renewable_life;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+setMaxRenewableLife(spp,val)
+ sprincipal_t *spp
+ IV val
+ CODE:
+ {
+ spp->principal.max_renewable_life = val;
+ spp->mask |= KADM5_MAX_RLIFE;
+ }
+
+IV
+getLastSuccess(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.last_success;
+ }
+ OUTPUT:
+ RETVAL
+
+IV
+getLastFailed(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.last_failed;
+ }
+ OUTPUT:
+ RETVAL
+
+IV
+getFailAuthCount(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.fail_auth_count;
+ }
+ OUTPUT:
+ RETVAL
+
+IV
+getAttributes(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ RETVAL = spp->principal.attributes;
+ }
+ OUTPUT:
+ RETVAL
+
+void
+setAttributes(spp,val)
+ sprincipal_t *spp
+ IV val
+ CODE:
+ {
+ spp->principal.attributes = val;
+ spp->mask |= KADM5_ATTRIBUTES;
+ }
+
+SV *
+getKeytypes(spp)
+ sprincipal_t *spp
+ CODE:
+ {
+ int i;
+ AV *lst = newAV();
+
+ for (i = 0; i < spp->principal.n_key_data; ++i)
+ {
+ krb5_key_data *k = &spp->principal.key_data[i];
+ krb5_error_code ret;
+ char *e_string, *s_string;
+ SV *ksv[2];
+
+ ret = krb5_enctype_to_string (spp->handle->context,
+ k->key_data_type[0],
+ &e_string);
+ if (ret)
+ asprintf (&e_string, "unknown(%d)", k->key_data_type[0]);
+ ksv[0] = newSVpv(e_string,0);
+
+ ret = krb5_salttype_to_string (spp->handle->context,
+ k->key_data_type[0],
+ k->key_data_type[1],
+ &s_string);
+ if (ret)
+ asprintf (&s_string, "unknown(%d)", k->key_data_type[1]);
+ ksv[1] = newSVpv(s_string,0);
+
+ av_push(lst,newRV_inc((SV *)av_make(2,ksv)));
+ free (e_string);
+ free (s_string);
+ }
+ RETVAL = newRV_inc((SV *)lst);
+ }
+ OUTPUT:
+ RETVAL
+
+MODULE = Heimdal::Kadm5 PACKAGE = Heimdal::Kadm5
+
+double
+constant(name,arg)
+ char * name
+ int arg
--- /dev/null
+Changes
+Kadm5.pm
+Kadm5.xs
+Makefile.PL
+MANIFEST
+README
+test.pl
--- /dev/null
+use ExtUtils::MakeMaker;
+# See lib/ExtUtils/MakeMaker.pm for details of how to influence
+# the contents of the Makefile that is written.
+WriteMakefile(
+ 'NAME' => 'Heimdal::Kadm5',
+ 'VERSION_FROM' => 'Kadm5.pm', # finds $VERSION
+ 'PREREQ_PM' => {}, # e.g., Module::Name => 1.1
+ ($] >= 5.005 ? ## Add these new keywords supported since 5.005
+ (ABSTRACT_FROM => 'Kadm5.pm', # retrieve abstract from module
+ AUTHOR => 'A. U. Thor <a.u.thor@a.galaxy.far.far.away>') : ()),
+ 'LIBS' => ['-lresolv -L/pkg/heimdal/default/lib -lkrb5 -lroken -lasn1 -lkadm5clnt'], # e.g., '-lm'
+ 'INC' => '-I/pkg/heimdal/default/include', # e.g., '-I/usr/include/other'
+ 'DEFINE' => '', # e.g., '-DHAVE_SOMETHING'
+ # Insert -I. if you add *.h files later:
+ # 'OBJECT' => '$(O_FILES)', # link all the C files too
+);
--- /dev/null
+Heimdal/Kadm5 version 0.01
+==========================
+
+The README is used to introduce the module and provide instructions on
+how to install the module, any machine dependencies it may have (for
+example C compilers and installed libraries) and any other information
+that should be provided before the module is installed.
+
+A README file is required for CPAN modules since CPAN extracts the
+README file from a module distribution so that people browsing the
+archive can use it get an idea of the modules uses. It is usually a
+good idea to provide version information here so that people can
+decide whether fixes for the module are worth downloading.
+
+INSTALLATION
+
+To install this module type the following:
+
+ perl Makefile.PL
+ make
+ make test
+ make install
+
+DEPENDENCIES
+
+This module requires these other modules and libraries:
+
+ blah blah blah
+
+COPYRIGHT AND LICENCE
+
+Put the correct copyright and licence information here.
+
+Copyright (C) 2003 A. U. Thor blah blah blah
+
--- /dev/null
+
+static double
+constant(name, arg)
+char *name;
+int arg;
+{
+ errno = 0;
+ switch (*name) {
+ case 'A':
+ break;
+ case 'B':
+ break;
+ case 'C':
+ break;
+ case 'D':
+ break;
+ case 'E':
+ break;
+ case 'F':
+ break;
+ case 'G':
+ break;
+ case 'H':
+ break;
+ case 'I':
+ break;
+ case 'J':
+ break;
+ case 'K':
+ if (strEQ(name, "KRB5_KDB_DISALLOW_ALL_TIX"))
+#ifdef KRB5_KDB_DISALLOW_ALL_TIX
+ return KRB5_KDB_DISALLOW_ALL_TIX;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_API_VERSION_1"))
+#ifdef KADM5_API_VERSION_1
+ return KADM5_API_VERSION_1;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_API_VERSION_2"))
+#ifdef KADM5_API_VERSION_2
+ return KADM5_API_VERSION_2;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_ATTRIBUTES"))
+#ifdef KADM5_ATTRIBUTES
+ return KADM5_ATTRIBUTES;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_AUX_ATTRIBUTES"))
+#ifdef KADM5_AUX_ATTRIBUTES
+ return KADM5_AUX_ATTRIBUTES;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ACL_FILE"))
+#ifdef KADM5_CONFIG_ACL_FILE
+ return KADM5_CONFIG_ACL_FILE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ADBNAME"))
+#ifdef KADM5_CONFIG_ADBNAME
+ return KADM5_CONFIG_ADBNAME;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ADB_LOCKFILE"))
+#ifdef KADM5_CONFIG_ADB_LOCKFILE
+ return KADM5_CONFIG_ADB_LOCKFILE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ADMIN_KEYTAB"))
+#ifdef KADM5_CONFIG_ADMIN_KEYTAB
+ return KADM5_CONFIG_ADMIN_KEYTAB;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ADMIN_SERVER"))
+#ifdef KADM5_CONFIG_ADMIN_SERVER
+ return KADM5_CONFIG_ADMIN_SERVER;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_DBNAME"))
+#ifdef KADM5_CONFIG_DBNAME
+ return KADM5_CONFIG_DBNAME;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_DICT_FILE"))
+#ifdef KADM5_CONFIG_DICT_FILE
+ return KADM5_CONFIG_DICT_FILE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ENCTYPE"))
+#ifdef KADM5_CONFIG_ENCTYPE
+ return KADM5_CONFIG_ENCTYPE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_ENCTYPES"))
+#ifdef KADM5_CONFIG_ENCTYPES
+ return KADM5_CONFIG_ENCTYPES;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_EXPIRATION"))
+#ifdef KADM5_CONFIG_EXPIRATION
+ return KADM5_CONFIG_EXPIRATION;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_FLAGS"))
+#ifdef KADM5_CONFIG_FLAGS
+ return KADM5_CONFIG_FLAGS;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_KADMIND_PORT"))
+#ifdef KADM5_CONFIG_KADMIND_PORT
+ return KADM5_CONFIG_KADMIND_PORT;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_MAX_LIFE"))
+#ifdef KADM5_CONFIG_MAX_LIFE
+ return KADM5_CONFIG_MAX_LIFE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_MAX_RLIFE"))
+#ifdef KADM5_CONFIG_MAX_RLIFE
+ return KADM5_CONFIG_MAX_RLIFE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_MKEY_FROM_KEYBOARD"))
+#ifdef KADM5_CONFIG_MKEY_FROM_KEYBOARD
+ return KADM5_CONFIG_MKEY_FROM_KEYBOARD;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_MKEY_NAME"))
+#ifdef KADM5_CONFIG_MKEY_NAME
+ return KADM5_CONFIG_MKEY_NAME;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_PROFILE"))
+#ifdef KADM5_CONFIG_PROFILE
+ return KADM5_CONFIG_PROFILE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_REALM"))
+#ifdef KADM5_CONFIG_REALM
+ return KADM5_CONFIG_REALM;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_CONFIG_STASH_FILE"))
+#ifdef KADM5_CONFIG_STASH_FILE
+ return KADM5_CONFIG_STASH_FILE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_FAIL_AUTH_COUNT"))
+#ifdef KADM5_FAIL_AUTH_COUNT
+ return KADM5_FAIL_AUTH_COUNT;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_KEY_DATA"))
+#ifdef KADM5_KEY_DATA
+ return KADM5_KEY_DATA;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_KVNO"))
+#ifdef KADM5_KVNO
+ return KADM5_KVNO;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_LAST_FAILED"))
+#ifdef KADM5_LAST_FAILED
+ return KADM5_LAST_FAILED;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_LAST_PWD_CHANGE"))
+#ifdef KADM5_LAST_PWD_CHANGE
+ return KADM5_LAST_PWD_CHANGE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_LAST_SUCCESS"))
+#ifdef KADM5_LAST_SUCCESS
+ return KADM5_LAST_SUCCESS;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_MAX_LIFE"))
+#ifdef KADM5_MAX_LIFE
+ return KADM5_MAX_LIFE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_MAX_RLIFE"))
+#ifdef KADM5_MAX_RLIFE
+ return KADM5_MAX_RLIFE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_MKVNO"))
+#ifdef KADM5_MKVNO
+ return KADM5_MKVNO;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_MOD_NAME"))
+#ifdef KADM5_MOD_NAME
+ return KADM5_MOD_NAME;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_MOD_TIME"))
+#ifdef KADM5_MOD_TIME
+ return KADM5_MOD_TIME;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_POLICY"))
+#ifdef KADM5_POLICY
+ return KADM5_POLICY;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_POLICY_CLR"))
+#ifdef KADM5_POLICY_CLR
+ return KADM5_POLICY_CLR;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_POLICY_NORMAL_MASK"))
+#ifdef KADM5_POLICY_NORMAL_MASK
+ return KADM5_POLICY_NORMAL_MASK;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRINCIPAL"))
+#ifdef KADM5_PRINCIPAL
+ return KADM5_PRINCIPAL;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRINCIPAL_NORMAL_MASK"))
+#ifdef KADM5_PRINCIPAL_NORMAL_MASK
+ return KADM5_PRINCIPAL_NORMAL_MASK;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRINC_EXPIRE_TIME"))
+#ifdef KADM5_PRINC_EXPIRE_TIME
+ return KADM5_PRINC_EXPIRE_TIME;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_ADD"))
+#ifdef KADM5_PRIV_ADD
+ return KADM5_PRIV_ADD;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_ALL"))
+#ifdef KADM5_PRIV_ALL
+ return KADM5_PRIV_ALL;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_CPW"))
+#ifdef KADM5_PRIV_CPW
+ return KADM5_PRIV_CPW;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_DELETE"))
+#ifdef KADM5_PRIV_DELETE
+ return KADM5_PRIV_DELETE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_GET"))
+#ifdef KADM5_PRIV_GET
+ return KADM5_PRIV_GET;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_LIST"))
+#ifdef KADM5_PRIV_LIST
+ return KADM5_PRIV_LIST;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PRIV_MODIFY"))
+#ifdef KADM5_PRIV_MODIFY
+ return KADM5_PRIV_MODIFY;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PW_EXPIRATION"))
+#ifdef KADM5_PW_EXPIRATION
+ return KADM5_PW_EXPIRATION;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PW_HISTORY_NUM"))
+#ifdef KADM5_PW_HISTORY_NUM
+ return KADM5_PW_HISTORY_NUM;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PW_MAX_LIFE"))
+#ifdef KADM5_PW_MAX_LIFE
+ return KADM5_PW_MAX_LIFE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PW_MIN_CLASSES"))
+#ifdef KADM5_PW_MIN_CLASSES
+ return KADM5_PW_MIN_CLASSES;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PW_MIN_LENGTH"))
+#ifdef KADM5_PW_MIN_LENGTH
+ return KADM5_PW_MIN_LENGTH;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_PW_MIN_LIFE"))
+#ifdef KADM5_PW_MIN_LIFE
+ return KADM5_PW_MIN_LIFE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_REF_COUNT"))
+#ifdef KADM5_REF_COUNT
+ return KADM5_REF_COUNT;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_STRUCT_VERSION"))
+#ifdef KADM5_STRUCT_VERSION
+ return KADM5_STRUCT_VERSION;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KADM5_TL_DATA"))
+#ifdef KADM5_TL_DATA
+ return KADM5_TL_DATA;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_ALL_TIX"))
+#ifdef KRB5_KDB_DISALLOW_ALL_TIX
+ return KRB5_KDB_DISALLOW_ALL_TIX;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_DUP_SKEY"))
+#ifdef KRB5_KDB_DISALLOW_DUP_SKEY
+ return KRB5_KDB_DISALLOW_DUP_SKEY;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_FORWARDABLE"))
+#ifdef KRB5_KDB_DISALLOW_FORWARDABLE
+ return KRB5_KDB_DISALLOW_FORWARDABLE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_POSTDATED"))
+#ifdef KRB5_KDB_DISALLOW_POSTDATED
+ return KRB5_KDB_DISALLOW_POSTDATED;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_PROXIABLE"))
+#ifdef KRB5_KDB_DISALLOW_PROXIABLE
+ return KRB5_KDB_DISALLOW_PROXIABLE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_RENEWABLE"))
+#ifdef KRB5_KDB_DISALLOW_RENEWABLE
+ return KRB5_KDB_DISALLOW_RENEWABLE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_SVR"))
+#ifdef KRB5_KDB_DISALLOW_SVR
+ return KRB5_KDB_DISALLOW_SVR;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_DISALLOW_TGT_BASED"))
+#ifdef KRB5_KDB_DISALLOW_TGT_BASED
+ return KRB5_KDB_DISALLOW_TGT_BASED;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_NEW_PRINC"))
+#ifdef KRB5_KDB_NEW_PRINC
+ return KRB5_KDB_NEW_PRINC;
+#else
+ goto not_there;
+#endif
+
+ if (strEQ(name, "KRB5_KDB_REQUIRES_HW_AUTH"))
+#ifdef KRB5_KDB_REQUIRES_HW_AUTH
+ return KRB5_KDB_REQUIRES_HW_AUTH;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_REQUIRES_PRE_AUTH"))
+#ifdef KRB5_KDB_REQUIRES_PRE_AUTH
+ return KRB5_KDB_REQUIRES_PRE_AUTH;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_REQUIRES_PWCHANGE"))
+#ifdef KRB5_KDB_REQUIRES_PWCHANGE
+ return KRB5_KDB_REQUIRES_PWCHANGE;
+#else
+ goto not_there;
+#endif
+ if (strEQ(name, "KRB5_KDB_SUPPORT_DESMD5"))
+#ifdef KRB5_KDB_SUPPORT_DESMD5
+ return KRB5_KDB_SUPPORT_DESMD5;
+#else
+ goto not_there;
+#endif
+ break;
+ case 'L':
+ break;
+ case 'M':
+ break;
+ case 'N':
+ break;
+ case 'O':
+ break;
+ case 'P':
+ break;
+ case 'Q':
+ break;
+ case 'R':
+ break;
+ case 'S':
+ break;
+ case 'T':
+ break;
+ case 'U':
+ if (strEQ(name, "USE_KADM5_API_VERSION"))
+#ifdef USE_KADM5_API_VERSION
+ return USE_KADM5_API_VERSION;
+#else
+ goto not_there;
+#endif
+ break;
+ case 'V':
+ break;
+ case 'W':
+ break;
+ case 'X':
+ break;
+ case 'Y':
+ break;
+ case 'Z':
+ break;
+ }
+ errno = EINVAL;
+ return 0;
+
+not_there:
+ errno = ENOENT;
+ return 0;
+}
--- /dev/null
+# Before `make install' is performed this script should be runnable with
+# `make test'. After `make install' it should work as `perl test.pl'
+
+######################### We start with some black magic to print on failure.
+
+# Change 1..1 below to 1..last_test_to_print .
+# (It may become useful if the test is moved to ./t subdirectory.)
+
+BEGIN { $| = 1; print "0..4\n"; }
+END {print "not ok 1\n" unless $loaded;}
+#use lib './blib/lib';
+use Heimdal::Kadm5 qw(/KADM5_/);
+$loaded = 1;
+
+print "ok 0\n";
+
+my $mask = KADM5_PRINCIPAL_NORMAL_MASK | KADM5_KEY_DATA;
+print "ok 1\n";
+
+$client = Heimdal::Kadm5::Client->new(Server=>'localhost',Realm=>'EXAMPLE.COM',Principal=>'admin/admin@EXAMPLE.COM');
+print "ok 2\n";
+
+while (1) {
+my $princ = $client->getPrincipal('leifj@EXAMPLE.COM');
+print "ok 4\n";
+}
+warn $princ->getPrincipal;
+warn $princ->getLastPwdChange;
+my $hoho = $princ->getPolicy();
+print $hoho if defined $hoho;
+warn $princ->getLastSuccess;
+warn $princ->getLastFailed;
+warn $princ->getMaxRenewableLife;
+warn $princ->getFailAuthCount;
+for my $ks (@{$princ->getKeytypes})
+ {
+ print "Keytype: $ks->[0]\n";
+ print "Salt: $ks->[1]\n";
+ }
+
+#for my $name ($client->getPrincipals('*/admin'))
+# {
+# my $princ = $client->getPrincipal($name);
+# warn $princ->getPrincipal;
+# }
+#$princ = $client->getPrincipal('host/njal.matematik.su.se');
+#$client->extractKeytab($princ,'/tmp/trurl.keytab');
+
+
+
+######################### End of black magic.
+
+# Insert your test code below (better if it prints "ok 13"
+# (correspondingly "not ok 13") depending on the success of chunk 13
+# of the test code):
+
--- /dev/null
+TYPEMAP
+
+shandle_t * T_shandle_t
+sprincipal_t * T_sprincipal_t
+
+INPUT
+
+T_shandle_t
+ $var = sv2server_handle($arg)
+
+T_sprincipal_t
+ $var = sv2sprincipal($arg)
+
+OUTPUT
+
+T_shandle_t
+ sv_setref_pv($arg, \"Heimdal::Kadm5::SHandle\", (void *)$var);
+
+T_sprincipal_t
+ sv_setref_pv($arg, \"Heimdal::Kadm5::Principal\", (void *)$var);