Create dedicate crate for php_escaping.rs
[hiphop-php.git] / hphp / runtime / server / cert-reloader.cpp
blob4cd0b3572fa342ed204704803ae6308dd00a48ef
1 /*
2 +----------------------------------------------------------------------+
3 | HipHop for PHP |
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>
22 #include <sys/stat.h>
24 #include <folly/portability/Fcntl.h>
26 namespace HPHP {
28 const std::string CertReloader::crt_ext = ".crt";
29 const std::string CertReloader::key_ext = ".key";
31 /**
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) {
36 auto path = cert_dir;
37 // Ensure path ends with '/'. This helps our pruning later.
38 if (path.size() > 0 && path[path.size() - 1] != '/') {
39 path.append("/");
42 std::vector<CertKeyPair> paths;
43 find_paths(path, paths);
44 certHandlerFn(paths);
47 bool CertReloader::fileIsValid(const std::string &filename) {
48 if (filename.empty()) {
49 return false;
51 int fd = open(filename.c_str(), O_RDONLY);
52 if (fd >= 0) {
53 close(fd);
54 return true;
56 return false;
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()) {
88 continue;
90 struct stat statbuf;
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) {
96 continue;
97 } else if (rc != 0) {
98 Logger::Warning("Stat '%s' failed with errno=%d", crt_path.c_str(),
99 errno);
101 if (!fileIsValid(key_path) || !fileIsValid(crt_path)) {
102 continue;
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());
113 return false;