NAME¶
Net::Remctl - Perl bindings for remctl (Kerberos remote command execution)
SYNOPSIS¶
    # Simplified form.
    use Net::Remctl;
    my $result = remctl("hostname", undef, undef, "test", "echo", "Hi");
    if ($result->error) {
        die "test echo failed with error ", $result->error, "\n";
    } else {
        warn $result->stderr;
        print $result->stdout;
        exit $result->status;
    }
    # Full interface.
    use Net::Remctl ();
    my $remctl = Net::Remctl->new;
    $remctl->open("hostname")
        or die "Cannot connect to hostname: ", $remctl->error, "\n";
    $remctl->command("test", "echo", "Hi there")
        or die "Cannot send command: ", $remctl->error, "\n";
    my $output;
    do {
        $output = $remctl->output;
        if ($output->type eq 'output') {
            if ($output->stream == 1) {
                print $output->data;
            } elsif ($output->stream == 2) {
                warn $output->data;
            }
        } elsif ($output->type eq 'error') {
            warn $output->error, "\n";
        } elsif ($output->type eq 'status') {
            exit $output->status;
        } else {
            die "Unknown output token from library: ", $output->type, "\n";
        }
    } while ($output->type eq 'output');
    $remctl->noop or die "Cannot send NOOP: ", $remctl->error, "\n";
DESCRIPTION¶
Net::Remctl provides Perl bindings to the libremctl client library. remctl is a
  protocol for remote command execution using GSS-API authentication. The
  specific allowable commands must be listed in a configuration file on the
  remote system and the remote system can map the remctl command names to any
  local command without exposing that mapping to the client. This module
  implements a remctl client.
Simplified Interface¶
If you want to run a single command on a remote system and get back the output
  and exit status, you can use the exported 
remctl() function:
  - remctl(HOSTNAME, PORT, PRINCIPAL, COMMAND, [ARGS,
    ...])
 
  - Runs a command on the remote system and returns a
      Net::Remctl::Result object (see below). HOSTNAME is the remote host to
      contact. PORT is the port of the remote remctld server and may be 0
      to tell the library to use the default (first try 4373, the registered
      remctl port, and fall back to the legacy 4444 port if that fails).
      PRINCIPAL is the principal of the server to use for authentication; pass
      in the empty string to use the default of host/HOSTNAME, with the realm
      determined by domain-realm mapping. The remaining arguments are the remctl
      command and arguments passed to the remote server.
    
 
    As far as the module is concerned, undef may be passed as PORT and PRINCIPAL
      and is the same as 0 and the empty string respectively. However, Perl will
      warn about passing undef explicitly as a function argument.
     
    The return value is a Net::Remctl::Result object which supports the
      following methods: 
  - error()
 
  - Returns the error message from either the remote host or
      from the local client library (if, for instance, contacting the remote
      host failed). Returns undef if there was no error. Checking whether
      error() returns undef is the supported way of determining whether
      the remctl() call succeeded.
 
  - stdout()
 
  - Returns the command's standard output or undef if there was
      none.
 
  - stderr()
 
  - Returns the command's standard error or undef if there was
      none.
 
  - status()
 
  - Returns the command's exit status.
 
 
 
Each call to 
remctl() will open a new connection to the remote host and
  close it after retrieving the results of the command. To maintain a persistent
  connection, use the full interface described below.
 
Full Interface¶
The full remctl library interface requires that the user do more bookkeeping,
  but it provides more flexibility and allows one to issue multiple commands on
  the same persistent connection (provided that the remote server supports
  protocol version two; if not, the library will transparently fall back to
  opening a new connection for each command).
To use the full interface, first create a Net::Remctl object with 
new()
  and then 
connect() to a remote server. Then, issue a 
command()
  and call 
output() to retrieve output tokens (as Net::Remctl::Output
  objects) until a status token is received. Destroying the Net::Remctl object
  will close the connection.
The supported object methods are:
  - new()
 
  - Create a new Net::Remctl object. This doesn't attempt to
      connect to a host and hence will only fail (by throwing an exception) if
      the library cannot allocate memory.
 
  - error()
 
  - Retrieves the error message from the last failing operation
      and returns it as a string.
 
  - set_ccache(CCACHE)
 
  - Sets the GSS-API credential cache for outgoing connections
      to CCACHE, which is normally the path to a Kerberos ticket cache but may
      have other valid forms depending on the underlying Kerberos implementation
      in use by GSS-API. This method must be called prior to calling
      open() and will affect all subsequent open() calls on at
      least the same object. Returns true on success and false on failure.
    
 
    For current GSS-API implementations, this will affect not only all
      subsequent open() calls for the same object, but all subsequent
      remctl connections of any kind from the same process, and even other
      GSS-API connections from the same process unrelated to remctl. This is due
      to a limitation in the GSS-API that makes this setting a global setting
      for the process or thread.
     
    Not all GSS-API implementations support setting the credential cache. If
      this is not supported, false will be returned. 
  - set_source_ip(SOURCE)
 
  - Sets the source IP for outgoing connections to SOURCE,
      which can be either an IPv4 or an IPv6 address (if IPv6 is supported). It
      must be an IP address, not a host name. This method must be called prior
      to calling open() and will affect all subsequent open()
      calls on the same object. Returns true on success and false on
    failure.
 
  - set_timeout(TIMEOUT)
 
  - Sets the timeout for connections and commands to TIMEOUT,
      which should be an integer number of seconds. TIMEOUT may be 0 to clear a
      timeout that was previously set. All subsequent operations on this
      Net::Remctl object will be subject to this timeout, including
      open() if called prior to calling open(). Returns true on
      success and false on failure. Failure is only possible if TIMEOUT is
      malformed.
    
 
    The timeout is a timeout on network activity from the server, not on a
      complete operation. So, for example, a timeout of ten seconds just
      requires that the server send some data every ten seconds. If the server
      sends only tiny amounts of data at a time, the complete operation could
      take much longer than ten seconds without triggering the timeout. 
  - open(HOSTNAME[, PORT[, PRINCIPAL]])
 
  - Connect to HOSTNAME on port PORT using PRINCIPAL as the
      remote server's principal for authentication. If PORT is omitted or 0, use
      the default (first try 4373, the registered remctl port, and fall back to
      the legacy 4444 port if that fails). If PRINCIPAL is omitted or the empty
      string, use the default of host/HOSTNAME, with the realm determined by
      domain-realm mapping. Returns true on success, false on failure. On
      failure, call error() to get the failure message.
    
 
    As far as the module is concerned, undef may be passed as PORT and PRINCIPAL
      and is the same as 0 and the empty string respectively. However, Perl will
      warn about passing undef explicitly as a function argument. 
  - command(COMMAND[, ARGS, ...])
 
  - Send the command and arguments to the remote host. The
      command and the arguments may, under the remctl protocol, contain any
      character, but be aware that most remctl servers will reject commands or
      arguments containing ASCII 0 (NUL), so currently this cannot be used for
      upload of arbitrary unencoded binary data. Returns true on success
      (meaning success in sending the command, and implying nothing about the
      result of the command), false on failure. On failure, call error()
      to get the failure message.
 
  - output()
 
  - Returns the next output token from the remote host. The
      token is returned as a Net::Remctl::Output object, which supports the
      following methods:
 
  - type()
 
  - Returns the type of the output token, which will be one of
      "output", "error", "status", or
      "done". A command will result in either one "error"
      token or zero or more "output" tokens followed by a
      "status" token. After either a "error" or
      "status" token is seen, another command can be issued. If the
      caller tries to retrieve another output token when it has already consumed
      all of them for that command, the library will return a "done"
      token.
 
  - data()
 
  - Returns the contents of the token. This method only makes
      sense for "output" and "error" tokens; otherwise, it
      will return undef. Note that the returned value may contain any character,
      including ASCII 0 (NUL).
 
  - length()
 
  - Returns the length of the data in the token. As with
      data(), this method only makes sense for the "output" and
      "error" tokens. It will return 0 if there is no data or if the
      data is zero-length.
 
  - stream()
 
  - For an "output" token, returns the stream with
      which the data is associated. Currently, only two stream values will be
      used: 1, meaning standard output; and 2, meaning standard error. The value
      is undefined for all other output token types.
 
  - status()
 
  - For a "status" token, returns the exit status of
      the remote command. The value is undefined for all other token types.
 
  - error()
 
  - For an "error" token, returns the remctl error
      code for the protocol error. The text message will be returned by
      data(). The value is undefined for all other token types.
 
 
  - noop()
 
  - Send a NOOP message to the server and read the reply. This
      is primarily used to keep a connection to a remctl server alive, such as
      through a firewall with a session timeout, while waiting to issue further
      commands. Returns true on success, false on failure. On failure, call
      error() to get the failure message.
    
 
    The NOOP message requires protocol version 3 support in the server, so the
      caller should be prepared for this function to fail, indicating that the
      connection could not be kept alive and possibly that it was closed by the
      server. In this case, the client will need to explicitly reopen the
      connection with open(). 
Note that, due to internal implementation details in the library, the
  Net::Remctl::Output object returned by 
output() will be invalidated by
  the next call to 
command() or 
output() or by destroying the
  producing Net::Remctl object. Therefore, any data in the output token should
  be processed and stored if needed before making any further Net::Remctl method
  calls on the same object.
CAVEATS¶
If the 
principal argument to 
remctl() or 
remctl_open() is
  NULL, most GSS-API libraries will canonicalize the 
host using DNS
  before deriving the principal name from it. This means that when connecting to
  a remctl server via a CNAME, 
remctl() and 
remctl_open() will
  normally authenticate using a principal based on the canonical name of the
  host instead of the specified 
host parameter. This behavior may cause
  problems if two consecutive DNS lookups of 
host may return two
  different results, such as with some DNS-based load-balancing systems.
The canonicalization behavior is controlled by the GSS-API library; with the MIT
  Kerberos GSS-API library, canonicalization can be disabled by setting
  "rdns" to false in the [libdefaults] section of 
krb5.conf. It
  can also be disabled by passing an explicit Kerberos principal name via the
  
principal argument, which will then be used without changes. If
  canonicalization is desired, the caller may wish to canonicalize 
host
  before calling 
remctl() or 
remctl_open() to avoid problems with
  multiple DNS calls returning different results.
The default behavior, when the port is not specified, of trying 4373 and falling
  back to 4444 will be removed in a future version of this module in favor of
  using the "remctl" service in 
/etc/services if set and then
  falling back on only 4373. 4444 was the poorly-chosen original remctl port and
  should be phased out.
NOTES¶
The remctl port number, 4373, was derived by tracing the diagonals of a QWERTY
  keyboard up from the letters "remc" to the number row.
SEE ALSO¶
remctl(1), 
remctld(8)
The current version of this module is available from its web page at
  <
http://www.eyrie.org/~eagle/software/remctl/>.
AUTHOR¶
Russ Allbery <rra@stanford.edu>
COPYRIGHT AND LICENSE¶
Copyright 2007, 2008, 2011 The Board of Trustees of the Leland Stanford Junior
  University. All rights reserved.
Permission is hereby granted, free of charge, to any person obtaining a copy of
  this software and associated documentation files (the "Software"),
  to deal in the Software without restriction, including without limitation the
  rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
  sell copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
  copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO
  EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES
  OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
  DEALINGS IN THE SOFTWARE.