Security: add security_runtime_error

Signed-off-by: Simon Rozman <simon@rozman.si>
This commit is contained in:
Simon Rozman 2025-06-02 14:24:27 +02:00
parent 945d6d819e
commit e15c6fc25a
2 changed files with 179 additions and 0 deletions

134
include/MacStd/Security.hpp Normal file
View File

@ -0,0 +1,134 @@
/*
SPDX-License-Identifier: MIT
Copyright © 2025 Amebis
*/
#pragma once
#include "common.hpp"
#import <Security/Security.h>
namespace macstd
{
///
/// Security runtime error
///
class security_runtime_error : public num_runtime_error<OSStatus>
{
public:
///
/// Constructs an exception
///
/// \param[in] num WinSock2 error code
///
security_runtime_error(error_type num) : num_runtime_error<OSStatus>(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<OSStatus>(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<OSStatus>(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<AuthorizationRef, static_cast<AuthorizationRef>(NULL)>
{
MACSTD_HANDLE_IMPL(authorization, AuthorizationRef, static_cast<AuthorizationRef>(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<AuthorizationRef>(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);
}
};
}

View File

@ -431,4 +431,49 @@ namespace macstd
///
virtual T duplicate_internal(_In_ T h) const = 0;
};
///
/// Numerical runtime error
///
template <typename _Tn>
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
};
}