Passed
Push — master ( c08bf0...59250a )
by Kevin
14:24 queued 07:13
created

account_ownership_form()   B

Complexity

Conditions 6
Paths 17

Size

Total Lines 46
Code Lines 24

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 6
eloc 24
c 1
b 0
f 0
nc 17
nop 1
dl 0
loc 46
rs 8.9137
1
<?php
2
// This file is part of BOINC.
3
// http://boinc.berkeley.edu
4
// Copyright (C) 2008 University of California
5
//
6
// BOINC is free software; you can redistribute it and/or modify it
7
// under the terms of the GNU Lesser General Public License
8
// as published by the Free Software Foundation,
9
// either version 3 of the License, or (at your option) any later version.
10
//
11
// BOINC is distributed in the hope that it will be useful,
12
// but WITHOUT ANY WARRANTY; without even the implied warranty of
13
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
// See the GNU Lesser General Public License for more details.
15
//
16
// You should have received a copy of the GNU Lesser General Public License
17
// along with BOINC.  If not, see <http://www.gnu.org/licenses/>.
18
19
require_once("../inc/boinc_db.inc");
20
require_once("../inc/user.inc");
21
require_once("../inc/util.inc");
22
require_once("../inc/countries.inc");
23
require_once('../inc/recaptchalib.php');
24
25
check_get_args(array("tnow", "ttok"));
26
27
$user = get_logged_in_user();
28
check_tokens($user->authenticator);
29
30
function account_ownership_action($user) {
31
  // POST request - the user has submitted the form.
32
  page_head(tra("Proof of account ownership results"), null, null, null, boinc_recaptcha_get_head_extra());
33
34
  global $recaptcha_private_key;
35
  if ($recaptcha_private_key) {
36
      // Recaptcha is enabled on the BOINC server
37
      if (!boinc_recaptcha_isValidated($recaptcha_private_key)) {
38
          // The user failed to solve the recaptcha prompt - redirect them to an error message!
39
          error_page(
40
              tra("Your reCAPTCHA response was not correct. Please try again.")
41
          );
42
      }
43
  }
44
45
  // Input is passed in from the openssl_sign_form
46
  $user_data = htmlentities(post_str("user_data", true), ENT_QUOTES, "UTF-8"); // Convert special characters to html equivelant
47
48
  if ((strlen($user_data) > 0) && (strlen($user_data) <= 4096)) {
49
      require_once("../inc/account_ownership.inc");
50
      // Check that the private key file exists where specified. If not, redirect to error page.
51
      if (!file_exists($account_ownership_private_key_file_path)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $account_ownership_private_key_file_path seems to be never defined.
Loading history...
52
          error_page(tra("The proof of account ownership feature is not set up properly. Contact the project administrator to resolve the issue."));
53
      }
54
55
      // Check that the public key file exists where specified. If not, redirect to error page.
56
      if (!file_exists($account_ownership_public_key_file_path)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $account_ownership_public_key_file_path seems to be never defined.
Loading history...
57
          error_page(tra("The proof of account ownership feature is not set up properly. Contact the project administrator to resolve the issue."));
58
      }
59
60
      $privkey = fopen($account_ownership_private_key_file_path, "r"); // Opening private key file
61
      if (!isset($privkey) || empty($privkey)) {
62
        error_page(tra("The proof of account ownership feature is not set up properly. Contact the project administrator to resolve the issue."));
63
      }
64
      $privkey_contents = fread($privkey, 8192); // Reading contents of private key into var
65
      fclose($privkey); // Closing private key file
66
67
      $userid = $user->id; // Retrieving the user's UserId
68
      $message_data = "$userid $user_data"; // Create the message which will be signed.
69
70
      $private_key_pem = openssl_pkey_get_private($privkey_contents); // Loading the private key into memory
71
      openssl_sign($message_data, $signature, $private_key_pem, OPENSSL_ALGO_SHA512); // Compute signature using SHA512
72
      openssl_free_key($private_key_pem); // Free the private key from memory for additional security
0 ignored issues
show
Bug introduced by
It seems like $private_key_pem can also be of type false; however, parameter $key_identifier of openssl_free_key() does only seem to accept resource, maybe add an additional type check? ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

72
      openssl_free_key(/** @scrutinizer ignore-type */ $private_key_pem); // Free the private key from memory for additional security
Loading history...
73
74
      $pubkey = fopen($account_ownership_public_key_file_path, "r"); // Open public key file
75
      if ((!isset($pubkey)) || empty($pubkey)) {
76
        error_page(tra("The proof of account ownership feature is not set up properly. Contact the project administrator to resolve the issue."));
77
      }
78
      $pubkey_contents = fread($pubkey, 8192); // Read contents to var
79
      fclose($pubkey); // Close pub key file
80
81
      $base64_sig = base64_encode($signature); // Base64 encode the generated signature to enable safe output to text file.
82
      $decoded_sig = base64_decode($base64_sig); // Decode base64 sig for use in sig_verification
83
      $pubkeyid = openssl_pkey_get_public($pubkey_contents); // fetch public key into memory
84
      $sig_verification = openssl_verify($message_data, $decoded_sig, $pubkeyid, OPENSSL_ALGO_SHA512); // Verify that the generated signature against the original data, using the public key.
85
      openssl_free_key($pubkeyid); // Free the public key from memory
86
87
      // Check if signature was successfully validated
88
      if ($sig_verification == 1) {
89
          $url_tokens = url_tokens($user->authenticator);
90
          // The generated signature has been successfully verified using the public key.
91
          global $master_url; // Define global master_url variable for use in output
92
          echo "<p>Do not share this information with anyone other than the external system which has requested this proof of account ownership.</p>";
93
          echo "<textarea rows='13' cols='50' id='result_textbox'><account_ownership_verification>\n<master_url>$master_url</master_url>\n<msg>$message_data</msg>\n<signature>$base64_sig</signature>\n</account_ownership_verification></textarea>";
94
          echo "<br/><br/><button class='btn btn-success' onclick='copy_result_textbox()'>Copy text</button>";
95
          echo "<a href='account_ownership.php?$url_tokens'><button class='btn btn-default'>Go back</button></a>";
96
          echo '<script type="text/javascript">';
97
          echo 'function copy_result_textbox() {
98
                var target_textbox = document.getElementById("result_textbox");
99
                target_textbox.select();
100
                document.execCommand("copy");
101
                alert("Copied to clipboard");
102
              }';
103
          echo '</script>';
104
          page_tail();
105
106
      } elseif ($sig_verification == 0) {
107
          // The generated signature has not been verified. The private/public keys do not match.
108
          error_page(tra("Signature verification failed. Contact the project administrator to resolve the issue."));
109
      } else {
110
          // Something has gone wrong & an error has occurred.
111
          error_page(tra("An error occured during the signature verification. Contact the project administrator to resolve the issue."));
112
      }
113
  } else {
114
      // User data input invalid
115
      error_page(tra("Invalid input. User input must have a length > 0 and < 4096. <form><input type='button' value='Go back!'' onclick='history.back()'></form>"));
116
  }
117
}
118
119
function account_ownership_form($user) {
120
  // GET request - the user has navigated to the page.
121
  page_head(tra("Generate proof of account ownership"), null, null, null, boinc_recaptcha_get_head_extra());
122
123
  if ($user) { // Verify the user is logged in
124
      require_once("../inc/account_ownership.inc");
125
126
      if (!file_exists($account_ownership_private_key_file_path)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $account_ownership_private_key_file_path seems to be never defined.
Loading history...
127
          // Check that the private key file exists where specified. If not, redirect to error page.
128
          error_page(tra("The proof of account ownership feature is not set up properly. Contact the project administrator to resolve the issue."));
129
      }
130
131
      if (!file_exists($account_ownership_public_key_file_path)) {
0 ignored issues
show
Comprehensibility Best Practice introduced by
The variable $account_ownership_public_key_file_path seems to be never defined.
Loading history...
132
          // Check that the public key file exists where specified. If not, redirect to error page.
133
          error_page(tra("The proof of account ownership feature is not set up properly. Contact the project administrator to resolve the issue."));
134
      }
135
136
      echo "<p>This tool is designed to create a proof of account ownership for external systems.</p>";
137
138
      global $recaptcha_public_key;
139
      if ($recaptcha_public_key) {
140
          // Recaptcha configured
141
          echo "<p>Enter a message with length less than 4096 characters into the input textbox below, solve the captcha then click the 'Generate' button.</p>";
142
      } else {
143
          // Recaptcha not configured
144
          echo "<p>Enter a message with length less than 4096 characters into the input textbox below then click the 'Generate' button.</p>";
145
      }
146
      echo "<p>A textbox will then appear which contains your proof of account ownership.";
147
      echo "<form method=post action=account_ownership.php>";
148
149
      echo form_tokens($user->authenticator);
150
      echo "<textarea rows='4' cols='50' name=user_data type=text size=20 placeholder='Enter text'></textarea><br/><br/>";
151
152
      if ($recaptcha_public_key) {
153
          // Trigger recaptcha!
154
          form_general("", boinc_recaptcha_get_html($recaptcha_public_key));
155
      }
156
157
      echo "<input class=\"btn btn-success\" type=submit value='".tra("Generate")."'>";
158
      echo "</form><br/><hr/>";
159
  } else {
160
      // The user is not logged in!
161
      echo "<p>You need to be logged in to use this functionality.</p>";
162
  }
163
164
  page_tail();
165
}
166
167
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
168
    account_ownership_action($user);
169
} else {
170
    account_ownership_form($user);
171
}
172
173
?>
174