File indexing completed on 2024-04-28 03:52:38

0001 /*
0002     SPDX-FileCopyrightText: 2008 Nicola Gigante <nicola.gigante@gmail.com>
0003     SPDX-FileCopyrightText: 2014, 2016 René Bertin <rjvbertin@gmail.com>
0004 
0005     SPDX-License-Identifier: LGPL-2.1-or-later
0006 */
0007 
0008 #include "AuthServicesBackend.h"
0009 
0010 #include <qplugin.h>
0011 
0012 #include <QDebug>
0013 #include <QLoggingCategory>
0014 
0015 Q_DECLARE_LOGGING_CATEGORY(KAUTH_OSX)
0016 // logging category for this backend, default: log stuff >= warning
0017 Q_LOGGING_CATEGORY(KAUTH_OSX, "kf.auth.apple", QtWarningMsg)
0018 
0019 namespace KAuth
0020 {
0021 static AuthorizationRef s_authRef = NULL;
0022 
0023 AuthorizationRef authRef()
0024 {
0025     if (!s_authRef) {
0026         AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &s_authRef);
0027     }
0028 
0029     return s_authRef;
0030 }
0031 
0032 // GetActionRights return codes:
0033 //     errAuthorizationSuccess                 = 0,
0034 //     errAuthorizationInvalidSet              = -60001, /* The authorization rights are invalid. */
0035 //     errAuthorizationInvalidRef              = -60002, /* The authorization reference is invalid. */
0036 //     errAuthorizationInvalidTag              = -60003, /* The authorization tag is invalid. */
0037 //     errAuthorizationInvalidPointer          = -60004, /* The returned authorization is invalid. */
0038 //     errAuthorizationDenied                  = -60005, /* The authorization was denied. */
0039 //     errAuthorizationCanceled                = -60006, /* The authorization was cancelled by the user. */
0040 //     errAuthorizationInteractionNotAllowed   = -60007, /* The authorization was denied since no user interaction was possible. */
0041 //     errAuthorizationInternal                = -60008, /* Unable to obtain authorization for this operation. */
0042 //     errAuthorizationExternalizeNotAllowed    = -60009, /* The authorization is not allowed to be converted to an external format. */
0043 //     errAuthorizationInternalizeNotAllowed    = -60010, /* The authorization is not allowed to be created from an external format. */
0044 //     errAuthorizationInvalidFlags            = -60011, /* The provided option flag(s) are invalid for this authorization operation. */
0045 //     errAuthorizationToolExecuteFailure      = -60031, /* The specified program could not be executed. */
0046 //     errAuthorizationToolEnvironmentError    = -60032, /* An invalid status was returned during execution of a privileged tool. */
0047 //     errAuthorizationBadAddress              = -60033, /* The requested socket address is invalid (must be 0-1023 inclusive). */
0048 static OSStatus GetActionRights(const QString &action, AuthorizationFlags flags, AuthorizationRef auth)
0049 {
0050     AuthorizationItem item;
0051     item.name = action.toUtf8().constData();
0052     item.valueLength = 0;
0053     item.value = NULL;
0054     item.flags = 0;
0055 
0056     AuthorizationRights rights;
0057     rights.count = 1;
0058     rights.items = &item;
0059 
0060     OSStatus result = AuthorizationCopyRights(auth, &rights, kAuthorizationEmptyEnvironment, flags, NULL);
0061     return result;
0062 }
0063 
0064 // On OS X we avoid using a helper but grab privilege from here, the client.
0065 AuthServicesBackend::AuthServicesBackend()
0066     : AuthBackend()
0067 {
0068     setCapabilities(AuthorizeFromClientCapability);
0069 }
0070 
0071 AuthServicesBackend::~AuthServicesBackend()
0072 {
0073     if (s_authRef) {
0074         OSStatus err = AuthorizationFree(s_authRef, kAuthorizationFlagDefaults);
0075         qCDebug(KAUTH_OSX) << "AuthorizationFree(" << s_authRef << ") returned" << err;
0076         s_authRef = NULL;
0077     }
0078 }
0079 
0080 void AuthServicesBackend::setupAction(const QString &)
0081 {
0082     // Nothing to do here...
0083 }
0084 
0085 Action::AuthStatus AuthServicesBackend::authorizeAction(const QString &action)
0086 {
0087     Action::AuthStatus retval;
0088     OSStatus result = GetActionRights(action, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, authRef());
0089     qCDebug(KAUTH_OSX) << "AuthServicesBackend::authorizeAction(" << action << ") AuthorizationCopyRights returned" << result;
0090     switch (result) {
0091     case errAuthorizationSuccess:
0092         retval = Action::AuthorizedStatus;
0093         break;
0094     case errAuthorizationCanceled:
0095         retval = Action::UserCancelledStatus;
0096         break;
0097     case errAuthorizationInteractionNotAllowed:
0098     case errAuthorizationDenied:
0099         retval = Action::DeniedStatus;
0100         break;
0101     case errAuthorizationInternal:
0102         // does this make sense?
0103         retval = Action::AuthRequiredStatus;
0104         break;
0105     case errAuthorizationExternalizeNotAllowed:
0106     case errAuthorizationInternalizeNotAllowed:
0107     case errAuthorizationToolExecuteFailure:
0108     case errAuthorizationToolEnvironmentError:
0109     case errAuthorizationBadAddress:
0110         retval = Action::ErrorStatus;
0111         break;
0112     default:
0113         retval = Action::InvalidStatus;
0114         break;
0115     }
0116     return retval;
0117 }
0118 
0119 Action::AuthStatus AuthServicesBackend::actionStatus(const QString &action)
0120 {
0121     Action::AuthStatus retval;
0122     OSStatus result = GetActionRights(action, kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize, authRef());
0123     qCDebug(KAUTH_OSX) << "AuthServicesBackend::actionStatus(" << action << ") AuthorizationCopyRights returned" << result;
0124     // this function has a simpler return code parser:
0125     switch (result) {
0126     case errAuthorizationSuccess:
0127         retval = Action::AuthorizedStatus;
0128         break;
0129     case errAuthorizationCanceled:
0130         retval = Action::UserCancelledStatus;
0131         break;
0132     case errAuthorizationInteractionNotAllowed:
0133         retval = Action::AuthRequiredStatus;
0134         break;
0135     default:
0136         retval = Action::DeniedStatus;
0137         break;
0138     }
0139     return retval;
0140 }
0141 
0142 QByteArray AuthServicesBackend::callerID() const
0143 {
0144     AuthorizationExternalForm ext;
0145     AuthorizationMakeExternalForm(authRef(), &ext);
0146     QByteArray id((const char *)&ext, sizeof(ext));
0147 
0148     return id;
0149 }
0150 
0151 bool AuthServicesBackend::isCallerAuthorized(const QString &action, const QByteArray &callerID, const QVariantMap &details)
0152 {
0153     Q_UNUSED(details);
0154 
0155     AuthorizationExternalForm ext;
0156     memcpy(&ext, callerID.data(), sizeof(ext));
0157 
0158     AuthorizationRef auth;
0159 
0160     if (AuthorizationCreateFromExternalForm(&ext, &auth) != noErr) {
0161         qCWarning(KAUTH_OSX()) << "AuthorizationCreateFromExternalForm(" << action << "," << callerID.constData() << ") failed";
0162         return false;
0163     }
0164 
0165     OSStatus result = GetActionRights(action, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, auth);
0166 
0167     AuthorizationFree(auth, kAuthorizationFlagDefaults);
0168     qCDebug(KAUTH_OSX) << "AuthServicesBackend::isCallerAuthorized(" << action << "," << callerID.constData() << ") AuthorizationCopyRights returned" << result;
0169 
0170     return result == errAuthorizationSuccess;
0171 }
0172 
0173 }; // namespace KAuth
0174 
0175 #include "moc_AuthServicesBackend.cpp"