From e15c6fc25a5302d2bd1c32519d2ea30af7d7d4dd Mon Sep 17 00:00:00 2001 From: Simon Rozman Date: Mon, 2 Jun 2025 14:24:27 +0200 Subject: [PATCH] Security: add security_runtime_error Signed-off-by: Simon Rozman --- include/MacStd/Security.hpp | 134 ++++++++++++++++++++++++++++++++++++ include/MacStd/common.hpp | 45 ++++++++++++ 2 files changed, 179 insertions(+) create mode 100644 include/MacStd/Security.hpp diff --git a/include/MacStd/Security.hpp b/include/MacStd/Security.hpp new file mode 100644 index 0000000..aa57d1d --- /dev/null +++ b/include/MacStd/Security.hpp @@ -0,0 +1,134 @@ +/* + SPDX-License-Identifier: MIT + Copyright © 2025 Amebis +*/ + +#pragma once + +#include "common.hpp" +#import + +namespace macstd +{ + /// + /// Security runtime error + /// + class security_runtime_error : public num_runtime_error + { + public: + /// + /// Constructs an exception + /// + /// \param[in] num WinSock2 error code + /// + security_runtime_error(error_type num) : num_runtime_error(num, message(num)) + { + } + + /// + /// Constructs an exception + /// + /// \param[in] num WinSock2 error code + /// \param[in] msg Error message + /// + security_runtime_error(error_type num, const std::string &msg) : num_runtime_error(num, msg + ": " + message(num)) + { + } + + /// + /// Constructs an exception + /// + /// \param[in] num WinSock2 error code + /// \param[in] msg Error message + /// + security_runtime_error(error_type num, const char *msg) : num_runtime_error(num, std::string(msg) + ": " + message(num)) + { + } + + protected: + /// + /// Returns a string explaining the meaning of a security result code + /// + /// \sa [SecCopyErrorMessageString function](https://developer.apple.com/documentation/security/seccopyerrormessagestring) + /// + static std::string message(error_type num) + { + // Handle common errors Apple does not provide message strings for. + switch (num) { + case errAuthorizationCanceled: return "Authorization was canceled by user"; + case errAuthorizationDenied: return "Authorization was denied"; + case errAuthorizationInteractionNotAllowed: return "User interaction not allowed for authorization"; + } + auto cfstr = SecCopyErrorMessageString(num, NULL); + if (!cfstr) + return "Security Framework error " + std::to_string(num); + auto ptr = CFStringGetCStringPtr(cfstr, kCFStringEncodingUTF8); + if (!ptr) { + CFRelease(cfstr); + return "Security Framework error " + std::to_string(num); + } + std::string str(ptr); + CFRelease(cfstr); + return str; + } + }; + + /// + /// Authorization reference wrapper class + /// + class authorization : public handle(NULL)> + { + MACSTD_HANDLE_IMPL(authorization, AuthorizationRef, static_cast(NULL)) + + public: + /// + /// Creates a new authorization reference and provides an option to authorize or preauthorize rights + /// + /// \sa [AuthorizationCreate function](https://developer.apple.com/documentation/security/authorizationcreate) + /// + authorization(const AuthorizationRights* rights, const AuthorizationEnvironment* environment, AuthorizationFlags flags) + { + AuthorizationRef h; + OSStatus status = AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &h); + if (status != errAuthorizationSuccess) + throw security_runtime_error(status, "AuthorizationCreate failed"); + this->m_h = h; + } + + /// + /// Internalizes the external representation of an authorization reference + /// + /// \sa [AuthorizationCreateFromExternalForm function](https://developer.apple.com/documentation/security/authorizationcreatefromexternalform) + /// + authorization(const AuthorizationExternalForm& extForm) + { + AuthorizationRef h; + OSStatus status = AuthorizationCreateFromExternalForm(&extForm, &h); + if (status != errAuthorizationSuccess) + throw security_runtime_error(status, "AuthorizationCreateFromExternalForm failed"); + this->m_h = h; + } + + /// + /// Releases an object handle + /// + /// \sa [AuthorizationFree function](https://developer.apple.com/documentation/security/authorizationfree) + /// + virtual ~authorization() + { + if (this->m_h != static_cast(NULL)) + free_internal(); + } + + protected: + /// + /// Releases an object handle + /// + /// \sa [AuthorizationFree function](https://developer.apple.com/documentation/security/authorizationfree) + /// + void free_internal() noexcept override + { + AuthorizationFree(this->m_h, kAuthorizationFlagDefaults); + } + }; +} diff --git a/include/MacStd/common.hpp b/include/MacStd/common.hpp index e6bcf5d..3fd3b77 100644 --- a/include/MacStd/common.hpp +++ b/include/MacStd/common.hpp @@ -431,4 +431,49 @@ namespace macstd /// virtual T duplicate_internal(_In_ T h) const = 0; }; + + + /// + /// Numerical runtime error + /// + template + class num_runtime_error : public std::runtime_error + { + public: + typedef _Tn error_type; ///< Error number type + + public: + /// + /// Constructs an exception + /// + /// \param[in] num Numeric error code + /// \param[in] msg Error message + /// + num_runtime_error(_In_ error_type num, _In_ const std::string& msg) : + m_num(num), + runtime_error(msg) + {} + + /// + /// Constructs an exception + /// + /// \param[in] num Numeric error code + /// \param[in] msg Error message + /// + num_runtime_error(_In_ error_type num, _In_z_ const char *msg) : + m_num(num), + runtime_error(msg) + {} + + /// + /// Returns the error number + /// + error_type number() const + { + return m_num; + } + + protected: + error_type m_num; ///< Numeric error code + }; }