PluginProbe ʕ •ᴥ•ʔ
CloudSecure WP Security / 1.3.22
CloudSecure WP Security v1.3.22
1.4.10 1.4.9 trunk 0.9.0 1.0.2 1.1.0 1.1.1 1.1.2 1.1.3 1.2.0 1.2.1 1.2.2 1.2.3 1.2.4 1.2.5 1.2.6 1.2.7 1.3.1 1.3.10 1.3.11 1.3.12 1.3.13 1.3.14 1.3.15 1.3.16 1.3.17 1.3.18 1.3.19 1.3.2 1.3.20 1.3.21 1.3.22 1.3.23 1.3.24 1.3.3 1.3.4 1.3.5 1.3.6 1.3.7 1.3.8 1.3.9 1.4.0 1.4.1 1.4.2 1.4.3 1.4.4 1.4.5 1.4.6 1.4.7 1.4.8
cloudsecure-wp-security / modules / admin / two-factor-authentication-registration.php
cloudsecure-wp-security / modules / admin Last commit date
captcha.php 1 year ago common.php 1 year ago dashboard.php 1 year ago disable-access-system-file.php 7 months ago disable-author-query.php 1 year ago disable-login.php 1 year ago disable-restapi.php 1 year ago disable-xmlrpc.php 1 year ago login-log-table.php 1 year ago login-log.php 1 year ago login-notification.php 1 year ago rename-login-page.php 1 year ago restrict-admin-page.php 1 year ago server-error-notification.php 1 year ago server-error-table.php 1 year ago two-factor-authentication-registration.php 2 years ago two-factor-authentication.php 1 year ago unify-messages.php 1 year ago update-notice.php 1 year ago waf-table.php 1 year ago waf.php 7 months ago
two-factor-authentication-registration.php
201 lines
1 <?php
2
3 if ( ! defined( 'ABSPATH' ) ) {
4 exit;
5 }
6
7 class CloudSecureWP_Admin_Two_Factor_Authentication_Registration extends CloudSecureWP_Admin_Common {
8 private $two_factor_authentication;
9 /**
10 * 管理画面にレンダリングするキー
11 *
12 * @var string
13 */
14 private $default_key;
15
16 function __construct( array $info, CloudSecureWP_Two_Factor_Authentication $two_factor_authentication ) {
17 parent::__construct( $info );
18 $this->two_factor_authentication = $two_factor_authentication;
19 $this->prepare_view_data();
20 $this->render();
21 }
22
23 /**
24 * 画面表示用のデータを準備
25 */
26 public function prepare_view_data(): void {
27 $this->default_key = get_user_option( 'cloudsecurewp_two_factor_authentication_secret' );
28 if ( ! empty( $_POST ) && check_admin_referer( $this->two_factor_authentication->get_feature_key() . '_csrf' ) ) {
29 if ( ! empty( $_POST['key'] ) ) {
30 $this->default_key = sanitize_text_field( $_POST['key'] );
31 }
32 if ( empty( $_POST['key'] ) ) {
33 $this->errors[] = 'セットアップキーを保存できませんでした。<br />セットアップキーを生成してください。';
34
35 return;
36 }
37 if ( empty( $_POST['google_authenticator_code'] ) ) {
38 $this->errors[] = 'セットアップキーを保存できませんでした。<br />QRコードをGoogle Authenticator アプリケーションでスキャンし、認証コードを�
39 �力してください。';
40
41 return;
42 }
43 $key = sanitize_text_field( $_POST['key'] );
44 $google_authenticator_code = sanitize_text_field( $_POST['google_authenticator_code'] );
45 if ( CloudSecureWP_Time_Based_One_Time_Password::verify_code( $key, $google_authenticator_code, 2 ) ) {
46 update_user_option( get_current_user_id(), 'cloudsecurewp_two_factor_authentication_secret', $key );
47 $this->messages[] = 'セットアップキーを保存しました。';
48 } else {
49 $this->errors[] = 'セットアップキーを保存できませんでした。<br />認証コードが間違っています。';
50 }
51 }
52 }
53
54 /**
55 * ディスクリプション
56 */
57 protected function admin_description(): void {
58 ?>
59 <div class="title-block mb-12">
60 <h1 class="title-block-title">デバイス登録 - 2段階認証</h1>
61 <p class="title-block-small-text">この機能のマニュアルは<a class="title-block-link" target="_blank"
62 href="https://wpplugin.cloudsecure.ne.jp/cloudsecure_wp_security/two_factor_authentication.php">こちら</a>
63 </p>
64 </div>
65 <div class="title-bottom-text">
66 2段階認証機能をアクティブにするには、セットアップキーを生成し、<a class="title-block-link" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank">Google Authenticator</a>  アプリケーションでQRコードを読み込んでください。<br />
67 QRコードを読み込めない場合、<a class="title-block-link" href="https://play.google.com/store/apps/details?id=com.google.android.apps.authenticator2" target="_blank">Google Authenticator</a>  アプリケーションにセットアップキーを�
68 �力してください。
69 </div>
70 <?php
71 }
72
73 /**
74 * ページコンテンツ
75 */
76 protected function page(): void {
77 ?>
78 <form method="post">
79 <div class="box">
80 <div class="box-bottom">
81 <div class="box-row flex-start">
82 <div class="box-row-title not-label pt-12">
83 <label for="key">セットアップキー</label>
84 </div>
85 <div class="box-row-content">
86 <div class="flex">
87 <input type="text" id="key" name="key"
88 value="<?php echo esc_attr( $this->default_key ); ?>" maxlength="16"
89 readonly/>
90 <button id="generate_key" type="button" class="button button-large">
91 セットアップキーを生成
92 </button>
93 </div>
94 <div id="qrcode_container" hidden>
95 <div id="qrcode"></div>
96 <div class="flex onetime-password-container">
97 <label for="google_authenticator_code">認証コード:</label>
98 <input type="text" id="google_authenticator_code" name="google_authenticator_code"
99 maxlength="6"/>
100 </div>
101 </div>
102 </div>
103 </div>
104 </div>
105 </div>
106 <div id="submit-btn-area">
107 <?php $this->nonce_wp( $this->two_factor_authentication->get_feature_key() ); ?>
108 <p id="guide_message" hidden>アプリケーションに表示された6桁の認証コードを�
109 �力し、「変更を保存」ボタンをクリックしてください。</p>
110 <?php $this->submit_button_wp(); ?>
111 </div>
112 </form>
113 <style>
114 #generate_key {
115 margin-left: 16px;
116 }
117
118 #qrcode {
119 margin: 32px 32px 16px;
120 }
121
122 .onetime-password-container {
123 margin-left: -20px;
124 }
125 </style>
126 <script src="https://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js"
127 type="text/javascript"></script>
128 <script type="text/javascript">
129 function quintetCount(buff) {
130 const quintets = Math.floor(buff.length / 5);
131 return buff.length % 5 === 0 ? quintets : quintets + 1;
132 }
133
134 function bufferToBase32(plain) {
135 let i = 0;
136 let j = 0;
137 let shiftIndex = 0;
138 let digit = 0;
139 const charTable = "ABCDEFGHIJKLMNOPQRSTUVWXYZ234567";
140 const encoded = new Array(quintetCount(plain) * 8);
141
142 /* byte by byte は、quintet by quintet ほどきれいではありませんが、テストは少し速くなります。 再訪する�
143 要があります。 */
144 while (i < plain.length) {
145 const current = plain[i];
146
147 if (shiftIndex > 3) {
148 digit = current & (0xff >> shiftIndex);
149 shiftIndex = (shiftIndex + 5) % 8;
150 digit = (digit << shiftIndex) | ((i + 1 < plain.length) ?
151 plain[i + 1] : 0) >> (8 - shiftIndex);
152 i++;
153 } else {
154 digit = (current >> (8 - (shiftIndex + 5))) & 0x1f;
155 shiftIndex = (shiftIndex + 5) % 8;
156 if (shiftIndex === 0) {
157 i++;
158 }
159 }
160
161 encoded[j] = charTable[digit];
162 j++;
163 }
164
165 for (i = j; i < encoded.length; i++) {
166 encoded[i] = '=';
167 }
168
169 return encoded.join('');
170 }
171
172 function generateKey() {
173 return bufferToBase32(crypto.getRandomValues(new Uint8Array(10)))
174 }
175
176 const qrcode = new QRCode('qrcode', {correctLevel: QRCode.CorrectLevel.M})
177
178 function showQRIfExists() {
179 const key = document.getElementById('key').value
180 document.getElementById('qrcode_container').hidden = !key
181 document.getElementById('guide_message').hidden = !key
182 if (!key) return
183 const name = document.querySelector('.display-name').textContent
184
185 // https://github.com/google/google-authenticator/wiki/Key-Uri-Format
186 qrcode.makeCode(`otpauth://totp/${encodeURIComponent(name)}?secret=${key}&issuer=${location.hostname}`)
187
188 document.getElementById('google_authenticator_code').focus()
189 }
190
191 showQRIfExists()
192
193 document.getElementById('generate_key').addEventListener('click', () => {
194 document.getElementById('key').value = generateKey()
195 showQRIfExists()
196 })
197 </script>
198 <?php
199 }
200 }
201