2 +----------------------------------------------------------------------+
4 +----------------------------------------------------------------------+
5 | Copyright (c) 2010-present Facebook, Inc. (http://www.facebook.com) |
6 +----------------------------------------------------------------------+
7 | This source file is subject to version 3.01 of the PHP license, |
8 | that is bundled with this package in the file LICENSE, and is |
9 | available through the world-wide-web at the following url: |
10 | http://www.php.net/license/3_01.txt |
11 | If you did not receive a copy of the PHP license and are unable to |
12 | obtain it through the world-wide-web, please send a note to |
13 | license@php.net so we can mail you a copy immediately. |
14 +----------------------------------------------------------------------+
17 #include "hphp/runtime/server/cert-reloader.h"
18 #include "hphp/runtime/base/runtime-option.h"
19 #include "hphp/runtime/base/extended-logger.h"
20 #include "hphp/runtime/base/file-util.h"
21 #include <sys/types.h>
24 #include <folly/portability/Fcntl.h>
28 const std::string
CertReloader::crt_ext
= ".crt";
29 const std::string
CertReloader::key_ext
= ".key";
32 * Given a default SSL config, SSL_CTX, and certificate path, load certs.
34 void CertReloader::load(const std::string
&cert_dir
,
35 CertHandlerFn certHandlerFn
) {
37 // Ensure path ends with '/'. This helps our pruning later.
38 if (path
.size() > 0 && path
[path
.size() - 1] != '/') {
42 std::vector
<CertKeyPair
> paths
;
43 find_paths(path
, paths
);
47 bool CertReloader::fileIsValid(const std::string
&filename
) {
48 if (filename
.empty()) {
51 int fd
= open(filename
.c_str(), O_RDONLY
);
59 void CertReloader::find_paths(
60 const std::string
&path
,
61 std::vector
<CertKeyPair
> &cert_key_paths
) {
63 // Iterate through all files in the cert directory.
64 std::vector
<std::string
> crt_dir_files
;
65 std::unordered_set
<std::string
> crt_files
;
66 std::unordered_set
<std::string
> key_files
;
67 FileUtil::find(crt_dir_files
, "/", path
,
68 /* php */ false, /* js */ false, /* other */ true);
70 for (auto it
= crt_dir_files
.begin(); it
!= crt_dir_files
.end(); ++it
) {
71 size_t filename_len
= it
->size() - path
.size();
72 if (ends_with(*it
, crt_ext
) &&
73 *it
!= RuntimeOption::SSLCertificateFile
) {
74 std::string name
= it
->substr(path
.size(), filename_len
- crt_ext
.size());
75 crt_files
.insert(name
);
76 } else if (ends_with(*it
, key_ext
) &&
77 *it
!= RuntimeOption::SSLCertificateKeyFile
) {
78 std::string name
= it
->substr(path
.size(), filename_len
- key_ext
.size());
79 key_files
.insert(name
);
83 // Intersect key_files and crt_files to find valid pairs.
84 std::unordered_set
<ino_t
> crt_inodes
;
85 for (auto name
: key_files
) {
86 auto crt_file_it
= crt_files
.find(name
);
87 if (crt_file_it
== crt_files
.end()) {
91 std::string crt_path
= folly::to
<std::string
>(path
, name
, crt_ext
);
92 std::string key_path
= folly::to
<std::string
>(path
, name
, key_ext
);
94 int rc
= stat(crt_path
.c_str(), &statbuf
);
95 if (rc
== 0 && !crt_inodes
.insert(statbuf
.st_ino
).second
) {
98 Logger::Warning("Stat '%s' failed with errno=%d", crt_path
.c_str(),
101 if (!fileIsValid(key_path
) || !fileIsValid(crt_path
)) {
104 cert_key_paths
.push_back({crt_path
, key_path
});
108 bool CertReloader::ends_with(const std::string
&s
,
109 const std::string
&end
) {
110 if (s
.size() > end
.size()) {
111 return std::equal(s
.begin() + s
.size() - end
.size(), s
.end(), end
.begin());