#!/usr/bin/perl
#
# This script is not run automatically by the build process or by the test
# suite.  It's here as an example for how to generate the test tokens using
# the WebKDC::Token Perl modules.  It will regenerate all the tokens that are
# currently used for testing or, if given a command-line argument, generate
# only that token.
#
# Since each time a token is generated, it uses new random data and therefore
# changes, this script should not normally be run.  It will change all of the
# test tokens.  For regular testing, we want to use static tokens generated
# previously with earlier known-good versions to ensure that no new symmetric
# bugs have been introduced.
#
# Written by Russ Allbery <rra@stanford.edu>
# Copyright 2011
#     The Board of Trustees of the Leland Stanford Junior University
#
# See LICENSE for licensing terms.

use WebAuth qw(WA_PEC_LOGIN_CANCELED);
use WebKDC::Token ();

# Path to the keyring used to generate the tokens.  We assume this script is
# being run from the test data directory.
our $KEYRING = 'keyring';

# Syntax: File name is key, value is the module to use and then a hash of
# pairs of method name and value to call.
our %TOKENS =
    (
     'app-empty'   => [ 'WebKDC::AppToken',
                        { expiration_time => 2147483600 }
                      ],
     'app-expired' => [ 'WebKDC::AppToken',
                        { subject         => 'testuser',
                          creation_time   => 1308777900,
                          expiration_time => 1308871632 }
                      ],
     'app-minimal' => [ 'WebKDC::AppToken',
                        { subject         => 'testuser',
                          expiration_time => 2147483600 }
                      ],
     'app-session' => [ 'WebKDC::AppToken',
                        { session_key     => "\0\0;s=test;\0",
                          expiration_time => 2147483600 }
                      ],
     'app-ok'      => [ 'WebKDC::AppToken',
                        { subject         => 'testuser',
                          lastused_time   => 1308777930,
                          initial_factors => 'p',
                          session_factors => 'c',
                          loa             => 1,
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'cred-ok'     => [ 'WebKDC::CredToken',
                        { subject         => 'testuser',
                          cred_type       => 'krb5',
                          cred_server     => 'webauth/example.com@EXAMPLE.COM',
                          cred_data       => "some\0cred;da;;ta",
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'cred-empty'  => [ 'WebKDC::CredToken',
                        { cred_type       => 'krb5',
                          cred_server     => 'webauth/example.com@EXAMPLE.COM',
                          cred_data       => "some\0cred;da;;ta",
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'cred-exp'    => [ 'WebKDC::CredToken',
                        { subject         => 'testuser',
                          cred_type       => 'krb5',
                          cred_server     => 'webauth/example.com@EXAMPLE.COM',
                          cred_data       => "some\0cred;da;;ta",
                          creation_time   => 1308777900,
                          expiration_time => 1308871632 }
                      ],
     'error-code'  => [ 'WebKDC::ErrorToken',
                        { error_code      => 'foo',
                          error_message   => 'user canceled login',
                          creation_time   => 1308777900 }
                      ],
     'error-ok'    => [ 'WebKDC::ErrorToken',
                        { error_code      => WA_PEC_LOGIN_CANCELED,
                          error_message   => 'user canceled login',
                          creation_time   => 1308777900 }
                      ],
     'id-expired'  => [ 'WebKDC::IdToken',
                        { subject         => 'testuser',
                          subject_auth    => 'webkdc',
                          creation_time   => 1308777900,
                          expiration_time => 1308871632 }
                      ],
     'id-krb5'     => [ 'WebKDC::IdToken',
                        { subject_auth      => 'krb5',
                          subject_auth_data => "s=foo\0s=bar;;da",
                          initial_factors   => 'p',
                          session_factors   => 'c',
                          loa               => 1,
                          creation_time     => 1308777900,
                          expiration_time   => 2147483600 }
                      ],
     'id-minimal'  => [ 'WebKDC::IdToken',
                        { subject         => 'testuser',
                          subject_auth    => 'webkdc',
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'id-webkdc'   => [ 'WebKDC::IdToken',
                        { subject         => 'testuser',
                          subject_auth    => 'webkdc',
                          initial_factors => 'p',
                          session_factors => 'c',
                          loa             => 1,
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'login-empty' => [ 'WebKDC::LoginToken',
                        { username        => 'testuser',
                          password        => 'some;s=password' }
                      ],
     'login-otp'   => [ 'WebKDC::LoginToken',
                        { username        => 'testuser',
                          otp             => '489147',
                          creation_time   => 1308777900 }
                      ],
     'login-pass'  => [ 'WebKDC::LoginToken',
                        { username        => 'testuser',
                          password        => 'some;s=password',
                          creation_time   => 1308777900 }
                      ],
     'proxy-empty' => [ 'WebKDC::ProxyToken',
                        { proxy_type      => 'krb5',
                          webkdc_token    => "s=foo\0s=bar;;da",
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'proxy-exp'   => [ 'WebKDC::ProxyToken',
                        { subject         => 'testuser',
                          proxy_type      => 'krb5',
                          webkdc_token    => "s=foo\0s=bar;;da",
                          creation_time   => 1308777900,
                          expiration_time => 1308871632 }
                      ],
     'proxy-ok'    => [ 'WebKDC::ProxyToken',
                        { subject         => 'testuser',
                          proxy_type      => 'krb5',
                          webkdc_token    => "s=foo\0s=bar;;da",
                          initial_factors => 'p,o1,o,m',
                          session_factors => 'p,o1,o,m',
                          loa             => 2,
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'req-id'      => [ 'WebKDC::RequestToken',
                        { requested_token_type => 'id',
                          subject_auth         => 'webkdc',
                          app_state            => "s=foo\0s=bar;;da",
                          return_url           => 'https://example.com/',
                          request_options      => 'fa',
                          initial_factors      => 'p,o3,o,m',
                          session_factors      => 'p,o3,o,m',
                          loa                  => 3,
                          creation_time        => 1308777900 }
                      ],
     'req-id-krb5' => [ 'WebKDC::RequestToken',
                        { requested_token_type => 'id',
                          subject_auth         => 'krb5',
                          app_state            => "s=foo\0s=bar;;da",
                          return_url           => 'https://example.com/',
                          request_options      => 'fa',
                          initial_factors      => 'p,o3,o,m',
                          session_factors      => 'p,o3,o,m',
                          loa                  => 3,
                          creation_time        => 1308777900 }
                      ],
     'req-minimal' => [ 'WebKDC::RequestToken',
                        { requested_token_type => 'id',
                          subject_auth         => 'webkdc',
                          return_url           => 'https://example.com/',
                          creation_time        => 1308777900 }
                      ],
     'req-proxy'   => [ 'WebKDC::RequestToken',
                        { requested_token_type => 'proxy',
                          proxy_type           => 'krb5',
                          app_state            => "s=foo\0s=bar;;da",
                          return_url           => 'https://example.com/',
                          request_options      => 'fa',
                          initial_factors      => 'p,o3,o,m',
                          session_factors      => 'p,o3,o,m',
                          loa                  => 3,
                          creation_time        => 1308777900 }
                      ],
     'req-command' => [ 'WebKDC::RequestToken',
                        { command         => 'getTokensRequest',
                          creation_time   => 1308777900 }
                      ],
     'service-exp' => [ 'WebKDC::WebKDCServiceToken',
                        { subject         => 'krb5:service/foo@EXAMPLE.COM',
                          session_key     => "s=foo\0s=bar;;da",
                          creation_time   => 1308777900,
                          expiration_time => 1308871632 }
                      ],
     'service-ok'  => [ 'WebKDC::WebKDCServiceToken',
                        { subject         => 'krb5:service/foo@EXAMPLE.COM',
                          session_key     => "s=foo\0s=bar;;da",
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'wkproxy-exp' => [ 'WebKDC::WebKDCProxyToken',
                        { subject         => 'testuser',
                          proxy_type      => 'remuser',
                          proxy_subject   => 'WEBKDC:remuser',
                          proxy_data      => 'testuser',
                          creation_time   => 1308777900,
                          expiration_time => 1308871632 }
                      ],
     'wkproxy-min' => [ 'WebKDC::WebKDCProxyToken',
                        { subject         => 'testuser',
                          proxy_type      => 'remuser',
                          proxy_subject   => 'WEBKDC:remuser',
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
     'wkproxy-ok'  => [ 'WebKDC::WebKDCProxyToken',
                        { subject         => 'testuser',
                          proxy_type      => 'krb5',
                          proxy_subject   => 'krb5:service/foo@EXAMPLE.COM',
                          proxy_data      => "s=foo\0s=bar;;da",
                          initial_factors => 'p,o1,o,m',
                          loa             => 2,
                          creation_time   => 1308777900,
                          expiration_time => 2147483600 }
                      ],
    );

# Get the tokens to create from the command line, if any.
my %generate = map { $_ => 1 } @ARGV;

# Load the keyring.
my $keyring = WebAuth::Keyring->read_file ($KEYRING);

# Generate the tokens that we can generate from the hash.
for my $file (sort keys %TOKENS) {
    next if (%generate and not $generate{$file});
    my ($class, $data) = @{ $TOKENS{$file} };
    my $token = $class->new;
    for my $method (sort keys %$data) {
        $token->$method ($data->{$method});
    }
    open (TOKEN, '>', "tokens/$file")
        or die "cannot create tokens/$file: $!\n";
    print TOKEN WebAuth::base64_encode ($token->to_token ($keyring)), "\n";
    close TOKEN;
}

# Generate some additional tokens that cannot be generated directly.
if (not %generate or $generate{'app-bad-hmac'}) {
    open (OK, '<', 'tokens/app-ok')
        or die "cannot open tokens/app-ok: $!\n";
    my $token = <OK>;
    close OK;
    $token =~ s/^(.{109})./$1 . 'o'/e;
    open (BAD, '>', 'tokens/app-bad-hmac')
        or die "cannot create tokens/app-bad-hmac: $!\n";
    print BAD $token;
    close BAD;
}
if (not %generate or $generate{'app-raw'}) {
    my ($class, $data) = @{ $TOKENS{'app-ok'} };
    my $token = $class->new;
    for my $method (sort keys %$data) {
        $token->$method ($data->{$method});
    }
    open (RAW, '>', 'tokens/app-raw')
        or die "cannot create tokens/app-raw: $!\n";
    print RAW $token->to_token ($keyring);
    close RAW;
}
