プロジェクト

全般

プロフィール

Apache mod autoindex » 履歴 » バージョン 4

バージョン 3 (健二 酒井, 2019/11/13 00:05) → バージョン 4/5 (健二 酒井, 2019/11/13 22:09)

# Apache memo

## 概要

あったことを適当に書いてく

## クライアント認証とOption Index

### やりたい事

- 特定ディレクトリにクライアント認証をかけたい
- https://example.com/ でアクセスしたときにapacheのインデックスページを出したい https://example.com/でアクセスしたときにapacheのインデックスページを出したい

### 設定状況

こんなディレクトリを持っていたとする:

- DocumentRoot
- ClientVerifyDir
- FooDir
- BarDir

こんな設定だったりする:

- ディレクトリClientVerifyDirにクライアント認証をかけている
- ディレクトリDocumentRootにはクライアント認証をかけていない
- DocumentRootにOption +Indexがついている
- index.htmlとかはない

### 何が起きた

https://example.com/ でアクセスしたときにSSLのネゴシエーションに失敗する https://example.com/でアクセスしたときにSSLのネゴシエーションに失敗する

エラーログはこんな感じ

```
SSL Library Error: error:140890C7:SSL routines:ssl3_get_client_certificate:peer did not return a certificate -- No CAs known to server for verification?
AH02261: Re-negotiation handshake failed
```

結構悩んだのでメモしとく



### 原因(推測)

1. https://example.com/にアクセス
1. インデックスページを生成しようとする
1. DocumentRootのエントリ「ClientVerifyDir」を読もうとする
1. 一方ClientVerifyDirを読むにはクライアント認証が必要
アクセスしているDocumentRootはクライアント認証の提示をブラウザに要求していない
1. クライアント認証は失敗する

って感じなんだろうか。うーん、ディレクトリのread権限がなくて403 Forbidden的なしょぼいエラーと似ている気がする



### 対処

まず、ディレクトリ構造を変更

- DocumentRoot
- SecretsDir
- ClientVerifyDir
- FooDir
- BarDir

クライアント認証かけるディレクトリをSecretsDirより下のものたちに。

```
<Directory "DocumentRoot/SecretsDir/*">
SSLVerifyClient require
</Directory>
```

-------

### ソースを読んでみた

もやもやを解消したくせっかくだしソースを読んでみた。
https://github.com/apache/httpd/blob/trunk/modules/generators/mod_autoindex.c

たぶんこの辺。「make_autoindex_entry」とかいういかにもディレクトリエントリのリンク作り出しそうな関数

```c
if ((autoindex_opts & SHOW_FORBIDDEN)
&& (rr->status == HTTP_UNAUTHORIZED || rr->status == HTTP_FORBIDDEN)) {
show_forbidden = 1;
}

if ((rr->finfo.filetype != APR_DIR && rr->finfo.filetype != APR_REG)
|| !(rr->status == OK || ap_is_HTTP_SUCCESS(rr->status)
|| ap_is_HTTP_REDIRECT(rr->status)
|| show_forbidden == 1)) {
ap_destroy_sub_req(rr);
return (NULL);
}
```

以下、頭の中垂れ流し:

最初のifでたぶん、IndexOptionディレクティブのShowFobbidenのあたりを処理している。
if文の式を読むと「SHOW_FOBIDDENが立っていて、サブリクエストのステータスがUNAUTHORIZEDやFORBIDDENのとき」、フラグを立ててる。
このフラグが立っていると、下のif内の式第二項がfalseになると。なのでif文の中に突入するには、「ディレクトリでない かつ 通常のファイルでない」が成立すると。
で、このときNULL返してる、本来の返却値はentへのポインタなのでたぶん、エントリを作らなかった時にこのreturnなんだろう。

ここから逆に考えて、通常のファイルやディレクトリを表示しようとするときは第二項がfalseになる。
これはつまりサブリクエストがOKでないし、HTTPに成功もしてないし、リダイレクトでもないし、show_forbiddenが立ってない。
まぁ特に設定してない限りSHOW_FORBIDDENは0なのでいいや。

### 結論

うーん、つまりディレクトリエントリへのサブリクエストが成功しないと表示しないのね。
BASIC認証必要なディレクトリが出てきたり、出てこなかったりするのもこれでひとまず納得できる。
やっぱ表示していいディレクトリだけ出すようにmod_autoindexさんが辺制御してるということか。

ちゃんと読んでないけどたぶん合ってるだろう

## 参考

- mod_autoindex.c https://github.com/apache/httpd/blob/trunk/modules/generators/mod_autoindex.c
- mod_autoindexのディレクティブ https://httpd.apache.org/docs/2.4/en/mod/mod_autoindex.html#indexoptions
- サブリクエスト http://koseki.hatenablog.com/entry/20090921/ModDirRewrite