| line |
stmt |
bran |
cond |
sub |
pod |
time |
code |
|
1
|
|
|
|
|
|
|
##@file |
|
2
|
|
|
|
|
|
|
# Zimbra preauthentication |
|
3
|
|
|
|
|
|
|
|
|
4
|
|
|
|
|
|
|
##@class |
|
5
|
|
|
|
|
|
|
# Zimbra preauthentication |
|
6
|
|
|
|
|
|
|
# |
|
7
|
|
|
|
|
|
|
# It will build Zimbra preauth URL |
|
8
|
|
|
|
|
|
|
|
|
9
|
|
|
|
|
|
|
# This specific handler is intended to be called directly by Apache |
|
10
|
|
|
|
|
|
|
|
|
11
|
|
|
|
|
|
|
package Lemonldap::NG::Handler::Specific::ZimbraPreAuth; |
|
12
|
|
|
|
|
|
|
|
|
13
|
1
|
|
|
1
|
|
6891
|
use strict; |
|
|
1
|
|
|
|
|
2
|
|
|
|
1
|
|
|
|
|
34
|
|
|
14
|
1
|
|
|
1
|
|
470
|
use Lemonldap::NG::Handler::SharedConf qw(:all); |
|
|
0
|
|
|
|
|
|
|
|
|
0
|
|
|
|
|
|
|
|
15
|
|
|
|
|
|
|
use base qw(Lemonldap::NG::Handler::SharedConf); |
|
16
|
|
|
|
|
|
|
use Digest::HMAC_SHA1 qw(hmac_sha1 hmac_sha1_hex); |
|
17
|
|
|
|
|
|
|
use Lemonldap::NG::Handler::Main::Headers; |
|
18
|
|
|
|
|
|
|
use Lemonldap::NG::Handler::Main::Logger; |
|
19
|
|
|
|
|
|
|
|
|
20
|
|
|
|
|
|
|
our $VERSION = '1.0.0'; |
|
21
|
|
|
|
|
|
|
|
|
22
|
|
|
|
|
|
|
# Shared variables |
|
23
|
|
|
|
|
|
|
our ( $zimbraPreAuthKey, $zimbraAccountKey, $zimbraBy, $zimbraUrl, |
|
24
|
|
|
|
|
|
|
$zimbraSsoUrl, $timeout ); |
|
25
|
|
|
|
|
|
|
|
|
26
|
|
|
|
|
|
|
## @imethod protected void globalInit(hashRef args) |
|
27
|
|
|
|
|
|
|
# Overload globalInit to launch this class defaultValuesInit |
|
28
|
|
|
|
|
|
|
# @param $args reference to the configuration hash |
|
29
|
|
|
|
|
|
|
sub globalInit { |
|
30
|
|
|
|
|
|
|
my $class = shift; |
|
31
|
|
|
|
|
|
|
__PACKAGE__->defaultValuesInit(@_); |
|
32
|
|
|
|
|
|
|
$class->SUPER::globalInit(@_); |
|
33
|
|
|
|
|
|
|
} |
|
34
|
|
|
|
|
|
|
|
|
35
|
|
|
|
|
|
|
## @imethod protected void defaultValuesInit(hashRef args) |
|
36
|
|
|
|
|
|
|
# Overload defaultValuesInit |
|
37
|
|
|
|
|
|
|
# @param $args reference to the configuration hash |
|
38
|
|
|
|
|
|
|
sub defaultValuesInit { |
|
39
|
|
|
|
|
|
|
my ( $class, $args ) = splice @_; |
|
40
|
|
|
|
|
|
|
|
|
41
|
|
|
|
|
|
|
# Catch Zimbra parameters |
|
42
|
|
|
|
|
|
|
$zimbraPreAuthKey = $args->{'zimbraPreAuthKey'} || $zimbraPreAuthKey; |
|
43
|
|
|
|
|
|
|
$zimbraAccountKey = |
|
44
|
|
|
|
|
|
|
$args->{'zimbraAccountKey'} |
|
45
|
|
|
|
|
|
|
|| $zimbraAccountKey |
|
46
|
|
|
|
|
|
|
|| 'uid'; |
|
47
|
|
|
|
|
|
|
$zimbraBy = $args->{'zimbraBy'} || $zimbraBy || 'id'; |
|
48
|
|
|
|
|
|
|
$zimbraUrl = $args->{'zimbraUrl'} || $zimbraUrl || '/service/preauth'; |
|
49
|
|
|
|
|
|
|
$zimbraSsoUrl = $args->{'zimbraSsoUrl'} || $zimbraSsoUrl || '^/zimbrasso$'; |
|
50
|
|
|
|
|
|
|
$timeout = $args->{'timeout'} || $timeout || '0'; |
|
51
|
|
|
|
|
|
|
|
|
52
|
|
|
|
|
|
|
# Display found values in debug mode |
|
53
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( |
|
54
|
|
|
|
|
|
|
"zimbraPreAuthKey: $zimbraPreAuthKey", 'debug' ); |
|
55
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( |
|
56
|
|
|
|
|
|
|
"zimbraAccountKey: $zimbraAccountKey", 'debug' ); |
|
57
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "zimbraBy: $zimbraBy", |
|
58
|
|
|
|
|
|
|
'debug' ); |
|
59
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "zimbraUrl: $zimbraUrl", |
|
60
|
|
|
|
|
|
|
'debug' ); |
|
61
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "zimbraSsoUrl: $zimbraSsoUrl", |
|
62
|
|
|
|
|
|
|
'debug' ); |
|
63
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( "timeout: $timeout", 'debug' ); |
|
64
|
|
|
|
|
|
|
|
|
65
|
|
|
|
|
|
|
# Delete Zimbra parameters |
|
66
|
|
|
|
|
|
|
delete $args->{'zimbraPreAuthKey'}; |
|
67
|
|
|
|
|
|
|
delete $args->{'zimbraAccountKey'}; |
|
68
|
|
|
|
|
|
|
delete $args->{'zimbraBy'}; |
|
69
|
|
|
|
|
|
|
delete $args->{'zimbraUrl'}; |
|
70
|
|
|
|
|
|
|
delete $args->{'zimbraSsoUrl'}; |
|
71
|
|
|
|
|
|
|
delete $args->{'timeout'}; |
|
72
|
|
|
|
|
|
|
|
|
73
|
|
|
|
|
|
|
# Call main subroutine |
|
74
|
|
|
|
|
|
|
return $class->SUPER::defaultValuesInit($args); |
|
75
|
|
|
|
|
|
|
} |
|
76
|
|
|
|
|
|
|
|
|
77
|
|
|
|
|
|
|
## @rmethod Apache2::Const run(Apache2::RequestRec r) |
|
78
|
|
|
|
|
|
|
# Overload main run method |
|
79
|
|
|
|
|
|
|
# @param r Current request |
|
80
|
|
|
|
|
|
|
# @return Apache2::Const value (OK, FORBIDDEN, REDIRECT or SERVER_ERROR) |
|
81
|
|
|
|
|
|
|
sub run { |
|
82
|
|
|
|
|
|
|
my $class = shift; |
|
83
|
|
|
|
|
|
|
my $r = $_[0]; |
|
84
|
|
|
|
|
|
|
my $ret = $class->SUPER::run(@_); |
|
85
|
|
|
|
|
|
|
|
|
86
|
|
|
|
|
|
|
# Continue only if user is authorized |
|
87
|
|
|
|
|
|
|
return $ret unless ( $ret == OK ); |
|
88
|
|
|
|
|
|
|
|
|
89
|
|
|
|
|
|
|
# Get current URI |
|
90
|
|
|
|
|
|
|
my $args = $r->args; |
|
91
|
|
|
|
|
|
|
my $uri = $r->uri . ( $args ? "?$args" : "" ); |
|
92
|
|
|
|
|
|
|
|
|
93
|
|
|
|
|
|
|
# Return if we are not on a Zimbra SSO URI |
|
94
|
|
|
|
|
|
|
return OK unless ( $uri =~ $zimbraSsoUrl ); |
|
95
|
|
|
|
|
|
|
|
|
96
|
|
|
|
|
|
|
# Check mandatory parameters |
|
97
|
|
|
|
|
|
|
return $class->abort("No Zimbra preauth key configured") |
|
98
|
|
|
|
|
|
|
unless ($zimbraPreAuthKey); |
|
99
|
|
|
|
|
|
|
|
|
100
|
|
|
|
|
|
|
# Build URL |
|
101
|
|
|
|
|
|
|
my $zimbra_url = $class->_buildZimbraPreAuthUrl( |
|
102
|
|
|
|
|
|
|
$zimbraPreAuthKey, $zimbraUrl, |
|
103
|
|
|
|
|
|
|
$datas->{$zimbraAccountKey}, $zimbraBy |
|
104
|
|
|
|
|
|
|
); |
|
105
|
|
|
|
|
|
|
|
|
106
|
|
|
|
|
|
|
# Header location |
|
107
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Headers->lmSetHeaderOut( $r, |
|
108
|
|
|
|
|
|
|
'Location' => $zimbra_url ); |
|
109
|
|
|
|
|
|
|
|
|
110
|
|
|
|
|
|
|
# Return REDIRECT |
|
111
|
|
|
|
|
|
|
return REDIRECT; |
|
112
|
|
|
|
|
|
|
} |
|
113
|
|
|
|
|
|
|
|
|
114
|
|
|
|
|
|
|
## @method private string _buildZimbraPreAuthUrl(string key, string url, string account, string by) |
|
115
|
|
|
|
|
|
|
# Build Zimbra PreAuth URL |
|
116
|
|
|
|
|
|
|
# @param key PreAuthKey |
|
117
|
|
|
|
|
|
|
# @param url URL |
|
118
|
|
|
|
|
|
|
# @param account User account |
|
119
|
|
|
|
|
|
|
# @param by Account type |
|
120
|
|
|
|
|
|
|
# @return Zimbra PreAuth URL |
|
121
|
|
|
|
|
|
|
sub _buildZimbraPreAuthUrl { |
|
122
|
|
|
|
|
|
|
my ( $class, $key, $url, $account, $by ) = splice @_; |
|
123
|
|
|
|
|
|
|
|
|
124
|
|
|
|
|
|
|
# Expiration time is calculated with _utime and timeout |
|
125
|
|
|
|
|
|
|
my $expires = $timeout ? ( $datas->{_utime} + $timeout ) * 1000 : $timeout; |
|
126
|
|
|
|
|
|
|
|
|
127
|
|
|
|
|
|
|
# Timestamp |
|
128
|
|
|
|
|
|
|
my $timestamp = time() * 1000; |
|
129
|
|
|
|
|
|
|
|
|
130
|
|
|
|
|
|
|
# Compute preauth value |
|
131
|
|
|
|
|
|
|
my $computed_value = |
|
132
|
|
|
|
|
|
|
hmac_sha1_hex( "$account|$by|$expires|$timestamp", $key ); |
|
133
|
|
|
|
|
|
|
|
|
134
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( |
|
135
|
|
|
|
|
|
|
"Compute value $account|$by|$expires|$timestamp into $computed_value", |
|
136
|
|
|
|
|
|
|
'debug' ); |
|
137
|
|
|
|
|
|
|
|
|
138
|
|
|
|
|
|
|
# Build PreAuth URL |
|
139
|
|
|
|
|
|
|
my $zimbra_url = |
|
140
|
|
|
|
|
|
|
"$url?account=$account&by=$by×tamp=$timestamp&expires=$expires&preauth=$computed_value"; |
|
141
|
|
|
|
|
|
|
|
|
142
|
|
|
|
|
|
|
Lemonldap::NG::Handler::Main::Logger->lmLog( |
|
143
|
|
|
|
|
|
|
"Build Zimbra URL: $zimbra_url", 'debug' ); |
|
144
|
|
|
|
|
|
|
|
|
145
|
|
|
|
|
|
|
return $zimbra_url; |
|
146
|
|
|
|
|
|
|
} |
|
147
|
|
|
|
|
|
|
|
|
148
|
|
|
|
|
|
|
__PACKAGE__->init( {} ); |
|
149
|
|
|
|
|
|
|
|
|
150
|
|
|
|
|
|
|
1; |
|
151
|
|
|
|
|
|
|
|
|
152
|
|
|
|
|
|
|
__END__ |