Apache2-AuthCASpbh

 view release on metacpan or  search on metacpan

lib/Apache2/AuthCASpbh/Authn.pm  view on Meta::CPAN

				if (exists($session->{cas_proxy})) {
					$_log->l($debug_level, 'session contains proxy chain ' .
						 join(',', @{$session->{cas_proxy}}));
					$r->pnotes(cas_proxy => $session->{cas_proxy});
				}

				$cookies{$cookie_name}->bake($r);

				$r->pnotes(cas_session => $session->{_session_id});
				untie(%{$session});

				return Apache2::Const::OK;
			}
			else {
				$_log->l($debug_level, 'cookie for ' . ($session->{user} // '<missing>') .
					 ' expired ' . ($session->{expiration} // '<missing>'));

				eval { tied(%{$session})->delete; };
				if ($@) {
		    			$_log->l('warn', "session delete failed - $@");
				}
			}
		}
		elsif ($session !~ /Object does not exist in the data store/) {
		    	$_log->l('error', "session tie failed - $session");
			return Apache2::Const::SERVER_ERROR;
		}
		else {
			$_log->l($debug_level, "session not found");
		}
	}
	else {
		$_log->l($debug_level, "$cookie_name cookie not found");
	}

	my $q = CGI->new($r, $r->args);
	my $qs_nt = $r->args // '';
	if ($qs_nt) {
		$qs_nt =~ s/(^|&)ticket=[^&]+(&|$)/$1$2/;
		$qs_nt =~ s/(^&|&&|&$)//;
	}

	my $service;
	if (defined(cfg_value($dir_cfg, 'ServiceOverride'))) {
		$service = cfg_value($dir_cfg, 'ServiceOverride');
		$_log->l($debug_level, "overriding service to $service");
	}
	else {
		$service = $r->construct_url() . ($qs_nt ? "?$qs_nt" : '');
		$_log->l($debug_level, "set service to $service");
	};
	$service = Apache2::Util::escape_path($service, $r->pool);

	my $st = $q->param('ticket');
	if ($st) {
		my $ua = LWP::UserAgent->new(timeout => 10, keep_alive => 1);

		my $proxy_allow = cfg_value($dir_cfg, 'ProxyAllow');
		my $proxy_allow_re = cfg_value($dir_cfg, 'ProxyAllowRE');

		my $validate_url = cfg_value($dir_cfg, 'ServerURL') .
				   (defined($proxy_allow) || defined($proxy_allow_re) ?
				   	cfg_value($dir_cfg, 'ProxyValidatePath') :
					cfg_value($dir_cfg, 'ServiceValidatePath')) .
				   "?service=$service&ticket=$st";
		$_log->l($debug_level, "validating via URL $validate_url");

		if (cfg_value($dir_cfg, 'RequestPGT')) {
			my $pgt_callback = cfg_value($dir_cfg, 'PGTCallback');

			if ($pgt_callback !~ m#^https://#) {
				$pgt_callback = 'https://' . $r->server->server_hostname .
						 $pgt_callback;
			}

			$_log->l($debug_level, "using PGT callback $pgt_callback");
			$pgt_callback = Apache2::Util::escape_path($pgt_callback, $r->pool);

			$validate_url .= "&pgtUrl=$pgt_callback";
		}

		my $response;
		$response = $ua->get($validate_url);

		if(!$response->is_success()) {
			$_log->l('error', 'ticket validation call failed - ' .
				 $response->status_line());
			return Apache2::Const::SERVER_ERROR;
		}

		my $cas_data = eval { XML::Simple::XMLin($response->content(),
							 ForceArray => [ 'cas:proxy' ]); };
		if ($@) {
			$_log->l('error', "ticket validation xml parse failed - $@");
			return Apache2::Const::SERVER_ERROR;
		}

		if (exists($cas_data->{'cas:authenticationSuccess'})) {
			my $cas_success = $cas_data->{'cas:authenticationSuccess'};
			my $user = $cas_success->{'cas:user'};
			$_log->l($debug_level, "validated user $user");
			$r->user($user);

			my $cas_proxy;
			if (defined($proxy_allow) || defined($proxy_allow_re)) {
				if (exists($cas_success->{'cas:proxies'}{'cas:proxy'})) {
					$cas_proxy = $cas_success->{'cas:proxies'}{'cas:proxy'};

					if (!_allowed_proxy($_log, $debug_level, $cas_proxy,
							    $proxy_allow, $proxy_allow_re)) {
						$_log->l('notice', 'proxy chain (' .
								       join(' ', @{$cas_proxy}) .
								       ') not permitted');
						return Apache2::Const::FORBIDDEN;
					}
					$_log->l($debug_level, 'proxied via ' .
							       join(' ', @{$cas_proxy}));

					$r->pnotes(cas_proxy => $cas_proxy);
				}
				elsif (cfg_value($dir_cfg, 'ProxyRequired')) {
					$_log->l('notice', 'proxy chain not found in response');
					return Apache2::Const::FORBIDDEN;
				}
			}

			my $pgt;
			if (cfg_value($dir_cfg, 'RequestPGT')) {
				if (exists($cas_success->{'cas:proxyGrantingTicket'})) {
					my $pgt_iou = $cas_success->{'cas:proxyGrantingTicket'};
					my $pgt_session = open_session($session_db,
								       cfg_value($dir_cfg, 'SessionStateName'));

					$_log->l($debug_level, 'opening global state session ' .
							       cfg_value($dir_cfg, 'SessionStateName'));

					if (!ref($pgt_session)) {
						if ($pgt_session =~ /Object does not exist in the data store/) {
					    		$_log->l('error', 'global state session must be pre-created');
						}
						else {
					    		$_log->l('error', "session tie failed - $pgt_session");
						}
						return Apache2::Const::SERVER_ERROR;
					}

					if (exists($pgt_session->{pgtmap}{$pgt_iou})) {
						$pgt = $pgt_session->{pgtmap}{$pgt_iou}{pgt};
					    	$_log->l($debug_level, "found pgt $pgt");

						delete($pgt_session->{pgtmap}{$pgt_iou});
						$pgt_session->{update_count}++;
						untie(%{$pgt_session});

						$r->pnotes(cas_pgt => $pgt);
					}
					else {
				    		$_log->l('error', "pgt for $pgt_iou not found in session");
						return Apache2::Const::SERVER_ERROR;
					}
				}



( run in 1.745 second using v1.01-cache-2.11-cpan-437f7b0c052 )