クライアント証明書を要求するサイトの構築（Apache+OpenSSL）その2

[クライアント証明書を要求するサイトの構築（Apache+OpenSSL）その1](http://qiita.com/tukiyo/items/b5e8b3efce800b0fd269) の続き。

## p12キーのOUの値からアクセス許可判定をする。

```apache:/etc/apache2/sites-enabled/default-ssl.conf
#httpアクセスが来たらhttpsに転送する。
<VirtualHost *:80>
 ServerName democa.local
 ServerAlias localhost
 DocumentRoot /var/www/html
 RewriteEngine On
 RewriteCond %{SERVER_PORT} 80
 RewriteCond %{SERVER_NAME} !localhost
 RewriteRule ^(.*)?$ https://%{HTTP_HOST}$1 [R,L]
</VirtualHost>


<VirtualHost _default_:443>
 SSLEngine On
 SSLCertificateFile    /opt/demoCA/cert.pem
 SSLCertificateKeyFile /opt/demoCA/nokey.pem
 SSLCACertificateFile  /opt/demoCA/cacert.pem
 #SSLCARevocationFile   /opt/demoCA/crl.pem
 <Location />
    SSLVerifyClient require
    SSLRequire ( \
                %{SSL_CLIENT_S_DN_OU} eq "kitamura" \
             or %{SSL_CLIENT_S_DN_OU} eq "konaimura" \
             or %{SSL_CLIENT_S_DN_OU} eq "imakitamura" \
 #           or %{REMOTE_ADDR} =~ m/^10\.0\.2\.15$/ \
               )
 </Location>
 DocumentRoot /var/www/html
</VirtualHost>
```

アクセスさせたくないp12キーを持った人に対しては、以下の行を削除しapacheをreloadすれば良い。

```diff
-            or %{SSL_CLIENT_S_DN_OU} eq "imakitamura" \
```

またこの方法を応用するとLocationごとにユーザーのアクセス許可ができる。


| 設定                  | 備考                     |
|:----------------------|:-------------------------|
| SSLCertificateFile    | pem か cer か crt を指定 |
| SSLCertificateKeyFile | .keyを指定               |
| SSLCACertificateFile  | .p12を発行したCAの証明書 |


## 動作確認

```bash:動作確認
$ openssl s_client -connect localhost:443
```

* サーバーの証明書ファイルを入れ替えても、apacheをリスタートしないと反映されません。
* `unable to write 'random state'`と表示された場合、`sudo rm $HOME/.rnd`

## 拡張子対応表

| 拡張子| 備考                           | メモ                          |
|:-----|:------------------------------|-------------------------------|
| .key | 秘密鍵                         | ---BEGIN RSA PRIVATE KEY--- |
| .csr | CA(信頼された機関)に署名要求するもの。消してOK    | Certificate Signing Request   |
| .crt | CAが.csrに「このサーバは確かに存在する」と署名したもの | Certificate                   |
| .pem | 秘密鍵(.key),証明書(.crt),CAの中間証明書(.cer)を連結したもの | ------BEGIN CERTIFICATE------ |
| .p12 | .pemをパスワード暗号化           | &0� ��  �     |
| .crl | 証明書失効リスト                 | Certification Revocation List |


## 証明書の情報を表示

```bash:cert_info.sh
#!/bin/sh
set -u

if [ $# -eq 0 ];then
  echo "チェック対象のファイル名を指定してください。"
  exit 1
fi

if [ $# -gt 1 ];then
  echo "チェック対象のファイルは一つにしてください。"
  exit 1
fi

if [ ! -e "$1" ];then
  echo "チェック対象のファイルが見つかりません。"
  exit 1
fi

for mech in rsa req x509 crl
do
    openssl $mech -text -in $1 && echo "[上のコマンド#] openssl $mech -text -in $1"
done
```

```bash:使い方
$ cert_info.sh /var/pkg/ssl/OpenSolaris_extras.key.pem
$ cert_info.sh test_client.cer
```

```bash:有効期限を表示
$ openssl s_client -connect qiita.com:443 | openssl x509 -noout -dates
```

## phpでの判定

* [Apacheでのクライアント証明書利用設定入門](https://rms-digicert.ne.jp/howto/basis/apache_client_cert.html)

```php:
$_SERVER["SSL_CLIENT_S_DN"] // クライアント証明書のサブジェクト
$_SERVER["SSL_CLIENT_S_DN_CN"] // クライアント証明書のCN(CommonName)
```              

```
SSL_CLIENT_S_DN ---- 証明書 Subject
SSL_CLIENT_S_DN_C ---- 国名
SSL_CLIENT_S_DN_ST ---- 都道府県名
SSL_CLIENT_S_DN_L ---- 都市名
SSL_CLIENT_S_DN_O ---- 組織名
SSL_CLIENT_S_DN_OU ---- 部署名
```

### 注意点

* `SSL_CLIENT_V_END` は日付が2038年を超えると`Bad time value`になる様子。