+class Cynara {
+ public:
+ class Creds {
+ public:
+ Creds(int fd, std::string user, std::string client)
+ : fd_(fd), user_(std::move(user)), client_(std::move(client)) {
+ _W("client(%s), user(%s), fd(%d)", client_.c_str(), user_.c_str(), fd);
+ }
+
+ int GetFd() const { return fd_; }
+
+ const std::string& GetUser() const { return user_; }
+
+ const std::string& GetClient() const { return client_; }
+
+ private:
+ int fd_;
+ std::string user_;
+ std::string client_;
+ };
+
+ Cynara() : handle_(nullptr, cynara_finish) {
+ cynara* handle = nullptr;
+ if (cynara_initialize(&handle, nullptr) != CYNARA_API_SUCCESS) {
+ _E("cynara_initialize() is failed"); // LCOV_EXCL_LINE
+ } else {
+ handle_.reset(handle);
+ }
+ }
+
+ ~Cynara() = default;
+
+ std::shared_ptr<Creds> FetchCredsFromSocket(int fd) {
+ char* user = nullptr;
+ int ret = cynara_creds_socket_get_user(fd, USER_METHOD_DEFAULT, &user);
+ if (ret != CYNARA_API_SUCCESS) {
+ // LCOV_EXCL_START
+ char buf[128] = { 0, };
+ cynara_strerror(ret, buf, sizeof(buf));
+ _E("cynara_creds_socket_get_user() is failed. fd(%d), error(%d:%s)",
+ fd, ret, buf);
+ return nullptr;
+ // LCOV_EXCL_STOP
+ }
+ auto user_auto = std::unique_ptr<char, decltype(free)*>(user, free);
+
+ char* client = nullptr;
+ ret = cynara_creds_socket_get_client(fd, CLIENT_METHOD_DEFAULT, &client);
+ if (ret != CYNARA_API_SUCCESS) {
+ // LCOV_EXCL_START
+ char buf[128] = { 0, };
+ cynara_strerror(ret, buf, sizeof(buf));
+ _E("cynara_creds_socket_get_client() is failed. fd(%d), error(%d:%s)",
+ fd, ret, buf);
+ return nullptr;
+ // LCOV_EXCL_STOP
+ }
+ auto client_auto = std::unique_ptr<char, decltype(free)*>(client, free);
+
+ return std::make_shared<Creds>(fd, user, client);
+ }
+
+ int Check(const std::shared_ptr<Creds>& creds,
+ const std::string& privilege) const {
+ std::lock_guard<std::recursive_mutex> lock(mutex_);
+ _D("check privilege %s", privilege.c_str());
+ int ret = cynara_check(handle_.get(), creds->GetClient().c_str(), "",
+ creds->GetUser().c_str(), privilege.c_str());
+ if (ret != CYNARA_API_ACCESS_ALLOWED) {
+ _E("cynara_check() is not allowed. privilege(%s), error(%d)",
+ privilege.c_str(), ret);
+ return -1;
+ }
+
+ return 0;
+ }
+
+ private:
+ std::unique_ptr<cynara, decltype(cynara_finish)*> handle_;
+ mutable std::recursive_mutex mutex_;
+};
+
+Cynara cynara_inst;
+