diff options
| -rw-r--r-- | .travis.yml | 16 | ||||
| -rw-r--r-- | NEWS | 37 | ||||
| -rw-r--r-- | README | 5 | ||||
| -rw-r--r-- | TODO | 373 | ||||
| -rwxr-xr-x | contrib/wallet-contacts | 4 | ||||
| -rw-r--r-- | docs/design-acl | 34 | ||||
| -rw-r--r-- | perl/lib/Wallet/ACL/External.pm | 198 | ||||
| -rw-r--r-- | perl/lib/Wallet/Config.pm | 35 | ||||
| -rw-r--r-- | perl/lib/Wallet/Kadmin/MIT.pm | 5 | ||||
| -rw-r--r-- | perl/lib/Wallet/Object/Duo.pm | 34 | ||||
| -rwxr-xr-x | perl/t/data/acl-command | 43 | ||||
| -rwxr-xr-x | perl/t/object/keytab.t | 26 | ||||
| -rw-r--r-- | perl/t/object/password.t | 1 | ||||
| -rwxr-xr-x | perl/t/verifier/external.t | 32 | ||||
| -rwxr-xr-x | server/wallet-report | 24 | 
15 files changed, 637 insertions, 230 deletions
| diff --git a/.travis.yml b/.travis.yml new file mode 100644 index 0000000..3f60b23 --- /dev/null +++ b/.travis.yml @@ -0,0 +1,16 @@ +sudo: required +dist: trusty + +language: c +compiler: +  - gcc + +before_install: +  - sudo apt-get update -qq +  - sudo apt-get install -y libauthen-sasl-perl libcrypt-generatepassword-perl libdatetime-perl libdatetime-format-sqlite-perl libdbd-sqlite3-perl libdbi-perl libdbix-class-perl libheimdal-kadm5-perl libjson-perl libkrb5-dev libnet-dns-perl libnet-ldap-perl libnet-remctl-perl libperl6-slurp-perl libremctl-dev libsql-translator-perl libtest-minimumversion-perl libtest-pod-perl libtest-strict-perl libtimedate-perl libwebauth-perl perl sqlite3 +env: AUTHOR_TESTING=1 +script: ./autogen && ./configure && make warnings && make check + +branches: +  only: +    - master @@ -2,10 +2,33 @@  wallet 1.3 (unreleased) +    A new ACL type, nested (Wallet::ACL::Nested), is now supported.  The +    identifier of this ACL names another ACL, and access is granted if +    that ACL would grant access.  This lets one combine multiple other +    ACLs and apply the union to an object.  To enable this ACL type for an +    existing wallet database, use wallet-admin to register the new +    verifier. + +    A new ACL type, external (Wallet::ACL::External), is now supported. +    This ACL runs an external command to check if access is allowed, and +    passes the principal and the ACL identifier to that command.  To +    enable this ACL type for an existing wallet database, use wallet-admin +    to register the new verifier. + +    A new variation on the ldap-attr ACL type, ldap-attr-root +    (Wallet::ACL::LDAP::Attribute::Root), is now supported.  This is +    similar to netdb-root (compared to netdb): the authenticated principal +    must end in /root, and the LDAP entry checked will be for the same +    principal without the /root component.  This is useful for limiting +    access to certain privileged objects to Kerberos root instances.  To +    enable this ACL type for an existing wallet database, use wallet-admin +    to register the new verifier. +      A new object type, password (Wallet::Object::Password), is now      supported.  This is a subclass of the file object that will randomly      generate content for the object if you do a get before storing any -    content inside it. +    content inside it.  To enable this object type for an existing +    database, use wallet-admin to register the new object.      Add a new command to wallet-backend, update.  This will update the      contents of an object before running a get on it, and is only valid @@ -17,7 +40,8 @@ wallet 1.3 (unreleased)      warrants.      Add an acl replace command, to change all objects owned by one ACL to -    be owned by another. +    be owned by another.  This currently only handles owner, not any of +    the more specific ACLs.      All ACL operations now refer to the ACL by name rather than ID. @@ -25,11 +49,20 @@ wallet 1.3 (unreleased)      help for the existing unused report that implied it showed unstored as      well as unused. +    Add reports that list all object types (types) and all ACL schemes +    (schemes) currently registered in the wallet database. + +    Add a report of all ACLs that nest a given ACL.  This requires some +    additional local configuration (and probably some code).  See +    Wallet::Config for more information. +      Took contributions from Commerzbank AG to improve wallet history.  Add      a command to dump all object history for searching on to      wallet-report, and add a new script for more detailed object history      operations to the contrib directory. +    Displays of ACLs and ACL entries are now sorted correctly. +      Initial support for using Active Directory as the KDC for keytab      creation.  The interface to Active Directory uses a combination of      direct LDAP queries and the msktutil utility.  This version does @@ -109,7 +109,10 @@ REQUIREMENTS    WebAuth Perl module from WebAuth 4.4.0 or later.    The Duo integration object support in the wallet server requires the -  Net::Duo Perl module. +  Net::Duo, JSON, and Perl6::Slurp Perl modules. + +  The password object support in the wallet server requires the +  Crypt::GeneratePassword Perl module.    To support the LDAP attribute ACL verifier, the Authen::SASL and    Net::LDAP Perl modules must be installed on the server.  This verifier @@ -2,290 +2,265 @@  Client: - * KERB-94: Handle duplicate kvnos in a newly returned keytab and an -   existing keytab (such as when downloading an unchanging keytab and -   merging it into an existing one) in some reasonable fashion. + * Handle duplicate kvnos in a newly returned keytab and an existing +   keytab (such as when downloading an unchanging keytab and merging it +   into an existing one) in some reasonable fashion. - * KERB-90: Support removing old kvnos from a merged keytab (similar to -   kadmin ktremove old). + * Support removing old kvnos from a merged keytab (similar to kadmin +   ktremove old). - * KERB-88: When reading configuration from krb5.conf, we should first try -   to determine our principal from any existing Kerberos ticket cache -   (after obtaining tickets if -u was given) and extract the realm from -   that principal, using it as the default realm when reading -   configuration information. + * When reading configuration from krb5.conf, we should first try to +   determine our principal from any existing Kerberos ticket cache (after +   obtaining tickets if -u was given) and extract the realm from that +   principal, using it as the default realm when reading configuration +   information. - * KERB-89: Add readline support to the wallet client to make it easier to -   issue multiple commands. + * Add readline support to the wallet client to make it easier to issue +   multiple commands. - * KERB-115: Support authenticating with a keytab. + * Support authenticating with a keytab. - * KERB-97: When obtaining tickets in the wallet client with -u, directly -   obtain the service ticket we're going to use for remctl. + * When obtaining tickets in the wallet client with -u, directly obtain +   the service ticket we're going to use for remctl. - * KERB-95: Provide a way to refresh a file object if and only if what's -   stored on the server is different than what's on disk.  This will -   require server support as well for returning the checksum of a file. + * Provide a way to refresh a file object if and only if what's stored on +   the server is different than what's on disk.  This will require server +   support as well for returning the checksum of a file. - * KERB-104: Incorporate the wallet-rekey-periodic script (currently in -   contrib) into the package and teach it how to ignore foreign -   credentials. + * Incorporate the wallet-rekey-periodic script (currently in contrib) +   into the package and teach it how to ignore foreign credentials.  Server Interface: - * KERB-126: Provide a way to get history for deleted objects and ACLs. + * Provide a way to get history for deleted objects and ACLs. - * KERB-66: Provide an interface to mass-change all instances of one ACL -   to another. + * Provide an interface to mass-change all instances of one ACL to +   another.  (Owner changes are currently supported, but not the other +   ACLs.) - * KERB-96: Add help functions to wallet-backend, wallet-report, and -   wallet-admin listing the commands. + * Add help functions to wallet-backend and wallet-admin listing the +   commands. - * KERB-52: Catch exceptions on object creation in wallet-backend so that -   we can log those as well. + * Catch exceptions on object creation in wallet-backend so that we can +   log those as well. - * KERB-114: Provide a way to list all objects for which the connecting -   user has ACLs. + * Provide a way to list all objects for which the connecting user has +   ACLs. - * KERB-101: Support limiting returned history information by timestamp. + * Support limiting returned history information by timestamp. - * KERB-128: Provide a REST implementation of the wallet server. + * Provide a REST implementation of the wallet server. - * KERB-79: Provide a CGI implementation of the wallet server. + * Provide a CGI implementation of the wallet server. - * KERB-111: Support setting flags and attributes on autocreate.  In -   general, work out a Wallet::Object::Template Perl object that I can -   return that specifies things other than just the ACL. + * Support setting flags and attributes on autocreate.  In general, work +   out a Wallet::Object::Template Perl object that I can return that +   specifies things other than just the ACL. - * KERB-93: Remove the hard-coded ADMIN ACL in the server with something -   more configurable, perhaps a global ACL table or something. + * Remove the hard-coded ADMIN ACL in the server with something more +   configurable, perhaps a global ACL table or something. - * KERB-68: Support leap-of-faith keying of systems by registering an -   object for one-time download (ideally from a specific IP address) and -   then allowing that object to be downloaded anonymously from that IP. -   Relies on support for Kerberos anonymous authentication. + * Support leap-of-faith keying of systems by registering an object for +   one-time download (ideally from a specific IP address) and then +   allowing that object to be downloaded anonymously from that IP.  Relies +   on support for Kerberos anonymous authentication. - * KERB-84: Split "get" and "update" in semantics, and only do keytab -   rekeying on update.  "get" would not be permitted unless the keytab was -   flagged as unchanging, and update would still change even an unchanging -   keytab (maybe).  Or, alternately, maybe we allow get of any keytab? -   Requires more thought. + * Split "get" and "update" in semantics, and only do keytab rekeying on +   update.  "get" would not be permitted unless the keytab was flagged as +   unchanging, and update would still change even an unchanging keytab +   (maybe).  Or, alternately, maybe we allow get of any keytab?  Requires +   more thought. - * KERB-118: Add command to list available types and schemes. + * Add a mechanism to automate owner updates based on default_owner. - * KERB-75: Add a mechanism to automate owner updates based on -   default_owner. + * Partially merge create and autocreate.  create and autocreate should do +   the same thing provided there is an autocreation configuration +   available. If not, autocreate should fail and create should fall back +   on checking for ADMIN privileges. - * KERB-64: Partially merge create and autocreate.  create and autocreate -   should do the same thing provided there is an autocreation -   configuration available. If not, autocreate should fail and create -   should fall back on checking for ADMIN privileges. + * Rewrite server backends to use Net::Remctl::Backend. - * KERB-116: Support file object renaming. + * Merge the Wallet::Logger support written by Commerzbank AG: create a +   new class that handles logging, probably based on Log::Log4perl, and +   add logging points to all of the core classes. - * KERB-131: Rewrite server backends to use Net::Remctl::Backend. - - * KERB-132: Merge the Wallet::Logger support written by Commerzbank AG: -   create a new class that handles logging, probably based on -   Log::Log4perl, and add logging points to all of the core classes. - - * KERB-133: Support an authorization hook to determine whether or not to -   permit autocreate.  One requested example feature is to limit -   autocreate of keytab objects to certain hosts involved in deployment. -   It should be possible to write a hook that takes the information about -   what object is being autocreated and can accept or decline. + * Support an authorization hook to determine whether or not to permit +   autocreate.  One requested example feature is to limit autocreate of +   keytab objects to certain hosts involved in deployment.  It should be +   possible to write a hook that takes the information about what object +   is being autocreated and can accept or decline.  ACLs: - * KERB-119: Error messages from ACL operations should refer to the ACLs -   by name instead of by ID. - - * KERB-121: Write the PTS ACL verifier. + * Error messages from ACL operations should refer to the ACLs by name +   instead of by ID. - * KERB-123: Rename Wallet::ACL::* to Wallet::Verifier::*.  Add -   Wallet::ACL as a generic interface with Wallet::ACL::Database and -   Wallet::ACL::List implementations (or some similar name) so that we can -   create and check an ACL without having to write it into the database. -   Redo default ACL creation using that functionality. + * Write the PTS ACL verifier. - * KERB-67: Pass a reference to the object for which the ACL is -   interpreted to the ACL API so that ACL APIs can make more complex -   decisions. + * Rename Wallet::ACL::* to Wallet::Verifier::*.  Add Wallet::ACL as a +   generic interface with Wallet::ACL::Database and Wallet::ACL::List +   implementations (or some similar name) so that we can create and check +   an ACL without having to write it into the database.  Redo default ACL +   creation using that functionality. - * KERB-109: A group-in-groups ACL schema. + * Pass a reference to the object for which the ACL is interpreted to the +   ACL API so that ACL APIs can make more complex decisions. - * KERB-113: Provide an API for verifiers to syntax-check the values -   before an ACL is set and implement syntax checking for the krb5 and -   ldap-attr verifiers. + * Provide an API for verifiers to syntax-check the values before an ACL +   is set and implement syntax checking for the krb5 and ldap-attr +   verifiers. - * KERB-60: Investigate how best to support client authentication using -   anonymous PKINIT for things like initial system keying. + * Investigate how best to support client authentication using anonymous +   PKINIT for things like initial system keying. - * KERB-72: Generalize the current NetDB ACL type to allow a generic -   remctl query for whether a particular user is authorized to create -   host-based objects for a particular host. + * Generalize the current NetDB ACL type to allow a generic remctl query +   for whether a particular user is authorized to create host-based +   objects for a particular host. - * KERB-78: Add ldap-group ACL scheme. + * Add ldap-group ACL scheme (and possibly a root-only version). - * KERB-63: Provide a root-instance version of the ldap-attr (and possibly -   the ldap-group) ACL schemes. + * Add a comment field to ACLs. - * KERB-86: Add a comment field to ACLs. + * Support external ACLs under a backend other than remctl.  This will +   require some way of re-exporting the authenticated user identity +   instead of relying on the existence of the remctl variables.  Database: - * KERB-55: Fix case-insensitivity bug in unique keys with MySQL for -   objects.  When creating an http/<host> principal when an HTTP/<host> -   principal already existed, MySQL rejected the row entry as a duplicate. -   The name should be case-sensitive. + * Fix case-insensitivity bug in unique keys with MySQL for objects.  When +   creating an http/<host> principal when an HTTP/<host> principal already +   existed, MySQL rejected the row entry as a duplicate.  The name should +   be case-sensitive. - * KERB-103: On upgrades, support adding new object types and ACL -   verifiers to the class tables. + * On upgrades, support adding new object types and ACL verifiers to the +   class tables.  Objects: - * KERB-120: Check whether we can just drop the realm restriction on -   keytabs and allow the name to contain the realm if the Kerberos type is -   Heimdal. + * Check whether we can just drop the realm restriction on keytabs and +   allow the name to contain the realm if the Kerberos type is Heimdal. - * KERB-59: Use the Perl Authen::Krb5::Admin module instead of rolling our -   own kadmin code with Expect now that MIT Kerberos has made the kadmin -   API public. + * Use the Perl Authen::Krb5::Admin module instead of rolling our own +   kadmin code with Expect now that MIT Kerberos has made the kadmin API +   public. - * KERB-85: Implement an ssh keypair wallet object.  The server can run -   ssh-keygen to generate a public/private key pair and return both to the -   client, which would split them apart.  Used primarily for host keys. -   May need a side table to store key types, or a naming convention. + * Implement an ssh keypair wallet object.  The server can run ssh-keygen +   to generate a public/private key pair and return both to the client, +   which would split them apart.  Used primarily for host keys.  May need +   a side table to store key types, or a naming convention. - * KERB-124: Implement an X.509 certificate object.  I expect this would -   store the public and private key as a single file in the same format -   that Apache can read for combined public and private keys.  There were -   requests for storing the CSR, but I don't see why you'd want to do -   that.  Start with store support.  The file code is mostly sufficient -   here, but it would be nice to automatically support object expiration -   based on the expiration time for the certificate. + * Implement an X.509 certificate object.  I expect this would store the +   public and private key as a single file in the same format that Apache +   can read for combined public and private keys.  There were requests for +   storing the CSR, but I don't see why you'd want to do that.  Start with +   store support.  The file code is mostly sufficient here, but it would +   be nice to automatically support object expiration based on the +   expiration time for the certificate. - * KERB-106: Implement an X.509 CA so that you can get certificate objects -   without storing them first.  Need to resolve naming conventions if you -   want to run multiple CAs on the same wallet server (but why?).  Should -   this be a different type than stored certificates?  Consider using -   hxtool as the underlying CA mechanism. + * Implement an X.509 CA so that you can get certificate objects without +   storing them first.  Need to resolve naming conventions if you want to +   run multiple CAs on the same wallet server (but why?).  Should this be +   a different type than stored certificates?  Consider using hxtool as +   the underlying CA mechanism. - * KERB-77: Support returning the checksum of a file object stored in -   wallet so that one can determine whether the version stored on disk is -   identical. + * Support returning the checksum of a file object stored in wallet so +   that one can determine whether the version stored on disk is identical. - * KERB-108: Implement new password wallet object, which is like file -   except that it generates a random, strong password when retrieved the -   first time without being stored. - - * KERB-71: Support interrogating objects to find all host-based objects -   for a particular host, allowing cleanup of all of those host's objects -   after retiring the host. - - * KERB-127: Support setting the disallow-svr flag on created principals. -   In general, support setting arbitrary principal flags. + * Support setting the disallow-svr flag on created principals.  In +   general, support setting arbitrary principal flags.  Reports: - * KERB-117: Add audit for references to unknown ACLs, possibly introduced -   by previous versions before ACL deletion was checked with database + * Add audit for references to unknown ACLs, possibly introduced by +   previous versions before ACL deletion was checked with database     backends that don't do referential integrity. - * KERB-105: Add report for all objects that have never been stored. - - * KERB-122: For objects tied to hostnames, report on objects referring to -   hosts which do not exist.  For the initial pass, this is probably only -   keytab objects with names containing a slash where the part after the -   slash looks like a hostname.  This may need some configuration help. + * For objects tied to hostnames, report on objects referring to hosts +   which do not exist.  For the initial pass, this is probably only keytab +   objects with names containing a slash where the part after the slash +   looks like a hostname.  This may need some configuration help. - * KERB-102: Make contrib/wallet-summary generic and include it in -   wallet-report, with additional configuration in Wallet::Config. -   Enhance it to report on any sort of object, not just on keytabs, and to -   give numbers on downloaded versus not downloaded objects. + * Make contrib/wallet-summary generic and include it in wallet-report, +   with additional configuration in Wallet::Config.  Enhance it to report +   on any sort of object, not just on keytabs, and to give numbers on +   downloaded versus not downloaded objects. - * KERB-69: Write a tool to mail the owners of wallet objects, taking the -   list of objects and the mail message to send as inputs.  This could -   possibly use the notification service, although a version that sends -   mail directly would be useful external to Stanford. + * Write a tool to mail the owners of wallet objects, taking the list of +   objects and the mail message to send as inputs.  This could possibly +   use the notification service, although a version that sends mail +   directly would be useful external to Stanford. - * KERB-134: Merge the Commerzbank AG work to dump all the object history, -   applying various search criteria to it, or clear parts of the object -   history. + * Merge the Commerzbank AG work to dump all the object history, applying +   various search criteria to it, or clear parts of the object history.  Administrative Interface: - * KERB-80: Add a function to wallet-admin to purge expired entries. -   Possibly also check expiration before allowing anyone to get or store -   objects. + * Add a function to wallet-admin to purge expired entries.  Possibly also +   check expiration before allowing anyone to get or store objects. - * KERB-58: Add a function or separate script to automate removal of -   DNS-based objects for which the hosts no longer exist.  Will need to -   support a site-specific callout to determine whether the host exists. + * Add a function or separate script to automate removal of DNS-based +   objects for which the hosts no longer exist.  Will need to support a +   site-specific callout to determine whether the host exists. - * KERB-54: Database creation appears not to work without the SQL files, -   but it's supposed to work directly from the classes.  Double-check -   this. + * Database creation appears not to work without the SQL files, but it's +   supposed to work directly from the classes.  Double-check this.  Documentation: - * KERB-82: Write a conventions document for ACL naming, object naming, -   and similar issues. + * Write a conventions document for ACL naming, object naming, and similar +   issues. - * KERB-125: Write a future design and roadmap document to collect notes -   about how unimplemented features should be handled. + * Write a future design and roadmap document to collect notes about how +   unimplemented features should be handled. - * KERB-65: Document using the wallet system over something other than -   remctl. + * Document using the wallet system over something other than remctl. - * KERB-112: Document all diagnostics for all wallet APIs. + * Document all diagnostics for all wallet APIs. - * KERB-135: Document configuration with an Oracle database. + * Document configuration with an Oracle database.  Code Style and Cleanup: - * KERB-98: There is a lot of duplicate code in wallet-backend.  Convert -   that to use some sort of data-driven model with argument count and -   flags so that the method calls can be written only once.  Convert -   wallet-admin to use the same code. + * There is a lot of duplicate code in wallet-backend.  Convert that to +   use some sort of data-driven model with argument count and flags so +   that the method calls can be written only once.  Convert wallet-admin +   to use the same code. - * KERB-100: There's a lot of code duplication in the dispatch functions -   in the Wallet::Server class.  Find a way to rewrite that so that the -   dispatch doesn't duplicate the same code patterns. + * There's a lot of code duplication in the dispatch functions in the +   Wallet::Server class.  Find a way to rewrite that so that the dispatch +   doesn't duplicate the same code patterns. - * KERB-73: The wallet-backend and wallet documentation share the COMMANDS -   section.  Work out some means to assemble the documentation without -   duplicating content. + * The wallet-backend and wallet documentation share the COMMANDS section. +   Work out some means to assemble the documentation without duplicating +   content. - * KERB-110: The Wallet::Config class is very ugly and could use some -   better internal API to reference the variables in it. + * The Wallet::Config class is very ugly and could use some better +   internal API to reference the variables in it. - * KERB-76: Consider using Class::Accessor to get rid of the scaffolding -   code to access object data.  Alternately, consider using Moose. + * Consider using Class::Accessor to get rid of the scaffolding code to +   access object data.  Alternately, consider using Moose. - * KERB-130: Rewrite the error handling to use exceptions instead of the -   C-style return value and separate error call. + * Rewrite the error handling to use exceptions instead of the C-style +   return value and separate error call.  Test Suite: - * KERB-92: The ldap-attr verifier test case is awful and completely -   specific to people with admin access to the Stanford LDAP tree.  Write -   a real test. + * The ldap-attr verifier test case is awful and completely specific to +   people with admin access to the Stanford LDAP tree.  Write a real test. - * KERB-87: Rename the tests to use a subdirectory organization. + * Rename the tests to use a subdirectory organization. - * KERB-61: Add POD coverage testing using Test::POD::Coverage for the -   server modules. + * Add POD coverage testing using Test::POD::Coverage for the server +   modules. - * KERB-91: Rewrite the client test suite to use Perl and to make better -   use of shared code so that it can be broken into function components. + * Rewrite the client test suite to use Perl and to make better use of +   shared code so that it can be broken into function components. - * KERB-74: Refactor the test suite for the wallet backend to try to -   reduce the duplicated code.  Using a real mock infrastructure should -   make this test suite much easier to write. + * Refactor the test suite for the wallet backend to try to reduce the +   duplicated code.  Using a real mock infrastructure should make this +   test suite much easier to write. - * KERB-81: Pull common test suite code into a Perl library that can be -   reused. + * Pull common test suite code into a Perl library that can be reused. - * KERB-99: Write a test suite to scan all wallet code looking for -   diagnostics that aren't in the documentation and warn about them. + * Write a test suite to scan all wallet code looking for diagnostics that +   aren't in the documentation and warn about them. diff --git a/contrib/wallet-contacts b/contrib/wallet-contacts index ce16ab1..0c72c9c 100755 --- a/contrib/wallet-contacts +++ b/contrib/wallet-contacts @@ -12,7 +12,7 @@  # Modules and declarations  ############################################################################## -use 5.010; +use 5.008;  use autodie;  use strict;  use warnings; @@ -174,7 +174,7 @@ if ($mail) {  ##############################################################################  =for stopwords -ACL NetDB SQL hostname lookup swhois whois Allbery +ACL NetDB SQL hostname lookup swhois whois Allbery -dryrun  =head1 NAME diff --git a/docs/design-acl b/docs/design-acl index 424b3c6..b8bb8b3 100644 --- a/docs/design-acl +++ b/docs/design-acl @@ -13,7 +13,7 @@ Introduction  Syntax      An ACL entry in the wallet consists of two pieces of data, a <scheme> -    and an <instance>. <scheme> is one or more characters in the set +    and an <identifier>. <scheme> is one or more characters in the set      [a-z0-9-] that identifies the ACL backend to use when interpreting      this ACL.  <identifier> is zero or more characters including all      printable ASCII characters except whitespace.  Only the implementation @@ -50,11 +50,35 @@ Semantics  ACL Schemes +  external + +    The <identifier> is arguments to an external command.  Access is +    granted if the external command returns success.  The standard remctl +    environment variables are exposed to the external command. +    krb5      The <identifier> is a fully-qualified Kerberos principal.  Access is      granted if the principal of the client matches <identifier>. +  ldap-attr + +    <identifier> is an an attribute followed by an equal sign and a value. +    If the LDAP entry corresponding to the given principal contains the +    attribute and value specified by <identifier>, access is granted. + +  ldap-attr-root + +    This is almost identical to netdb except that the user must be in the +    form of a root instance (<user>/root) and the "/root" portion is +    stripped before checking the NetDB roles. + +  nested + +    <identifier> is the name of another ACL, and access is granted if it +    is granted by that ACL.  This can be used to organize multiple ACLs +    into a group and apply their union to an object. +    netdb      <identifier> is the name of a system.  Access is granted if the user @@ -67,13 +91,6 @@ ACL Schemes      form of a root instance (<user>/root) and the "/root" portion is      stripped before checking the NetDB roles. -  ldap-entitlement - -    (Not yet implemented.)  <identifier> is an entitlement.  If the -    entitlement attribute of the LDAP entry corresponding to the given -    principal contains the entitlement specified in <identifier>, access -    is granted. -    pts      (Not yet implemented.)  <identifier> is the name of an AFS PTS group. @@ -82,6 +99,7 @@ ACL Schemes  License +    Copyright 2016 Russ Allbery <eagle@eyrie.org>      Copyright 2006, 2007, 2008, 2013          The Board of Trustees of the Leland Stanford Junior University diff --git a/perl/lib/Wallet/ACL/External.pm b/perl/lib/Wallet/ACL/External.pm new file mode 100644 index 0000000..77c2499 --- /dev/null +++ b/perl/lib/Wallet/ACL/External.pm @@ -0,0 +1,198 @@ +# Wallet::ACL::External -- Wallet external ACL verifier +# +# Written by Russ Allbery <eagle@eyrie.org> +# Copyright 2016 Russ Allbery <eagle@eyrie.org> +# +# See LICENSE for licensing terms. + +############################################################################## +# Modules and declarations +############################################################################## + +package Wallet::ACL::External; +require 5.008; + +use strict; +use warnings; +use vars qw(@ISA $VERSION); + +use POSIX qw(_exit); +use Wallet::ACL::Base; +use Wallet::Config; + +@ISA = qw(Wallet::ACL::Base); + +# This version should be increased on any code change to this module.  Always +# use two digits for the minor version with a leading zero if necessary so +# that it will sort properly. +$VERSION = '0.01'; + +############################################################################## +# Interface +############################################################################## + +# Creates a new persistent verifier.  This just checks if the configuration +# is in place. +sub new { +    my $type = shift; +    unless ($Wallet::Config::EXTERNAL_COMMAND) { +        die "external ACL support not configured\n"; +    } +    my $self = {}; +    bless ($self, $type); +    return $self; +} + +# The most trivial ACL verifier.  Returns true if the provided principal +# matches the ACL. +sub check { +    my ($self, $principal, $acl) = @_; +    unless ($principal) { +        $self->error ('no principal specified'); +        return; +    } +    my @args = split (' ', $acl); +    unshift @args, $principal; +    my $pid = open (EXTERNAL, '-|'); +    if (not defined $pid) { +        $self->error ("cannot fork: $!"); +        return; +    } elsif ($pid == 0) { +        unless (open (STDERR, '>&STDOUT')) { +            warn "wallet: cannot dup stdout: $!\n"; +            _exit(1); +        } +        unless (exec ($Wallet::Config::EXTERNAL_COMMAND, @args)) { +            warn "wallet: cannot run $Wallet::Config::EXTERNAL_COMMAND: $!\n"; +            _exit(1); +        } +    } +    local $_; +    my @output = <EXTERNAL>; +    close EXTERNAL; +    if ($? == 0) { +        return 1; +    } else { +        if (@output) { +            $self->error ($output[0]); +            return; +        } else { +            return 0; +        } +    } +} + +1; +__END__ + +############################################################################## +# Documentation +############################################################################## + +=for stopwords +ACL Allbery verifier remctl + +=head1 NAME + +Wallet::ACL::External - Wallet ACL verifier using an external command + +=head1 SYNOPSIS + +    my $verifier = Wallet::ACL::External->new; +    my $status = $verifier->check ($principal, $acl); +    if (not defined $status) { +        die "Something failed: ", $verifier->error, "\n"; +    } elsif ($status) { +        print "Access granted\n"; +    } else { +        print "Access denied\n"; +    } + +=head1 DESCRIPTION + +Wallet::ACL::External runs an external command to determine whether access is +granted.  The command configured via $EXTERNAL_COMMAND in L<Wallet::Config> +will be run.  The first argument to the command will be the principal +requesting access.  The identifier of the ACL will be split on whitespace and +passed in as the remaining arguments to this command. + +No other arguments are passed to the command, but the command will have access +to all of the remctl environment variables seen by the wallet server (such as +REMOTE_USER).  For a full list of environment variables, see +L<remctld(8)/ENVIRONMENT>. + +The external command should exit with a non-zero status but no output to +indicate a normal failure to satisfy the ACL.  Any output will be treated as +an error. + +=head1 METHODS + +=over 4 + +=item new() + +Creates a new ACL verifier.  For this verifier, this just confirms that +the wallet configuration sets an external command. + +=item check(PRINCIPAL, ACL) + +Returns true if the external command returns success when run with that +PRINCIPAL and ACL.  ACL will be split on whitespace and passed as multiple +arguments.  So, for example, the ACL C<external mdbset shell> will, when +triggered by a request from rra@EXAMPLE.COM, result in the command: + +    $Wallet::Config::EXTERNAL_COMMAND rra@EXAMPLE.COM mdbset shell + +=item error() + +Returns the error if check() returned undef. + +=back + +=head1 DIAGNOSTICS + +The new() method may fail with one of the following exceptions: + +=over 4 + +=item external ACL support not configured + +The required configuration parameters were not set.  See L<Wallet::Config> +for the required configuration parameters and how to set them. + +=back + +Verifying an external ACL may fail with the following errors (returned by +the error() method): + +=over 4 + +=item cannot fork: %s + +The attempt to fork in order to execute the external ACL verifier +command failed, probably due to a lack of system resources. + +=item no principal specified + +The PRINCIPAL parameter to check() was undefined or the empty string. + +=back + +In addition, if the external command fails and produces some output, +that will be considered a failure and the first line of its output will +be returned as the error message.  The external command should exit +with a non-zero status but no error to indicate a normal failure. + +=head1 SEE ALSO + +remctld(8), Wallet::ACL(3), Wallet::ACL::Base(3), Wallet::Config(3), +wallet-backend(8) + +This module is part of the wallet system.  The current version is +available from L<http://www.eyrie.org/~eagle/software/wallet/>. + +=head1 AUTHOR + +Russ Allbery <eagle@eyrie.org> + +=cut diff --git a/perl/lib/Wallet/Config.pm b/perl/lib/Wallet/Config.pm index b3e1931..98b5dc9 100644 --- a/perl/lib/Wallet/Config.pm +++ b/perl/lib/Wallet/Config.pm @@ -1,7 +1,8 @@  # Wallet::Config -- Configuration handling for the wallet server.  #  # Written by Russ Allbery <eagle@eyrie.org> -# Copyright 2007, 2008, 2010, 2013, 2014 +# Copyright 2016 Russ Allbery <eagle@eyrie.org> +# Copyright 2007, 2008, 2010, 2013, 2014, 2015  #     The Board of Trustees of the Leland Stanford Junior University  #  # See LICENSE for licensing terms. @@ -16,7 +17,7 @@ use vars qw($PATH $VERSION);  # This version should be increased on any code change to this module.  Always  # use two digits for the minor version with a leading zero if necessary so  # that it will sort properly. -$VERSION = '0.05'; +$VERSION = '0.06';  # Path to the config file to load.  $PATH = $ENV{WALLET_CONFIG} || '/etc/wallet/wallet.conf'; @@ -540,6 +541,36 @@ our $WAKEYRING_PURGE_INTERVAL = 60 * 60 * 24 * 90;  =back +=head1 EXTERNAL ACL CONFIGURATION + +This configuration variable is only needed if you intend to use the +C<external> ACL type (the Wallet::ACL::External class).  This ACL type +runs an external command to determine if access is granted. + +=over 4 + +=item EXTERNAL_COMMAND + +Path to the command to run to determine whether access is granted.  The +first argument to the command will be the principal requesting access. +The identifier of the ACL will be split on whitespace and passed in as the +remaining arguments to this command. + +No other arguments are passed to the command, but the command will have +access to all of the remctl environment variables seen by the wallet +server (such as REMOTE_USER).  For a full list of environment variables, +see L<remctld(8)/ENVIRONMENT>. + +The external command should exit with a non-zero status but no output to +indicate a normal failure to satisfy the ACL.  Any output will be treated +as an error. + +=cut + +our $EXTERNAL_COMMAND; + +=back +  =head1 LDAP ACL CONFIGURATION  These configuration variables are only needed if you intend to use the diff --git a/perl/lib/Wallet/Kadmin/MIT.pm b/perl/lib/Wallet/Kadmin/MIT.pm index ac45265..c5dea23 100644 --- a/perl/lib/Wallet/Kadmin/MIT.pm +++ b/perl/lib/Wallet/Kadmin/MIT.pm @@ -18,6 +18,7 @@ use strict;  use warnings;  use vars qw(@ISA $VERSION); +use POSIX qw(_exit);  use Wallet::Config ();  use Wallet::Kadmin (); @@ -65,11 +66,11 @@ sub kadmin {          $self->{fork_callback} () if $self->{fork_callback};          unless (open (STDERR, '>&STDOUT')) {              warn "wallet: cannot dup stdout: $!\n"; -            exit 1; +            _exit(1);          }          unless (exec ($Wallet::Config::KEYTAB_KADMIN, @args)) {              warn "wallet: cannot run $Wallet::Config::KEYTAB_KADMIN: $!\n"; -            exit 1; +            _exit(1);          }      }      local $_; diff --git a/perl/lib/Wallet/Object/Duo.pm b/perl/lib/Wallet/Object/Duo.pm index d0901de..378c123 100644 --- a/perl/lib/Wallet/Object/Duo.pm +++ b/perl/lib/Wallet/Object/Duo.pm @@ -1,7 +1,8 @@  # Wallet::Object::Duo -- Base Duo object implementation for the wallet  #  # Written by Russ Allbery <eagle@eyrie.org> -# Copyright 2014 +# Copyright 2016 Russ Allbery <eagle@eyrie.org> +# Copyright 2014, 2015  #     The Board of Trustees of the Leland Stanford Junior University  #  # See LICENSE for licensing terms. @@ -18,8 +19,6 @@ use warnings;  use vars qw(@ISA $VERSION);  use JSON; -use Net::Duo::Admin; -use Net::Duo::Admin::Integration;  use Perl6::Slurp qw(slurp);  use Wallet::Config ();  use Wallet::Object::Base; @@ -159,8 +158,20 @@ sub new {      my $key_file = $Wallet::Config::DUO_KEY_FILE;      my $agent    = $Wallet::Config::DUO_AGENT; +    # Check that we can load all of the required modules. +    eval { +        require Net::Duo; +        require Net::Duo::Admin; +        require Net::Duo::Admin::Integration; +    }; +    if ($@) { +        my $error = $@; +        chomp $error; +        1 while ($error =~ s/ at \S+ line \d+\.?\z//); +        die "Duo object support not available: $error\n"; +    } +      # Construct the Net::Duo::Admin object. -    require Net::Duo::Admin;      my $duo = Net::Duo::Admin->new (          {              key_file   => $key_file, @@ -194,8 +205,20 @@ sub create {          die "$type is not a valid duo integration\n";      } +    # Check that we can load all of the required modules. +    eval { +        require Net::Duo; +        require Net::Duo::Admin; +        require Net::Duo::Admin::Integration; +    }; +    if ($@) { +        my $error = $@; +        chomp $error; +        1 while ($error =~ s/ at \S+ line \d+\.?\z//); +        die "Duo object support not available: $error\n"; +    } +      # Construct the Net::Duo::Admin object. -    require Net::Duo::Admin;      my $duo = Net::Duo::Admin->new (          {              key_file   => $key_file, @@ -204,7 +227,6 @@ sub create {      );      # Create the object in Duo. -    require Net::Duo::Admin::Integration;      my $duo_type = $DUO_TYPES{$type}{integration};      my %data = (          name  => "$name ($duo_type)", diff --git a/perl/t/data/acl-command b/perl/t/data/acl-command new file mode 100755 index 0000000..e368118 --- /dev/null +++ b/perl/t/data/acl-command @@ -0,0 +1,43 @@ +#!/bin/sh +# +# An external ACL implementation.  Checks that the first argument is +# eagle@eyrie.org, the second argument is "test", and then returns success, +# failure, or reports an error based on whether the second argument is +# success, failure, or error. +# +# Written by Russ Allbery <eagle@eyrie.org> +# Copyright 2016 Russ Allbery <eagle@eyrie.org> +# +# See LICENSE for licensing terms. + +set -e + +# Check the initial principal argument. +if [ "$1" != 'eagle@eyrie.org' ]; then +    echo 'incorrect principal' >&2 +    exit 1 +fi + +# Check that the second argument is test. +if [ "$2" != 'test' ]; then +    echo 'incorrect second argument' >&2 +    exit 1 +fi + +# Process the third argument. +case $3 in +    success) +        exit 0 +        ;; +    failure) +        exit 1 +        ;; +    error) +        echo 'some error' >&2 +        exit 1 +        ;; +    *) +        echo 'unknown third argument' >&2 +        exit 1 +        ;; +esac diff --git a/perl/t/object/keytab.t b/perl/t/object/keytab.t index 69db438..111b7d0 100755 --- a/perl/t/object/keytab.t +++ b/perl/t/object/keytab.t @@ -12,7 +12,7 @@ use strict;  use warnings;  use POSIX qw(strftime); -use Test::More tests => 141; +use Test::More tests => 142;  BEGIN { $Wallet::Config::KEYTAB_TMP = '.' } @@ -25,15 +25,28 @@ use Wallet::Object::Keytab;  use lib 't/lib';  use Util; -# Mapping of klist -ke encryption type names to the strings that Kerberos uses -# internally.  It's very annoying to have to maintain this, and it probably -# breaks with Heimdal. +# Mapping of klist -ke output from old MIT Kerberos implementations to to the +# strings that Kerberos uses internally.  It's very annoying to have to +# maintain this, and it probably breaks with Heimdal. +# +# Newer versions of MIT Kerberos just print out the canonical enctype names +# and don't need this logic, but the current test requires that they still +# have entries.  That's why the second set where the key and value are the +# same.  my %enctype =      ('triple des cbc mode with hmac/sha1'      => 'des3-cbc-sha1',       'des cbc mode with crc-32'                => 'des-cbc-crc',       'des cbc mode with rsa-md5'               => 'des-cbc-md5', +     'aes-128 cts mode with 96-bit sha-1 hmac' => 'aes128-cts-hmac-sha1-96',       'aes-256 cts mode with 96-bit sha-1 hmac' => 'aes256-cts-hmac-sha1-96', -     'arcfour with hmac/md5'                   => 'rc4-hmac'); +     'arcfour with hmac/md5'                   => 'rc4-hmac', + +     'des3-cbc-sha1'                           => 'des3-cbc-sha1', +     'des-cbc-crc'                             => 'des-cbc-crc', +     'des-cbc-md5'                             => 'des-cbc-md5', +     'aes128-cts-hmac-sha1-96'                 => 'aes128-cts-hmac-sha1-96', +     'aes256-cts-hmac-sha1-96'                 => 'aes256-cts-hmac-sha1-96', +     'rc4-hmac'                                => 'rc4-hmac');  # Some global defaults to use.  my $user = 'admin@EXAMPLE.COM'; @@ -159,7 +172,7 @@ my $date = strftime ('%Y-%m-%d %H:%M:%S', localtime $trace[2]);  # Basic keytab creation and manipulation tests.  SKIP: { -    skip 'no keytab configuration', 52 unless -f 't/data/test.keytab'; +    skip 'no keytab configuration', 53 unless -f 't/data/test.keytab';      # Set up our configuration.      $Wallet::Config::KEYTAB_FILE      = 't/data/test.keytab'; @@ -296,6 +309,7 @@ EOO                                          @trace)        };      ok (defined ($object), 'Creating good principal succeeds'); +    is ($@, '', ' with no error');      ok (created ('wallet/one'), ' and the principal was created');    SKIP: {          skip 'no kadmin program test for Heimdal', 2 diff --git a/perl/t/object/password.t b/perl/t/object/password.t index 4fe6b50..306d82b 100644 --- a/perl/t/object/password.t +++ b/perl/t/object/password.t @@ -120,5 +120,6 @@ like ($pwd, qr{^.{$Wallet::Config::PWD_LENGTH_MIN}$},  # Clean up.  $admin->destroy;  END { +    system ('rm -r test-files') == 0 or die "cannot remove test-files\n";      unlink ('wallet-db');  } diff --git a/perl/t/verifier/external.t b/perl/t/verifier/external.t new file mode 100755 index 0000000..3e7e776 --- /dev/null +++ b/perl/t/verifier/external.t @@ -0,0 +1,32 @@ +#!/usr/bin/perl +# +# Tests for the external wallet ACL verifier. +# +# Written by Russ Allbery <eagle@eyrie.org> +# Copyright 2016 Russ Allbery <eagle@eyrie.org> +# +# See LICENSE for licensing terms. + +use strict; +use warnings; + +use Test::More tests => 9; + +use Wallet::ACL::External; +use Wallet::Config; + +# Configure the external ACL verifier. +$Wallet::Config::EXTERNAL_COMMAND = 't/data/acl-command'; + +# Check a few verifications. +my $verifier = Wallet::ACL::External->new; +ok (defined $verifier, 'Wallet::ACL::External creation'); +ok ($verifier->isa ('Wallet::ACL::External'), ' and class verification'); +is ($verifier->check ('eagle@eyrie.org', 'test success'), 1, 'Success'); +is ($verifier->check ('eagle@eyrie.org', 'test failure'), 0, 'Failure'); +is ($verifier->error, undef, 'No error set'); +is ($verifier->check ('eagle@eyrie.org', 'test error'), undef, 'Error'); +is ($verifier->error, 'some error', ' and right error'); +is ($verifier->check (undef, 'eagle@eyrie.org'), undef, +    'Undefined principal'); +is ($verifier->error, 'no principal specified', ' and right error'); diff --git a/server/wallet-report b/server/wallet-report index 4719a8a..22637ca 100755 --- a/server/wallet-report +++ b/server/wallet-report @@ -135,7 +135,7 @@ wallet-report - Wallet server reporting interface  =for stopwords  metadata ACL hostname backend acl acls wildcard SQL Allbery remctl -MERCHANTABILITY NONINFRINGEMENT sublicense +MERCHANTABILITY NONINFRINGEMENT sublicense unstored  =head1 SYNOPSIS @@ -207,6 +207,10 @@ Returns all ACLs containing an entry with given scheme and identifier.  The scheme must be an exact match, but the <identifier> string will match  any identifier containing that string. +=item acls nested <acl> + +Returns all ACLs that contain this ACL as a nested entry. +  =item acls unused  Returns all ACLs that are not referenced by any of the objects in the @@ -274,6 +278,12 @@ those where that ACL has any other, more limited permissions.  Returns all objects which have the given flag set. +=item objects host <hostname> + +Returns all objects that belong to the given host.  This requires adding +local configuration to identify objects that belong to a given host.  See +L<Wallet::Config/"OBJECT HOST-BASED NAMES"> for more information. +  =item objects owner <acl>  Returns all objects owned by the given ACL name or ID. @@ -302,6 +312,14 @@ The output will be one line per ACL line in the form:  with duplicates suppressed. +=item schemes + +Returns a list of all registered ACL schemes. + +=item types + +Returns a list of all registered object types. +  =back  =head1 AUTHOR @@ -310,7 +328,9 @@ Russ Allbery <eagle@eyrie.org>  =head1 COPYRIGHT AND LICENSE -Copyright 2008, 2009, 2010, 2013 The Board of Trustees of the Leland +Copyright 2016 Russ Allbery <eagle@eyrie.org> + +Copyright 2008, 2009, 2010, 2013, 2015 The Board of Trustees of the Leland  Stanford Junior University  Permission is hereby granted, free of charge, to any person obtaining a | 
