1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
|
#!/usr/bin/perl -wT
# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.
#
# This Source Code Form is "Incompatible With Secondary Licenses", as
# defined by the Mozilla Public License, v. 2.0.
use 5.10.1;
use strict;
use warnings;
use lib qw(. lib);
use Bugzilla;
use Bugzilla::Constants;
use Bugzilla::Error;
use Bugzilla::Hook;
use Bugzilla::Util qw(trick_taint);
use Bugzilla::Token qw(issue_auth_delegation_token check_auth_delegation_token);
use Bugzilla::Mailer qw(MessageToMTA);
use URI;
use URI::QueryParam;
use Digest::SHA qw(sha256_hex);
use LWP::UserAgent ();
use JSON qw(decode_json encode_json);
Bugzilla->login(LOGIN_REQUIRED);
ThrowUserError('auth_delegation_disabled') unless Bugzilla->params->{auth_delegation};
my $cgi = Bugzilla->cgi;
my $template = Bugzilla->template;
my $user = Bugzilla->user;
my $callback = $cgi->param('callback') or ThrowUserError("auth_delegation_missing_callback");
my $description = $cgi->param('description') or ThrowUserError("auth_delegation_missing_description");
trick_taint($callback);
trick_taint($description);
my $callback_uri = URI->new($callback);
my $callback_base = $callback_uri->clone;
$callback_base->query(undef);
my $skip_confirmation = 0;
my %args = ( skip_confirmation => \$skip_confirmation,
callback => $callback_uri,
description => $description,
callback_base => $callback_base );
Bugzilla::Hook::process('auth_delegation_confirm', \%args);
my $confirmed = lc($cgi->request_method) eq 'post' && $cgi->param('confirm');
if ($confirmed || $skip_confirmation) {
my $token = $cgi->param('token');
unless ($skip_confirmation) {
ThrowUserError("auth_delegation_missing_token") unless $token;
trick_taint($token);
unless (check_auth_delegation_token($token, $callback)) {
ThrowUserError('auth_delegation_invalid_token',
{ token => $token, callback => $callback });
}
}
my $app_id = sha256_hex($callback_uri, $description);
my $keys = Bugzilla::User::APIKey->match({
user_id => $user->id,
app_id => $app_id,
revoked => 0,
});
my $api_key;
if (@$keys) {
$api_key = $keys->[0];
}
else {
$api_key = Bugzilla::User::APIKey->create({
user_id => $user->id,
description => $description,
app_id => $app_id,
});
my $template = Bugzilla->template_inner($user->setting('lang'));
my $vars = { user => $user, new_key => $api_key };
my $message;
$template->process('email/new-api-key.txt.tmpl', $vars, \$message)
or ThrowTemplateError($template->error());
MessageToMTA($message);
}
my $ua = LWP::UserAgent->new();
$ua->timeout(2);
$ua->protocols_allowed(['http', 'https']);
# If the URL of the proxy is given, use it, else get this information
# from the environment variable.
if (my $proxy_url = Bugzilla->params->{'proxy_url'}) {
$ua->proxy(['http', 'https'], $proxy_url);
}
else {
$ua->env_proxy;
}
my $content = encode_json({ client_api_key => $api_key->api_key,
client_api_login => $user->login });
my $resp = $ua->post($callback_uri,
'Content-Type' => 'application/json',
Content => $content);
if ($resp->code == 200) {
$callback_uri->query_param(client_api_login => $user->login);
eval {
my $data = decode_json($resp->content);
$callback_uri->query_param(callback_result => $data->{result});
};
ThrowUserError('auth_delegation_json_error', { json_text => $resp->content }) if $@;
print $cgi->redirect($callback_uri);
}
else {
ThrowUserError('auth_delegation_post_error', { code => $resp->code });
}
}
else {
$args{token} = issue_auth_delegation_token($callback);
print $cgi->header();
$template->process("account/auth/delegation.html.tmpl", \%args)
or ThrowTemplateError($template->error());
}
|