| @@ -348,8 +348,75 @@ | ||
| 348 | 348 | return $dir; |
| 349 | 349 | } |
| 350 | 350 | |
| 351 | 351 | /** |
| 352 | + * 証明書ディレクトリに公開遮断ファイルを設置する | |
| 353 | + * | |
| 354 | + * 秘密鍵を含む証明書が HTTP で配信される領域に保存されている場合に備え、 | |
| 355 | + * ディレクトリ名の推測困難性だけに頼らず Web サーバー側でも遮断する. | |
| 356 | + * 効果があるのは .htaccess を読む Apache のみ. nginx では無効. | |
| 357 | + * | |
| 358 | + * 証明書が実際に置かれているディレクトリのときにのみ設置する. | |
| 359 | + * 証明書ファイルパスは管理画面で任意のディレクトリに変更できるため、 | |
| 360 | + * 証明書と無関係なディレクトリには触れないようにする. | |
| 361 | + * | |
| 362 | + * 呼び出し元はディレクトリ作成時・証明書アップロード時・管理画面の読み込み時の3箇所. | |
| 363 | + * | |
| 364 | + * @param string $dir Certificate directory path. | |
| 365 | + * @return bool True if the directory has the blocking file. | |
| 366 | + */ | |
| 367 | + private function protect_certificate_dir( $dir ) { | |
| 368 | + if ( WCUtils::is_blank( $dir ) || ! is_dir( $dir ) ) { | |
| 369 | + return false; | |
| 370 | + } | |
| 371 | + | |
| 372 | + $htaccess = $dir . '/.htaccess'; | |
| 373 | + if ( file_exists( $htaccess ) ) { | |
| 374 | + return true; | |
| 375 | + } | |
| 376 | + | |
| 377 | + if ( ! is_writable( $dir ) || ! $this->has_certificate_file( $dir ) ) { | |
| 378 | + return false; | |
| 379 | + } | |
| 380 | + | |
| 381 | + $content = "<IfModule mod_authz_core.c>\n\tRequire all denied\n</IfModule>\n"; | |
| 382 | + $content .= "<IfModule !mod_authz_core.c>\n\tOrder deny,allow\n\tDeny from all\n</IfModule>\n"; | |
| 383 | + | |
| 384 | + return ( false !== file_put_contents( $htaccess, $content ) ); | |
| 385 | + } | |
| 386 | + | |
| 387 | + /** | |
| 388 | + * 証明書が置かれているディレクトリかを判定する | |
| 389 | + * | |
| 390 | + * クライアント証明書(.pem)かCAファイル(.crt)が1つでもあれば true. | |
| 391 | + * 拡張子はアップロード時の検証と揃えてある. | |
| 392 | + * 証明書が無いディレクトリでは決済設定画面の表示ごとにこの判定が走るため、 | |
| 393 | + * ファイル名を配列に溜めずに1件ずつ調べ、見つかった時点で打ち切る. | |
| 394 | + * | |
| 395 | + * @param string $dir Certificate directory path. | |
| 396 | + * @return bool True if the directory holds a certificate file. | |
| 397 | + */ | |
| 398 | + private function has_certificate_file( $dir ) { | |
| 399 | + $handle = opendir( $dir ); | |
| 400 | + if ( false === $handle ) { | |
| 401 | + return false; | |
| 402 | + } | |
| 403 | + | |
| 404 | + $extensions = array( 'pem', 'crt' ); | |
| 405 | + $found = false; | |
| 406 | + | |
| 407 | + while ( false !== ( $entry = readdir( $handle ) ) ) { | |
| 408 | + if ( in_array( strtolower( pathinfo( $entry, PATHINFO_EXTENSION ) ), $extensions, true ) ) { | |
| 409 | + $found = true; | |
| 410 | + break; | |
| 411 | + } | |
| 412 | + } | |
| 413 | + closedir( $handle ); | |
| 414 | + | |
| 415 | + return $found; | |
| 416 | + } | |
| 417 | + | |
| 418 | + /** | |
| 352 | 419 | * 決済有効判定 |
| 353 | 420 | * 支払方法で使用している場合に true |
| 354 | 421 | * |
| 355 | 422 | * @param string $type Module type. |
| @@ -1594,8 +1661,9 @@ | ||
| 1594 | 1661 | } else { |
| 1595 | 1662 | if ( ! is_dir( $certificate_path ) ) { |
| 1596 | 1663 | wp_mkdir_p( $certificate_path ); |
| 1597 | 1664 | } |
| 1665 | + $this->protect_certificate_dir( $certificate_path ); | |
| 1598 | 1666 | if ( ! empty( $post_data['file'] ) ) { |
| 1599 | 1667 | $full_path = $certificate_path . '/' . $post_data['file']; |
| 1600 | 1668 | foreach ( $invalid_wrappers as $wrapper ) { |
| 1601 | 1669 | if ( strpos( $full_path, $wrapper ) !== false ) { |
| @@ -1646,8 +1714,9 @@ | ||
| 1646 | 1714 | if ( 'NG' != $data['status'] ) { |
| 1647 | 1715 | if ( 0 < $upfile['error'] ) { |
| 1648 | 1716 | $data['status'] = $upfile['error']; |
| 1649 | 1717 | } else { |
| 1718 | + $this->protect_certificate_dir( $acting_opts['certificate_path'] ); | |
| 1650 | 1719 | $filename = sanitize_file_name( $upfile['name'] ); |
| 1651 | 1720 | $res = move_uploaded_file( $upfile['tmp_name'], $acting_opts['certificate_path'] . '/' . $filename ); |
| 1652 | 1721 | if ( $res ) { |
| 1653 | 1722 | $data['status'] = 'OK'; |
| @@ -1938,8 +2007,11 @@ | ||
| 1938 | 2007 | |
| 1939 | 2008 | $acting_opts = $this->get_acting_settings(); |
| 1940 | 2009 | $settlement_selected = get_option( 'usces_settlement_selected' ); |
| 1941 | 2010 | if ( in_array( $this->paymod_id, (array) $settlement_selected ) ) : |
| 2011 | + /* 証明書ディレクトリの遮断ファイルを点検する. */ | |
| 2012 | + $this->protect_certificate_dir( ( isset( $acting_opts['certificate_path'] ) ) ? $acting_opts['certificate_path'] : '' ); | |
| 2013 | + | |
| 1942 | 2014 | $seq_merchant_id = ( isset( $acting_opts['seq_merchant_id'] ) ) ? $acting_opts['seq_merchant_id'] : ''; |
| 1943 | 2015 | $connect_id = ( isset( $acting_opts['connect_id'] ) ) ? $acting_opts['connect_id'] : ''; |
| 1944 | 2016 | $connect_password = ( isset( $acting_opts['connect_password'] ) ) ? $acting_opts['connect_password'] : ''; |
| 1945 | 2017 | $hc = ( isset( $acting_opts['hc'] ) ) ? $acting_opts['hc'] : ''; |
| @@ -2157,9 +2229,9 @@ | ||
| 2157 | 2229 | <input type="button" class="button" value="変更する" id="change_certificate_path" /> |
| 2158 | 2230 | <input name="certificate_path_before" type="hidden" value="<?php echo esc_attr( $certificate_path ); ?>" /> |
| 2159 | 2231 | </td> |
| 2160 | 2232 | </tr> |
| 2161 | - <tr id="ex_certificate_path_paygent" class="explanation paygent_card_form"><td colspan="2">モジュールタイプで利用するときは必須です。</td></tr> | |
| 2233 | + <tr id="ex_certificate_path_paygent" class="explanation paygent_card_form"><td colspan="2">証明書を保存するフォルダです。モジュールタイプで利用するときは必須です。通常は初期値のままで問題ありません。変更する場合は、証明書だけを入れる専用のフォルダを指定してください。画像などが入っているフォルダを指定すると、それらが表示されなくなります。</td></tr> | |
| 2162 | 2234 | <tr class="paygent_card_form"> |
| 2163 | 2235 | <th><a class="explanation-label" id="label_ex_client_file_paygent">クライアント証明書ファイル</a></th> |
| 2164 | 2236 | <td><input name="client_file" type="text" id="client_file_paygent" value="<?php echo esc_attr( $client_file ); ?>" class="regular-text"<?php echo esc_html( $client_file_disabled ); ?> /><br /> |
| 2165 | 2237 | <input type="button" class="button" value="アップロード" id="client_file_upload"<?php echo esc_html( $client_file_disabled ); ?> /><span id="client_file_upload_result"></span> |
| @@ -2164,9 +2236,9 @@ | ||
| 2164 | 2236 | <td><input name="client_file" type="text" id="client_file_paygent" value="<?php echo esc_attr( $client_file ); ?>" class="regular-text"<?php echo esc_html( $client_file_disabled ); ?> /><br /> |
| 2165 | 2237 | <input type="button" class="button" value="アップロード" id="client_file_upload"<?php echo esc_html( $client_file_disabled ); ?> /><span id="client_file_upload_result"></span> |
| 2166 | 2238 | </td> |
| 2167 | 2239 | </tr> |
| 2168 | - <tr id="ex_client_file_paygent" class="explanation paygent_card_form"><td colspan="2">モジュールタイプで利用するときは必須です。クライアント証明書ファイルは試験環境と本番環境で異なります。アップロードができない場合は wp-content/uploads/ フォルダのパーミッションを確認してください。</td></tr> | |
| 2240 | + <tr id="ex_client_file_paygent" class="explanation paygent_card_form"><td colspan="2">モジュールタイプで利用するときは必須です。クライアント証明書ファイルは試験環境と本番環境で異なります。アップロードができない場合は、証明書ファイルパスのフォルダの書き込み権限を確認してください。</td></tr> | |
| 2169 | 2241 | <tr class="paygent_card_form"> |
| 2170 | 2242 | <th><a class="explanation-label" id="label_ex_ca_file_paygent">CAファイル</a></th> |
| 2171 | 2243 | <td><input name="ca_file" type="text" id="ca_file_paygent" value="<?php echo esc_attr( $ca_file ); ?>" class="regular-text"<?php echo esc_html( $ca_file_disabled ); ?> /><br /> |
| 2172 | 2244 | <input type="button" class="button" value="アップロード" id="ca_file_upload"<?php echo esc_html( $ca_file_disabled ); ?> /><span id="ca_file_upload_result"></span> |
| @@ -2171,9 +2243,9 @@ | ||
| 2171 | 2243 | <td><input name="ca_file" type="text" id="ca_file_paygent" value="<?php echo esc_attr( $ca_file ); ?>" class="regular-text"<?php echo esc_html( $ca_file_disabled ); ?> /><br /> |
| 2172 | 2244 | <input type="button" class="button" value="アップロード" id="ca_file_upload"<?php echo esc_html( $ca_file_disabled ); ?> /><span id="ca_file_upload_result"></span> |
| 2173 | 2245 | </td> |
| 2174 | 2246 | </tr> |
| 2175 | - <tr id="ex_ca_file_paygent" class="explanation paygent_card_form"><td colspan="2">モジュールタイプで利用するときは必須です。アップロードができない場合は wp-content/uploads/ フォルダのパーミッションを確認してください。</td></tr> | |
| 2247 | + <tr id="ex_ca_file_paygent" class="explanation paygent_card_form"><td colspan="2">モジュールタイプで利用するときは必須です。アップロードができない場合は、証明書ファイルパスのフォルダの書き込み権限を確認してください。</td></tr> | |
| 2176 | 2248 | <tr class="paygent_card_form paygent_card_module"> |
| 2177 | 2249 | <th><a class="explanation-label" id="label_ex_token_key_paygent">トークン生成鍵</a></th> |
| 2178 | 2250 | <td><input name="token_key" type="text" id="token_key_paygent" value="<?php echo esc_attr( $token_key ); ?>" class="regular-text" /></td> |
| 2179 | 2251 | </tr> |
| @@ -5261,21 +5333,24 @@ | ||
| 5261 | 5333 | <body onload="javascript:document.forms['redirectForm'].submit();"> |
| 5262 | 5334 | <form action="<?php echo esc_url( USCES_CART_URL ); ?>" method="post" id="redirectForm"> |
| 5263 | 5335 | <?php |
| 5264 | 5336 | foreach ( (array) $post_data as $key => $value ) { |
| 5265 | - echo '<input type="hidden" name="' . $key . '" value="' . $value . '" />' . "\n"; | |
| 5337 | + if ( is_array( $value ) ) { | |
| 5338 | + continue; | |
| 5339 | + } | |
| 5340 | + echo '<input type="hidden" name="' . esc_attr( $key ) . '" value="' . esc_attr( $value ) . '" />' . "\n"; | |
| 5266 | 5341 | } |
| 5267 | 5342 | if ( isset( $_GET['result'] ) ) { |
| 5268 | - echo '<input type="hidden" name="result" value="' . $_GET['result'] . '" />' . "\n"; | |
| 5343 | + echo '<input type="hidden" name="result" value="' . esc_attr( wp_unslash( $_GET['result'] ) ) . '" />' . "\n"; | |
| 5269 | 5344 | } |
| 5270 | 5345 | if ( isset( $_GET['3ds_auth_id'] ) ) { |
| 5271 | - echo '<input type="hidden" name="3ds_auth_id" value="' . $_GET['3ds_auth_id'] . '" />' . "\n"; | |
| 5346 | + echo '<input type="hidden" name="3ds_auth_id" value="' . esc_attr( wp_unslash( $_GET['3ds_auth_id'] ) ) . '" />' . "\n"; | |
| 5272 | 5347 | } |
| 5273 | 5348 | if ( isset( $_GET['3dsecure_ds_transaction_id'] ) ) { |
| 5274 | - echo '<input type="hidden" name="3dsecure_ds_transaction_id" value="' . $_GET['3dsecure_ds_transaction_id'] . '" />' . "\n"; | |
| 5349 | + echo '<input type="hidden" name="3dsecure_ds_transaction_id" value="' . esc_attr( wp_unslash( $_GET['3dsecure_ds_transaction_id'] ) ) . '" />' . "\n"; | |
| 5275 | 5350 | } |
| 5276 | 5351 | if ( isset( $_GET['attempt_kbn'] ) ) { |
| 5277 | - echo '<input type="hidden" name="attempt_kbn" value="' . $_GET['attempt_kbn'] . '" />' . "\n"; | |
| 5352 | + echo '<input type="hidden" name="attempt_kbn" value="' . esc_attr( wp_unslash( $_GET['attempt_kbn'] ) ) . '" />' . "\n"; | |
| 5278 | 5353 | } |
| 5279 | 5354 | ?> |
| 5280 | 5355 | <input type="hidden" name="purchase" value="purchase" /> |
| 5281 | 5356 | <input type="hidden" name="from3ds" value="1" /> |