KAuth

AuthServicesBackend.cpp
1 /*
2  SPDX-FileCopyrightText: 2008 Nicola Gigante <[email protected]>
3  SPDX-FileCopyrightText: 2014, 2016 RenĂ© Bertin <[email protected]>
4 
5  SPDX-License-Identifier: LGPL-2.1-or-later
6 */
7 
8 #include "AuthServicesBackend.h"
9 
10 #include <qplugin.h>
11 
12 #include <QDebug>
13 #include <QLoggingCategory>
14 
15 Q_DECLARE_LOGGING_CATEGORY(KAUTH_OSX)
16 // logging category for this backend, default: log stuff >= warning
17 Q_LOGGING_CATEGORY(KAUTH_OSX, "kf.auth.apple", QtWarningMsg)
18 
19 namespace KAuth
20 {
21 static AuthorizationRef s_authRef = NULL;
22 
23 AuthorizationRef authRef()
24 {
25  if (!s_authRef) {
26  AuthorizationCreate(NULL, kAuthorizationEmptyEnvironment, kAuthorizationFlagDefaults, &s_authRef);
27  }
28 
29  return s_authRef;
30 }
31 
32 // GetActionRights return codes:
33 // errAuthorizationSuccess = 0,
34 // errAuthorizationInvalidSet = -60001, /* The authorization rights are invalid. */
35 // errAuthorizationInvalidRef = -60002, /* The authorization reference is invalid. */
36 // errAuthorizationInvalidTag = -60003, /* The authorization tag is invalid. */
37 // errAuthorizationInvalidPointer = -60004, /* The returned authorization is invalid. */
38 // errAuthorizationDenied = -60005, /* The authorization was denied. */
39 // errAuthorizationCanceled = -60006, /* The authorization was cancelled by the user. */
40 // errAuthorizationInteractionNotAllowed = -60007, /* The authorization was denied since no user interaction was possible. */
41 // errAuthorizationInternal = -60008, /* Unable to obtain authorization for this operation. */
42 // errAuthorizationExternalizeNotAllowed = -60009, /* The authorization is not allowed to be converted to an external format. */
43 // errAuthorizationInternalizeNotAllowed = -60010, /* The authorization is not allowed to be created from an external format. */
44 // errAuthorizationInvalidFlags = -60011, /* The provided option flag(s) are invalid for this authorization operation. */
45 // errAuthorizationToolExecuteFailure = -60031, /* The specified program could not be executed. */
46 // errAuthorizationToolEnvironmentError = -60032, /* An invalid status was returned during execution of a privileged tool. */
47 // errAuthorizationBadAddress = -60033, /* The requested socket address is invalid (must be 0-1023 inclusive). */
48 static OSStatus GetActionRights(const QString &action, AuthorizationFlags flags, AuthorizationRef auth)
49 {
50  AuthorizationItem item;
51  item.name = action.toUtf8().constData();
52  item.valueLength = 0;
53  item.value = NULL;
54  item.flags = 0;
55 
56  AuthorizationRights rights;
57  rights.count = 1;
58  rights.items = &item;
59 
60  OSStatus result = AuthorizationCopyRights(auth, &rights, kAuthorizationEmptyEnvironment, flags, NULL);
61  return result;
62 }
63 
64 // On OS X we avoid using a helper but grab privilege from here, the client.
65 AuthServicesBackend::AuthServicesBackend()
66  : AuthBackend()
67 {
68  setCapabilities(AuthorizeFromClientCapability | CheckActionExistenceCapability);
69 }
70 
71 AuthServicesBackend::~AuthServicesBackend()
72 {
73  if (s_authRef) {
74  OSStatus err = AuthorizationFree(s_authRef, kAuthorizationFlagDefaults);
75  qCDebug(KAUTH_OSX) << "AuthorizationFree(" << s_authRef << ") returned" << err;
76  s_authRef = NULL;
77  }
78 }
79 
80 void AuthServicesBackend::setupAction(const QString &)
81 {
82  // Nothing to do here...
83 }
84 
85 Action::AuthStatus AuthServicesBackend::authorizeAction(const QString &action)
86 {
87  Action::AuthStatus retval;
88  OSStatus result = GetActionRights(action, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, authRef());
89  qCDebug(KAUTH_OSX) << "AuthServicesBackend::authorizeAction(" << action << ") AuthorizationCopyRights returned" << result;
90  switch (result) {
91  case errAuthorizationSuccess:
92  retval = Action::AuthorizedStatus;
93  break;
94  case errAuthorizationCanceled:
96  break;
97  case errAuthorizationInteractionNotAllowed:
98  case errAuthorizationDenied:
99  retval = Action::DeniedStatus;
100  break;
101  case errAuthorizationInternal:
102  // does this make sense?
104  break;
105  case errAuthorizationExternalizeNotAllowed:
106  case errAuthorizationInternalizeNotAllowed:
107  case errAuthorizationToolExecuteFailure:
108  case errAuthorizationToolEnvironmentError:
109  case errAuthorizationBadAddress:
110  retval = Action::ErrorStatus;
111  break;
112  default:
113  retval = Action::InvalidStatus;
114  break;
115  }
116  return retval;
117 }
118 
119 Action::AuthStatus AuthServicesBackend::actionStatus(const QString &action)
120 {
121  Action::AuthStatus retval;
122  OSStatus result = GetActionRights(action, kAuthorizationFlagExtendRights | kAuthorizationFlagPreAuthorize, authRef());
123  qCDebug(KAUTH_OSX) << "AuthServicesBackend::actionStatus(" << action << ") AuthorizationCopyRights returned" << result;
124  // this function has a simpler return code parser:
125  switch (result) {
126  case errAuthorizationSuccess:
127  retval = Action::AuthorizedStatus;
128  break;
129  case errAuthorizationCanceled:
131  break;
132  case errAuthorizationInteractionNotAllowed:
134  break;
135  default:
136  retval = Action::DeniedStatus;
137  break;
138  }
139  return retval;
140 }
141 
142 QByteArray AuthServicesBackend::callerID() const
143 {
144  AuthorizationExternalForm ext;
145  AuthorizationMakeExternalForm(authRef(), &ext);
146  QByteArray id((const char *)&ext, sizeof(ext));
147 
148  return id;
149 }
150 
151 bool AuthServicesBackend::isCallerAuthorized(const QString &action, const QByteArray &callerID, const QVariantMap &details)
152 {
153  Q_UNUSED(details);
154 
155  AuthorizationExternalForm ext;
156  memcpy(&ext, callerID.data(), sizeof(ext));
157 
158  AuthorizationRef auth;
159 
160  if (AuthorizationCreateFromExternalForm(&ext, &auth) != noErr) {
161  qCWarning(KAUTH_OSX()) << "AuthorizationCreateFromExternalForm(" << action << "," << callerID.constData() << ") failed";
162  return false;
163  }
164 
165  OSStatus result = GetActionRights(action, kAuthorizationFlagExtendRights | kAuthorizationFlagInteractionAllowed, auth);
166 
167  AuthorizationFree(auth, kAuthorizationFlagDefaults);
168  qCDebug(KAUTH_OSX) << "AuthServicesBackend::isCallerAuthorized(" << action << "," << callerID.constData() << ") AuthorizationCopyRights returned" << result;
169 
170  return result == errAuthorizationSuccess;
171 }
172 
173 // OS X doesn't distinguish between "action doesn't exist" and "action not allowed". So the
174 // best thing we can do is return true and hope that the action will be created if it didn't exist...
175 bool AuthServicesBackend::actionExists(const QString &)
176 {
177  return true;
178 }
179 
180 }; // namespace KAuth
@ AuthorizedStatus
The authorization has been granted by the authorization backend.
Definition: action.h:86
AuthStatus
The three values set by authorization methods.
Definition: action.h:82
QByteArray toUtf8() const const
Definition: action.cpp:18
@ InvalidStatus
An invalid action cannot be authorized.
Definition: action.h:85
const char * constData() const const
@ UserCancelledStatus
The user pressed Cancel the authentication dialog. Currently used only on the mac.
Definition: action.h:88
@ DeniedStatus
The authorization has been denied by the authorization backend.
Definition: action.h:83
@ ErrorStatus
An error occurred.
Definition: action.h:84
@ AuthRequiredStatus
The user could obtain the authorization after authentication.
Definition: action.h:87
char * data()
This file is part of the KDE documentation.
Documentation copyright © 1996-2023 The KDE developers.
Generated on Sun Feb 5 2023 04:14:58 by doxygen 1.8.17 written by Dimitri van Heesch, © 1997-2006

KDE's Doxygen guidelines are available online.