VirtualBox

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

Last change on this file since 59090 was 58368, checked in by vboxsync, 9 years ago

Main: moved external auth library helpers to a separate source file.

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