Le 08/06/2011 18:30, Fabrice Durand a écrit :
Hi, what a coincidence,
Yesterday I fixed this problem between Sogo and vulture.
Which version of vulture do you use and can you send me the
TransHandler.pm file, I make you a patch.

Regards
Fabrice Durand

Le 8 juin 2011 14:34, Sébastien Posé <[email protected]
<mailto:[email protected]>> a écrit :

    Hi,

    I'm trying to use sogo throw vulture. I would like vulture
    authenticates my users by sending their login and password to the
    sogo's connection page (SSO feature).

    I'm able to authenticate users but they are redirected to
    /SOGo/connect and got:
    {"grace": -1, "expire": -1}

    If I remove /connect and refresh, I'm redirected to
    /SOGo/so/sebastien.pose/Mail/view and everything is ok.

    Has anyone encountered a similar problem?

    Thanks.
    --
    Sébastien Posé
    Division des Services Informatiques
    Rectorat de la Réunion
    --
    [email protected] <mailto:[email protected]>
    https://inverse.ca/sogo/lists



Hi,

I'm using vulture 1.99

Thank you.

--
Sébastien Posé
Division des Services Informatiques
Rectorat de la Réunion
--
[email protected]
https://inverse.ca/sogo/lists
package Vulture::TransHandler;

use Apache2::Const -compile => qw(OK REDIRECT FORBIDDEN);
use Apache2::RequestRec ();
use Apache2::RequestIO ();
use Apache2::Reload;
use Apache2::Log;
use APR::URI;
use APR::Table;
use APR::URI;
use APR::SockAddr;
use HTTP::Request;
use Apache2::RequestUtil ();
use LWP::UserAgent;
use Apache2::Connection;
use Apache::SSLLookup;
use IPC::Run qw(run);

use Vulture qw(&get_app $proto &read_conf &get_cookie &session);

use Data::Dumper;

sub REMOTE_ADDR { 1 };
sub SCRIPT { 20 };
sub Vulture_portail { 1 };

my %headers_vars = (
		    2 => 'SSL_CLIENT_I_DN',
		    3 => 'SSL_CLIENT_M_SERIAL',
		    4 => 'SSL_CLIENT_S_DN',
		    5 => 'SSL_CLIENT_V_START',
		    6 => 'SSL_CLIENT_V_END',
		    7 => 'SSL_CLIENT_S_DN_C',
		    8 => 'SSL_CLIENT_S_DN_ST',
		    9 => 'SSL_CLIENT_S_DN_Email',
		    10 => 'SSL_CLIENT_S_DN_L',
		    11 => 'SSL_CLIENT_S_DN_O',
		    12 => 'SSL_CLIENT_S_DN_OU',
		    13 => 'SSL_CLIENT_S_DN_CN',
		    14 => 'SSL_CLIENT_S_DN_T',
		    15 => 'SSL_CLIENT_S_DN_I',
		    16 => 'SSL_CLIENT_S_DN_G',
		    17 => 'SSL_CLIENT_S_DN_S',
		    18 => 'SSL_CLIENT_S_DN_D',
		    19 => 'SSL_CLIENT_S_DN_UID',
		   );

sub rewrite {
	my ($r, $line, $uri) = @_;

	my ($exp, $rule) = split (/=>/, $line);

	$rule =~ s/\s*//g;
	$exp =~ s/\s*//g;

	$line =~ /\[([A-Z0-9]+)\]/;
	my ($cond) = $1;
	return unless ($rule and $exp and ($$uri.($r->args ? "?".$r->args : "")) =~ /$exp/x);
	return if ($cond =~ /,NOCERT$/ and $r->ssl_lookup('SSL_CLIENT_M_SERIAL'));
	return if ($cond eq "H" or $cond eq "MH" or $cond eq "F" or $cond eq "UH" or $cond eq "L" or $cond eq "RH" or $cond eq "HL" or $cond eq "HP");

	$rule =~ s/\[$cond\]//;
	$cond =~ s/,NOCERT$//;

	if ($cond =~ /([0-9]+)/) {
		$r->status($1);
		return $1;
	}

	if ($$uri =~ /$exp/x) { # Load $1 $2
		$$uri = eval "\"$rule\"";
	}
	return $cond;
}


sub rewrite_uri { # Fonction de reécriture d'url pour étre valide depuis internet
   my ($r, $app, $uri, $real_post_url, $log) = @_;

	if ($uri !~ /^(http|https):\/\/(.*)/ ) {
		my $rewrite_uri2 = APR::URI->parse($r->pool, $real_post_url);
		my $path = $rewrite_uri2->path();
		if ($uri =~ /^\/(.*)/) {
			$rewrite_uri2->hostname($app->{'name'});
			$rewrite_uri2->path($uri);
		}
		else {
			$path =~ s/[^\/]+$/$uri/g;
			$rewrite_uri2->path($path);	
		}
	$uri = $rewrite_uri2->unparse;
   }
   my $rewrite_uri = APR::URI->parse($r->pool, $uri);
   $rewrite_uri->hostname($app->{'name'});
   $rewrite_uri->scheme('http');
   $rewrite_uri->scheme('https') if $r->is_https;
   $rewrite_uri->port($r->connection->local_addr->port);
   return $rewrite_uri->unparse;
} 

sub handler {
	my $r = Apache::SSLLookup->new(shift);

	my $uri = $r->uri;
	my $server;
	my $dbh = DBI->connect($r->dir_config('VultureDSN'));
	my $log = $r->server->log;

	my $vulture_portail = 0;
	my $vulture_portail_uri = 0;


	if ($r->unparsed_uri =~ /static\/(.*)/) {
		$log->debug("Serving $1");
		$r->filename("/var/www/vulture/conf/static/$1");
		return Apache2::Const::OK;
	}

	my $app = get_app($log, $r->hostname, $dbh, $r->dir_config('VultureID')) if ($r->unparsed_uri !~ /vulture_app/ and $r->unparsed_uri !~ /vulture_logout/);

	if ($app and $app->{up}) {
		my ($id) = get_cookie($r->headers_in->{Cookie}, 'vulture_app=([^;]*)') if ($app->{auth});
		my ($vulture_portail) = get_cookie($r->headers_in->{Cookie}, 'vulture_portail=([^;]*)');

		my %session;
		my %session_referer;
		session(\%session, $app->{timeout}, $id) if ($id);

		if ($r->unparsed_uri =~ /vultureportail=(.*)/) {
			my ($vulture_portail_uri) = $1;
		}

		#Si il y a quelque chose dans cette variable c'est qu'il faut repasser pas le ResponseHandler.pm
		if ($session{reponse}) {
			return Apache2::Const::OK;
		}
		if (($session{_session_id} and $session{post}) or !$app->{'auth'}) {
			$r->user($session{user});
			my $sth = $dbh->prepare("SELECT var, value, type FROM headers, app WHERE id_app='".$app->{id}."' AND app.id=id_app AND app.has_headers='t'");
			$sth->execute;
			my $fqdn = URI->new($app->{'url'});
			$r->headers_in->set("Host" => $fqdn->host());
			while (my ($var, $value, $type) = $sth->fetchrow) {
				$value = $r->connection->remote_ip if ($type == REMOTE_ADDR);
				$value = $r->ssl_lookup($headers_vars{$type}) if (exists $headers_vars{$type});
				if ($type == SCRIPT) {
					if ($session{header_script_value}) {
						$value = $session{header_script_value};
					}
					else {
						my ($in, $out);
						run [$value, $session{user}, $session{pass}], \$in, \$out;
						$value = $out;
						$session{header_script_value} = $out;
					}
				}
				if ($var eq "Vulture_portail") {
					session(\%session_referer,undef,$vulture_portail);
					$r->headers_out->add('Set-Cookie' => 'vulture_portail='.$session_referer{_session_id}.'; path=/; domain='.$r->hostname);
					$session_referer{hostname} = $r->hostname;
					$session_referer{url} = $uri;
					$vulture_portail = 1;
				} else {
					$r->headers_in->set($var => $value);
				}
			}

			if (
			    $session{posted}
			    or !$app->{'auth'}
			    or ($session{post}
				and $app->{'sso_forward_type'} and $app->{'sso_forward_type'} ne "sso_forward")
			   ) {

				if (my $proxy_rules = $app->{'rewrite'}) {
					$proxy_rules =~ s/\r//;
					foreach (split ("\n",$proxy_rules)) {
						if (my $cond = rewrite($r, $_, \$uri)) {
							if ($cond eq "R") {
								$r->status(200);
								$r->headers_out->set('Location' => $uri . ($r->args ? "?".$r->args : ""));
								return Apache2::Const::REDIRECT;
							}
							if ($cond ne "P") {
								return $r->status;
							}
							last;
						}
					}
				}
				if ($app->{'sso_forward_type'} and ($app->{'sso_forward_type'} eq "sso_forward_htaccess" or $app->{'sso_forward_type'} eq "sso_forward_autologon")) {
					$r->headers_in->set('Authorization' => $session{post});
				}
				if (!$session{url}) {
					my $sth = $dbh->prepare("SELECT url FROM app_lb WHERE id_app='".$app->{id}."' ORDER BY RANDOM() LIMIT 1");
					$sth->execute;
					if (my ($url) = $sth->fetchrow) {
						session(\%session, $app->{timeout}) if (!$id);
						$session{url} = $url;
						$r->err_headers_out->add('Set-Cookie' => 'vulture_app='.$session{_session_id}.'; path=/; domain='.$r->hostname);
					} else {
						$session{url} = $app->{url};
					}
				}
				$session{url} = $app->{url};
				if ($uri =~ /^(http|https|ftp):\/\//) {
					if ($vulture_portail) {
						$r->headers_in->set("Vulture_portail" => $session_referer{_session_id});
						$r->filename("proxy:".$uri);
					} else {
						$r->filename("proxy:".$uri);
					}
				} else {
					$r->filename("proxy:".$session{url}.$uri);
				}
				$r->handler('proxy-server');
				$r->proxyreq(2);
				return Apache2::Const::OK;
			}

			$r->headers_out->add('Set-Cookie' => 'vulture_app='.$session{_session_id}.'; path=/; domain='.$r->hostname);
			$session{posted} = 1;

                       if ($app->{post_url}) { #Si il n'y a pas d'url pour le post pas besoin d'en faire un

			       my $ua = LWP::UserAgent->new;
			       # use a proxy if proxyremote is enabled

			       if ( $app->{remoteproxy} ne '') {
				       $ua->proxy(['http', 'https'], $app->{remoteproxy});
			       }

			       my $request = HTTP::Request->new('GET', $session{post_url} ? $session{post_url} : $app->{post_url});

			       $request->push_header('User-Agent' => $r->headers_in->{'User-Agent'});
			       $request->push_header('Host' => $r->headers_in->{'Host'});

			       if (defined($r->headers_in->{'Max-Forwards'})) {
				       $request->push_header('Max-Forwards' => $r->headers_in->{'Max-Forwards'} - 1);
			       } else {
				       $request->push_header('Max-Forwards' => '10');
			       }
			       if (defined($r->headers_in->{'X-Forwarded-For'})) {
				       $request->push_header('X-Forwarded-For' => $r->headers_in->{'X-Forwarded-For'}.", ".$r->connection->remote_ip);
			       } else {
				       $request->push_header('X-Forwarded-For' => $r->connection->remote_ip);
			       }

			       $request->push_header('X-Forwarded-Host' => $r->hostname());
			       $request->push_header('X-Forwarded-Server' => $r->hostname());

			       my $response = $ua->request($request);
			       my $cc = $response->header('Set-Cookie');

			       foreach ($response->headers->header('Set-Cookie')) {
				       my @list=split(/;/,$_);
				       my $cook;
				       foreach (@list) {
					       if (/([^,; ]+)=([^;]+)/) {
                                               my $var=$1;
                                               my $data=$2;
                                               if (($var =~ /^[Dd][Oo][Mm][Aa][Ii][Nn]/) and ($data =~ /^\./)) { #Si la variable contient domain et que la valeur commence par .
                                                       $r->hostname =~ /^\w*(.*)/;
                                                       $cook .= $var."=".$1."; ";
                                               }
                                               elsif (($var =~ /^[Dd][Oo][Mm][Aa][Ii][Nn]/) and ($data =~ /^\w\./)) { #Si la variable contient domain et que la valeur commence par un mot
                                                       $cook .= $var."=".$r->hostname."; ";
                                               }
                                               else {
                                                       $cook .= $var."=".$data."; ";
                                               }
                                       }
				       }
				       $r->headers_out->add('Set-Cookie' => $cook);
			       }
			       my %cookies;
			       while ($cc and $cc =~ s/([^,; ]+)=([^,; ]+)//) {
				       $cookies{$1} = $2;
			       }
			       my $cookie;
			       foreach my $k (keys %cookies) {
				       if ($k ne "Expires" and $k ne "Path") {
					       $cookie .= $k . "=". $cookies{$k} . "; ";
				       }
			       }


			       # modification pour prendre en compte l'url relative à l'adresse récupéré depuis un serveur LDAP ou radius. Pour cela, on s'appuie sur l'url de session. On vérifie l'attribut contenant l'url de propagation pour connaître sa forme.
			       # Si l'url est de la forme http....... alors on prendre cette url telle quelle.
			       #sinon on concatène l'url et session et cet attribut.
			       # On nettoie tout de même ces deux variables, a savoir, on enlève tout / inutile.Cela permettra une meileuur souplesse sur les données rentrées par l'utilisateur (notamment au niveau de LDAP et raidus).
			       my $real_post_url;

			       if ($app->{post_url} =~ /^(http)/) {
				       $real_post_url=$app->{post_url};
			       } else {
				       my $url_temp = $session{url};
				       $url_temp =~ s/(\/)*$//;
				       $real_post_url=$url_temp."/".$app->{post_url};
			       }
			       $request = HTTP::Request->new('POST',  $session{post_url} ? $session{post_url} : $app->{post_url}, undef, $session{post});
			       $request->push_header('Content-Type' => 'application/x-www-form-urlencoded');
			       $request->push_header('Cookie' => $cookie);
			       $request->push_header('User-Agent' => $r->headers_in->{'User-Agent'});
			       $request->push_header('Host' => $r->headers_in->{'Host'});
			       if (defined($r->headers_in->{'Max-Forwards'})) {
				       $request->push_header('Max-Forwards' => $r->headers_in->{'Max-Forwards'} - 1);
			       } else {
				       $request->push_header('Max-Forwards' => '10');
			       }

			       if (defined($r->headers_in->{'X-Forwarded-For'})) {
				       $request->push_header('X-Forwarded-For' => $r->headers_in->{'X-Forwarded-For'}.", ".$r->connection->remote_ip);
			       } else {
				       $request->push_header('X-Forwarded-For' => $r->connection->remote_ip);
			       }

			       $request->push_header('X-Forwarded-Host' => $r->hostname());
			       $request->push_header('X-Forwarded-Server' => $r->hostname());
			       $response = $ua->request($request);

			       if ($response->headers->header('Set-Cookie')) {
#				       foreach ($response->headers->header('Set-Cookie')) {
#					       my @list=split(/;/,$_);
#					       my $cook;
#					       foreach (@list) {
#						       if (/([^,; ]+)=([^;]+)/) {
#							       my $var=$1;
#							       my $data=$2;
#							       if (($var =~ /^[Dd][Oo][Mm][Aa][Ii][Nn]/) and ($data =~ /^\./)) { #Si la variable contient domain et que la valeur commence par .
#								       $r->hostname =~ /^\w*(.*)/;
#								       $cook .= $var."=".$1."; ";
#							       }
#							       elsif (($var =~ /^[Dd][Oo][Mm][Aa][Ii][Nn]/) and ($data =~ /^\w\./)) { #Si la variable contient domain et que la valeur commence par un mot
#								       $cook .= $var."=".$r->hostname."; ";
#							       }
#							       else {
#								       $cook .= $var."=".$data."; ";
#							       }
#						       }
#					       }
#					       $r->headers_out->add('Set-Cookie' => $cook);				       
#				       }
				       foreach ($response->headers->header('Set-Cookie')) {
					       if (/([^,; ]+)=([^,; ]+)/) {
						       $r->headers_out->add('Set-Cookie' => $1."=".$2."; domain=".$r->hostname."; path=/");
					       }
				       }
			       }
			       if ($response->headers->header('refresh') and $response->headers->header('refresh') =~ /URL=(.*)/) {
				       $r->headers_out->add('Location' => rewrite_uri($r,$app,$1,$real_post_url,$log));
			       }
			       if ($response->code =~ /^30(.*)/ ) { #On gère les redirections de type 30x
				       $r->headers_out->add('Location' => rewrite_uri($r,$app,$response->headers->header('location'),$real_post_url,$log));
			       } else {
				       $session{urlpost}= rewrite_uri($r,$app,$real_post_url,$real_post_url,$log); #On récupère l'url du post vu de l'exterieur pour le ResponseHandler.pm
				       $session{reponse}=$response;
			       }
			       $log->debug("POST=".$session{post}."[".$real_post_url."]");
		       }
		}
	}
	$r->status(Apache2::Const::REDIRECT);
	return Apache2::Const::OK;
}

1;

Reply via email to