VirtualBox

source: vbox/trunk/src/VBox/Main/src-all/AuthLibrary.cpp@ 93943

Last change on this file since 93943 was 93115, checked in by vboxsync, 3 years ago

scm --update-copyright-year

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
File size: 8.1 KB
Line 
1/* $Id: AuthLibrary.cpp 93115 2022-01-01 11:31:46Z vboxsync $ */
2/** @file
3 * Main - External authentication library interface.
4 */
5
6/*
7 * Copyright (C) 2015-2022 Oracle Corporation
8 *
9 * This file is part of VirtualBox Open Source Edition (OSE), as
10 * available from http://www.virtualbox.org. This file is free software;
11 * you can redistribute it and/or modify it under the terms of the GNU
12 * General Public License (GPL) as published by the Free Software
13 * Foundation, in version 2 as it comes in the "COPYING" file of the
14 * VirtualBox OSE distribution. VirtualBox OSE is distributed in the
15 * hope that it will be useful, but WITHOUT ANY WARRANTY of any kind.
16 */
17
18#define LOG_GROUP LOG_GROUP_MAIN
19#include "AuthLibrary.h"
20#include "LoggingNew.h"
21
22#include <iprt/err.h>
23#include <iprt/ldr.h>
24#include <iprt/path.h>
25#include <iprt/string.h>
26#include <iprt/thread.h>
27
28typedef struct AuthCtx
29{
30 AuthResult result;
31
32 PAUTHENTRY3 pfnAuthEntry3;
33 PAUTHENTRY2 pfnAuthEntry2;
34 PAUTHENTRY pfnAuthEntry;
35
36 const char *pszCaller;
37 PAUTHUUID pUuid;
38 AuthGuestJudgement guestJudgement;
39 const char *pszUser;
40 const char *pszPassword;
41 const char *pszDomain;
42 int fLogon;
43 unsigned clientId;
44} AuthCtx;
45
46static DECLCALLBACK(int) authThread(RTTHREAD hThreadSelf, void *pvUser)
47{
48 RT_NOREF(hThreadSelf);
49 AuthCtx *pCtx = (AuthCtx *)pvUser;
50
51 if (pCtx->pfnAuthEntry3)
52 {
53 pCtx->result = pCtx->pfnAuthEntry3(pCtx->pszCaller, pCtx->pUuid, pCtx->guestJudgement,
54 pCtx->pszUser, pCtx->pszPassword, pCtx->pszDomain,
55 pCtx->fLogon, pCtx->clientId);
56 }
57 else if (pCtx->pfnAuthEntry2)
58 {
59 pCtx->result = pCtx->pfnAuthEntry2(pCtx->pUuid, pCtx->guestJudgement,
60 pCtx->pszUser, pCtx->pszPassword, pCtx->pszDomain,
61 pCtx->fLogon, pCtx->clientId);
62 }
63 else if (pCtx->pfnAuthEntry)
64 {
65 pCtx->result = pCtx->pfnAuthEntry(pCtx->pUuid, pCtx->guestJudgement,
66 pCtx->pszUser, pCtx->pszPassword, pCtx->pszDomain);
67 }
68 return VINF_SUCCESS;
69}
70
71static AuthResult authCall(AuthCtx *pCtx)
72{
73 AuthResult result = AuthResultAccessDenied;
74
75 /* Use a separate thread because external modules might need a lot of stack space. */
76 RTTHREAD thread = NIL_RTTHREAD;
77 int rc = RTThreadCreate(&thread, authThread, pCtx, 512*_1K,
78 RTTHREADTYPE_DEFAULT, RTTHREADFLAGS_WAITABLE, "VRDEAuth");
79 LogFlowFunc(("RTThreadCreate %Rrc\n", rc));
80
81 if (RT_SUCCESS(rc))
82 {
83 rc = RTThreadWait(thread, RT_INDEFINITE_WAIT, NULL);
84 LogFlowFunc(("RTThreadWait %Rrc\n", rc));
85 }
86
87 if (RT_SUCCESS(rc))
88 {
89 /* Only update the result if the thread finished without errors. */
90 result = pCtx->result;
91 }
92 else
93 {
94 LogRel(("AUTH: Unable to execute the auth thread %Rrc\n", rc));
95 }
96
97 return result;
98}
99
100int AuthLibLoad(AUTHLIBRARYCONTEXT *pAuthLibCtx, const char *pszLibrary)
101{
102 RT_ZERO(*pAuthLibCtx);
103
104 /* Load the external authentication library. */
105 LogRel(("AUTH: Loading external authentication library '%s'\n", pszLibrary));
106
107 int rc;
108 if (RTPathHavePath(pszLibrary))
109 rc = RTLdrLoad(pszLibrary, &pAuthLibCtx->hAuthLibrary);
110 else
111 {
112 rc = RTLdrLoadAppPriv(pszLibrary, &pAuthLibCtx->hAuthLibrary);
113 if (RT_FAILURE(rc))
114 {
115 /* Backward compatibility with old default 'VRDPAuth' name.
116 * Try to load new default 'VBoxAuth' instead.
117 */
118 if (RTStrICmp(pszLibrary, "VRDPAuth") == 0)
119 {
120 LogRel(("AUTH: Loading external authentication library 'VBoxAuth'\n"));
121 rc = RTLdrLoadAppPriv("VBoxAuth", &pAuthLibCtx->hAuthLibrary);
122 }
123 }
124 }
125
126 if (RT_FAILURE(rc))
127 {
128 LogRel(("AUTH: Failed to load external authentication library: %Rrc\n", rc));
129 pAuthLibCtx->hAuthLibrary = NIL_RTLDRMOD;
130 }
131
132 if (RT_SUCCESS(rc))
133 {
134 typedef struct AuthEntryInfoStruct
135 {
136 const char *pszName;
137 void **ppvAddress;
138 } AuthEntryInfo;
139
140 AuthEntryInfo entries[] =
141 {
142 { AUTHENTRY3_NAME, (void **)&pAuthLibCtx->pfnAuthEntry3 },
143 { AUTHENTRY2_NAME, (void **)&pAuthLibCtx->pfnAuthEntry2 },
144 { AUTHENTRY_NAME, (void **)&pAuthLibCtx->pfnAuthEntry },
145 { NULL, NULL }
146 };
147
148 /* Get the entry point. */
149 AuthEntryInfo *pEntryInfo = &entries[0];
150 while (pEntryInfo->pszName)
151 {
152 *pEntryInfo->ppvAddress = NULL;
153
154 int rc2 = RTLdrGetSymbol(pAuthLibCtx->hAuthLibrary, pEntryInfo->pszName, pEntryInfo->ppvAddress);
155 if (RT_SUCCESS(rc2))
156 {
157 /* Found an entry point. */
158 LogRel(("AUTH: Using entry point '%s'\n", pEntryInfo->pszName));
159 rc = VINF_SUCCESS;
160 break;
161 }
162
163 if (rc2 != VERR_SYMBOL_NOT_FOUND)
164 LogRel(("AUTH: Could not resolve import '%s': %Rrc\n", pEntryInfo->pszName, rc2));
165
166 rc = rc2;
167
168 pEntryInfo++;
169 }
170 }
171
172 if (RT_FAILURE(rc))
173 AuthLibUnload(pAuthLibCtx);
174
175 return rc;
176}
177
178void AuthLibUnload(AUTHLIBRARYCONTEXT *pAuthLibCtx)
179{
180 if (pAuthLibCtx->hAuthLibrary != NIL_RTLDRMOD)
181 RTLdrClose(pAuthLibCtx->hAuthLibrary);
182
183 RT_ZERO(*pAuthLibCtx);
184 pAuthLibCtx->hAuthLibrary = NIL_RTLDRMOD;
185}
186
187AuthResult AuthLibAuthenticate(const AUTHLIBRARYCONTEXT *pAuthLibCtx,
188 PCRTUUID pUuid, AuthGuestJudgement guestJudgement,
189 const char *pszUser, const char *pszPassword, const char *pszDomain,
190 uint32_t u32ClientId)
191{
192 AuthResult result = AuthResultAccessDenied;
193
194 AUTHUUID rawuuid;
195 memcpy(rawuuid, pUuid, sizeof(rawuuid));
196
197 LogFlowFunc(("pAuthLibCtx = %p, uuid = %RTuuid, guestJudgement = %d, pszUser = %s, pszPassword = %s, pszDomain = %s, u32ClientId = %d\n",
198 pAuthLibCtx, rawuuid, guestJudgement, pszUser, pszPassword, pszDomain, u32ClientId));
199
200 if ( pAuthLibCtx->hAuthLibrary
201 && (pAuthLibCtx->pfnAuthEntry || pAuthLibCtx->pfnAuthEntry2 || pAuthLibCtx->pfnAuthEntry3))
202 {
203 AuthCtx ctx;
204 ctx.result = AuthResultAccessDenied; /* Denied by default. */
205 ctx.pfnAuthEntry3 = pAuthLibCtx->pfnAuthEntry3;
206 ctx.pfnAuthEntry2 = pAuthLibCtx->pfnAuthEntry2;
207 ctx.pfnAuthEntry = pAuthLibCtx->pfnAuthEntry;
208 ctx.pszCaller = "vrde";
209 ctx.pUuid = &rawuuid;
210 ctx.guestJudgement = guestJudgement;
211 ctx.pszUser = pszUser;
212 ctx.pszPassword = pszPassword;
213 ctx.pszDomain = pszDomain;
214 ctx.fLogon = true;
215 ctx.clientId = u32ClientId;
216
217 result = authCall(&ctx);
218 }
219 else
220 {
221 LogRelMax(8, ("AUTH: Invalid authentication module context\n"));
222 AssertFailed();
223 }
224
225 LogFlowFunc(("result = %d\n", result));
226
227 return result;
228}
229
230void AuthLibDisconnect(const AUTHLIBRARYCONTEXT *pAuthLibCtx, PCRTUUID pUuid, uint32_t u32ClientId)
231{
232 AUTHUUID rawuuid;
233 memcpy(rawuuid, pUuid, sizeof(rawuuid));
234
235 LogFlowFunc(("pAuthLibCtx = %p, , uuid = %RTuuid, u32ClientId = %d\n",
236 pAuthLibCtx, rawuuid, u32ClientId));
237
238 if ( pAuthLibCtx->hAuthLibrary
239 && (pAuthLibCtx->pfnAuthEntry || pAuthLibCtx->pfnAuthEntry2 || pAuthLibCtx->pfnAuthEntry3))
240 {
241 AuthCtx ctx;
242 ctx.result = AuthResultAccessDenied; /* Not used. */
243 ctx.pfnAuthEntry3 = pAuthLibCtx->pfnAuthEntry3;
244 ctx.pfnAuthEntry2 = pAuthLibCtx->pfnAuthEntry2;
245 ctx.pfnAuthEntry = NULL; /* Does not use disconnect notification. */
246 ctx.pszCaller = "vrde";
247 ctx.pUuid = &rawuuid;
248 ctx.guestJudgement = AuthGuestNotAsked;
249 ctx.pszUser = NULL;
250 ctx.pszPassword = NULL;
251 ctx.pszDomain = NULL;
252 ctx.fLogon = false;
253 ctx.clientId = u32ClientId;
254
255 authCall(&ctx);
256 }
257}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette