VirtualBox

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

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