summaryrefslogtreecommitdiffstats
path: root/src/VBox/HostServices/auth/simple/VBoxAuthSimple.cpp
blob: 671f2f00b725710d7e4423004d744335a35387cf (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
/* $Id: VBoxAuthSimple.cpp $ */
/** @file
 * VirtualBox External Authentication Library - Simple Authentication.
 */

/*
 * Copyright (C) 2006-2023 Oracle and/or its affiliates.
 *
 * This file is part of VirtualBox base platform packages, as
 * available from https://www.virtualbox.org.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License
 * as published by the Free Software Foundation, in version 3 of the
 * License.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, see <https://www.gnu.org/licenses>.
 *
 * SPDX-License-Identifier: GPL-3.0-only
 */

#include <stdlib.h>
#include <stdio.h>
#include <string.h>

#include <iprt/cdefs.h>
#include <iprt/uuid.h>
#include <iprt/sha.h>

#include <VBox/VBoxAuth.h>

#include <VBox/com/com.h>
#include <VBox/com/string.h>
#include <VBox/com/Guid.h>
#include <VBox/com/VirtualBox.h>

using namespace com;

/* If defined, debug messages will be written to the specified file. */
//#define AUTH_DEBUG_FILE_NAME "/tmp/VBoxAuth.log"


static void dprintf(const char *pszFormat, ...)
{
#ifdef AUTH_DEBUG_FILE_NAME
    FILE *f = fopen(AUTH_DEBUG_FILE_NAME, "ab");
    if (f)
    {
        va_list va;
        va_start(va, pszFormat);
        vfprintf(f, pszFormat, va);
        va_end(va);
        fclose(f);
    }
#else
    RT_NOREF(pszFormat);
#endif
}

RT_C_DECLS_BEGIN
DECLEXPORT(FNAUTHENTRY3) AuthEntry;
RT_C_DECLS_END

DECLEXPORT(AuthResult) AUTHCALL AuthEntry(const char *pszCaller,
                                          PAUTHUUID pUuid,
                                          AuthGuestJudgement guestJudgement,
                                          const char *pszUser,
                                          const char *pszPassword,
                                          const char *pszDomain,
                                          int fLogon,
                                          unsigned clientId)
{
    RT_NOREF(pszCaller, guestJudgement, pszDomain, clientId);

    /* default is failed */
    AuthResult result = AuthResultAccessDenied;

    /* only interested in logon */
    if (!fLogon)
        /* return value ignored */
        return result;

    char uuid[RTUUID_STR_LENGTH] = {0};
    if (pUuid)
        RTUuidToStr((PCRTUUID)pUuid, (char*)uuid, RTUUID_STR_LENGTH);

    /* the user might contain a domain name, split it */
    const char *user = strchr(pszUser, '\\');
    if (user)
        user++;
    else
        user = (char*)pszUser;

    dprintf("VBoxAuth: uuid: %s, user: %s, pszPassword: %s\n", uuid, user, pszPassword);

    ComPtr<IVirtualBoxClient> virtualBoxClient;
    ComPtr<IVirtualBox> virtualBox;
    HRESULT rc;

    rc = virtualBoxClient.createInprocObject(CLSID_VirtualBoxClient);
    if (SUCCEEDED(rc))
    {
        rc = virtualBoxClient->COMGETTER(VirtualBox)(virtualBox.asOutParam());
        if (SUCCEEDED(rc))
        {
            Bstr key = BstrFmt("VBoxAuthSimple/users/%s", user);
            Bstr password;

            /* lookup in VM's extra data? */
            if (pUuid)
            {
                ComPtr<IMachine> machine;
                virtualBox->FindMachine(Bstr(uuid).raw(), machine.asOutParam());
                if (machine)
                    machine->GetExtraData(key.raw(), password.asOutParam());
            }
            else
                /* lookup global extra data */
                virtualBox->GetExtraData(key.raw(), password.asOutParam());

            if (!password.isEmpty())
            {
                /* calculate hash */
                uint8_t abDigest[RTSHA256_HASH_SIZE];
                RTSha256(pszPassword, strlen(pszPassword), abDigest);
                char pszDigest[RTSHA256_DIGEST_LEN + 1];
                RTSha256ToString(abDigest, pszDigest, sizeof(pszDigest));

                if (password == pszDigest)
                    result = AuthResultAccessGranted;
            }
        }
        else
            dprintf("VBoxAuth: failed to get VirtualBox object reference: %#x\n", rc);
    }
    else
        dprintf("VBoxAuth: failed to get VirtualBoxClient object reference: %#x\n", rc);

    return result;
}