1#!/usr/bin/perl
2#
3# Tests for cookie setting
4#
5# Written by Jon Robertson <jonrober@stanford.edu>
6# Copyright 2013
7#     The Board of Trustees of the Leland Stanford Junior University
8#
9# See LICENSE for licensing terms.
10
11use strict;
12use warnings;
13
14use Test::More tests => 12;
15
16# Ensure we don't pick up the system webkdc.conf.
17BEGIN { $ENV{WEBKDC_CONFIG} = '/nonexistent' }
18
19use lib ('t/lib', 'lib', 'blib/arch');
20
21use CGI;
22use CGI::Cookie;
23use Date::Parse;
24use WebAuth qw(3.00 :const);
25use WebKDC ();
26use WebKDC::Config;
27use WebLogin;
28
29# Set our method to not have password tests complain.
30$ENV{REQUEST_METHOD} = 'POST';
31
32# Override the WebKDC package in order to put in our own version of a function
33# for testing.
34our ($TEST_STATUS, $TEST_ERROR);
35package WebKDC;
36no warnings 'redefine';
37sub make_request_token_request {
38    return ($TEST_STATUS, $TEST_ERROR);
39}
40use warnings 'redefine';
41package main;
42
43#############################################################################
44# Wrapper functions
45#############################################################################
46
47# Initialize the weblogin object, as we'll have to keep touching this over
48# and again.
49sub init_weblogin {
50    my $query = CGI->new ({});
51    $query->request_method ('POST');
52
53    my $weblogin = WebLogin->new (QUERY  => $query);
54    $weblogin->cgiapp_prerun;
55    $weblogin->param ('debug', 0);
56    $weblogin->param ('logging', 0);
57    $weblogin->param ('script_name', '/login');
58
59    return $weblogin;
60}
61
62#############################################################################
63# Environment setup
64#############################################################################
65
66# Disable all the memcached stuff for now.
67@WebKDC::Config::MEMCACHED_SERVERS = ();
68
69# Expiration to test against, as epoch seconds and text.
70my $expires_epoch = 1577865600;
71my $expires_text  = 'Wed, 01-Jan-2020 08:00:00 GMT';
72
73my $cookie_name = 'webauth_wpt_test';
74
75#############################################################################
76# Tests
77#############################################################################
78
79my ($status, $error);
80
81# Check to see if we set a cookie when we should.  Requires digging into the
82# CGI::Application object a little.
83my $weblogin = init_weblogin;
84$status = $weblogin->setup_kdc_request;
85$weblogin->{response}->cookie ($cookie_name, 'test', $expires_epoch);
86my %args = (cookies => $weblogin->{response}->cookies);
87$weblogin->print_headers (\%args);
88my $cookie = undef;
89for my $c (@{ $weblogin->{'__HEADER_PROPS'}{'-cookie'} }) {
90    if ($c->name eq $cookie_name) {
91        $cookie = $c;
92    }
93}
94is ($cookie->name, $cookie_name, 'SSO cookie was set');
95is ($cookie->expires, undef, '... with the default lifetime');
96
97# Check clearing an SSO cookie by giving it an empty value.
98$weblogin = init_weblogin;
99$status = $weblogin->setup_kdc_request;
100$weblogin->{response}->cookie ($cookie_name, '', $expires_epoch);
101%args = (cookies => $weblogin->{response}->cookies);
102$weblogin->print_headers (\%args);
103$cookie = undef;
104for my $c (@{ $weblogin->{'__HEADER_PROPS'}{'-cookie'} }) {
105    if ($c->name eq $cookie_name) {
106        $cookie = $c;
107    }
108}
109is ($cookie->name, $cookie_name, 'SSO cookie with no content was set');
110my $expires = str2time ($cookie->expires);
111ok ($expires >= time - 60 * 60 * 24 - 2 && $expires <= time - 60 * 60 * 24,
112    '... and set to expire immediately');
113
114# Check clearing an SSO cookie by setting the public computer checkbox
115# and nothing else.  That shouldn't clear it, as it should only be cleared
116# when the login proces is over.
117$weblogin = init_weblogin;
118$status = $weblogin->setup_kdc_request;
119$weblogin->query->param (remember_login => 'no');
120$weblogin->{response}->cookie ($cookie_name, 'test', $expires_epoch);
121%args = (cookies => $weblogin->{response}->cookies);
122$weblogin->print_headers (\%args);
123$cookie = undef;
124for my $c (@{ $weblogin->{'__HEADER_PROPS'}{'-cookie'} }) {
125    if ($c->name eq $cookie_name) {
126        $cookie = $c;
127    }
128}
129is ($cookie->name, $cookie_name,
130    'SSO cookie on public computer during normal login process was set');
131is ($cookie->expires, undef, '... with the default lifetime');
132
133# Check clearing an SSO cookie by setting the public computer checkbox
134# and a redirect URL.  This simulates a redirect without showing the confirm
135# page.
136$weblogin = init_weblogin;
137$status = $weblogin->setup_kdc_request;
138$weblogin->query->param (remember_login => 'no');
139$weblogin->{response}->cookie ($cookie_name, 'test', $expires_epoch);
140%args = (confirm_page => 1,
141         cookies      => $weblogin->{response}->cookies,
142         return_url   => 'http://www.test.com');
143$weblogin->print_headers (\%args);
144$cookie = undef;
145for my $c (@{ $weblogin->{'__HEADER_PROPS'}{'-cookie'} }) {
146    if ($c->name eq $cookie_name) {
147        $cookie = $c;
148    }
149}
150is ($cookie->name, $cookie_name,
151    'SSO cookie on public computer redirecting without confirm was set');
152$expires = str2time ($cookie->expires);
153is ($expires, time - 60 * 60 * 24, '... and set to expire immediately');
154
155# Check clearing an SSO cookie by setting the public computer checkbox,
156# and the flag for having come from the confirm page.  This should clear the
157# cookie.
158$weblogin = init_weblogin;
159$status = $weblogin->setup_kdc_request;
160$weblogin->query->param (remember_login => 'no');
161$weblogin->{response}->cookie ($cookie_name, 'test', $expires_epoch);
162%args = (cookies      => $weblogin->{response}->cookies,
163         confirm_page => 1);
164$weblogin->print_headers (\%args);
165$cookie = undef;
166for my $c (@{ $weblogin->{'__HEADER_PROPS'}{'-cookie'} }) {
167    if ($c->name eq $cookie_name) {
168        $cookie = $c;
169    }
170}
171is ($cookie->name, $cookie_name,
172    'SSO cookie on public computer on confirm page');
173$expires = str2time ($cookie->expires);
174is ($expires, time - 60 * 60 * 24, '... and set to expire immediately');
175
176# Check whether a cookie that's set in the browser's cookie jar will be
177# correctly cleared even if the response doesn't contain any cookies.
178$weblogin = init_weblogin;
179$status = $weblogin->setup_kdc_request;
180$weblogin->query->param (remember_login => 'no');
181%args = (confirm_page => 1);
182{
183    local $ENV{HTTP_COOKIE} = "$cookie_name=something";
184    $weblogin->print_headers (\%args);
185}
186$cookie = undef;
187for my $c (@{ $weblogin->{'__HEADER_PROPS'}{'-cookie'} }) {
188    if ($c->name eq $cookie_name) {
189        $cookie = $c;
190    }
191}
192is ($cookie->name, $cookie_name, 'Expiring browser cookie not sent by WebKDC');
193$expires = str2time ($cookie->expires);
194is ($expires, time - 60 * 60 * 24, '... and set to expire immediately');
195