1
/* Copyright 2000-2005 The Apache Software Foundation or its licensors, as
4
* Licensed under the Apache License, Version 2.0 (the "License");
5
* you may not use this file except in compliance with the License.
6
* You may obtain a copy of the License at
8
* http://www.apache.org/licenses/LICENSE-2.0
10
* Unless required by applicable law or agreed to in writing, software
11
* distributed under the License is distributed on an "AS IS" BASIS,
12
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13
* See the License for the specific language governing permissions and
14
* limitations under the License.
17
#include "apr_private.h"
18
#include "apr_strings.h"
19
#include "apr_portable.h"
21
#include "apr_arch_file_io.h"
22
#if APR_HAVE_SYS_TYPES_H
23
#include <sys/types.h>
27
/* Internal sid binary to string translation, see MSKB Q131320.
28
* Several user related operations require our SID to access
29
* the registry, but in a string format. All error handling
30
* depends on IsValidSid(), which internally we better test long
33
void get_sid_string(char *buf, apr_size_t blen, apr_uid_t id)
35
PSID_IDENTIFIER_AUTHORITY psia;
40
/* Determine authority values (these is a big-endian value,
41
* and NT records the value as hex if the value is > 2^32.)
43
psia = GetSidIdentifierAuthority(id);
44
nsa = (DWORD)(psia->Value[5]) + ((DWORD)(psia->Value[4]) << 8)
45
+ ((DWORD)(psia->Value[3]) << 16) + ((DWORD)(psia->Value[2]) << 24);
46
sa = (DWORD)(psia->Value[1]) + ((DWORD)(psia->Value[0]) << 8);
48
slen = apr_snprintf(buf, blen, "S-%lu-0x%04x%08x",
49
SID_REVISION, sa, nsa);
51
slen = apr_snprintf(buf, blen, "S-%lu-%lu",
55
/* Now append all the subauthority strings.
57
nsa = *GetSidSubAuthorityCount(id);
58
for (sa = 0; sa < nsa; ++sa) {
59
slen += apr_snprintf(buf + slen, blen - slen, "-%lu",
60
*GetSidSubAuthority(id, sa));
64
/* Query the ProfileImagePath from the version-specific branch, where the
65
* regkey uses the user's name on 9x, and user's sid string on NT.
67
APR_DECLARE(apr_status_t) apr_uid_homepath_get(char **dirname,
72
*dirname = apr_pstrdup(p, "/My Documents");
76
char regkey[MAX_PATH * 2];
82
if (apr_os_level >= APR_WIN_NT) {
86
if ((rv = apr_uid_get(&uid, &gid, username, p)) != APR_SUCCESS)
89
strcpy(regkey, "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\"
91
keylen = (DWORD)strlen(regkey);
92
get_sid_string(regkey + keylen, sizeof(regkey) - keylen, uid);
95
strcpy(regkey, "SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\"
97
keylen = (DWORD)strlen(regkey);
98
apr_cpystrn(regkey + keylen, username, sizeof(regkey) - keylen);
101
if ((rv = RegOpenKeyEx(HKEY_LOCAL_MACHINE, regkey, 0,
102
KEY_QUERY_VALUE, &key)) != ERROR_SUCCESS)
103
return APR_FROM_OS_ERROR(rv);
105
#if APR_HAS_UNICODE_FS
108
keylen = sizeof(regkey);
109
rv = RegQueryValueExW(key, L"ProfileImagePath", NULL, &type,
110
(void*)regkey, &keylen);
112
if (rv != ERROR_SUCCESS)
113
return APR_FROM_OS_ERROR(rv);
114
if (type == REG_SZ) {
115
char retdir[MAX_PATH];
116
if ((rv = unicode_to_utf8_path(retdir, sizeof(retdir),
117
(apr_wchar_t*)regkey)) != APR_SUCCESS)
119
*dirname = apr_pstrdup(p, retdir);
121
else if (type == REG_EXPAND_SZ) {
122
apr_wchar_t path[MAX_PATH];
123
char retdir[MAX_PATH];
124
ExpandEnvironmentStringsW((apr_wchar_t*)regkey, path, sizeof(path));
125
if ((rv = unicode_to_utf8_path(retdir, sizeof(retdir), path))
128
*dirname = apr_pstrdup(p, retdir);
137
keylen = sizeof(regkey);
138
rv = RegQueryValueEx(key, "ProfileImagePath", NULL, &type,
139
(void*)regkey, &keylen);
141
if (rv != ERROR_SUCCESS)
142
return APR_FROM_OS_ERROR(rv);
143
if (type == REG_SZ) {
144
*dirname = apr_pstrdup(p, regkey);
146
else if (type == REG_EXPAND_SZ) {
148
ExpandEnvironmentStrings(regkey, path, sizeof(path));
149
*dirname = apr_pstrdup(p, path);
154
#endif /* APR_HAS_ANSI_FS */
155
for (fixch = *dirname; *fixch; ++fixch)
159
#endif /* _WIN32_WCE */
162
APR_DECLARE(apr_status_t) apr_uid_current(apr_uid_t *uid,
172
TOKEN_PRIMARY_GROUP *grp;
174
if(!OpenProcessToken(GetCurrentProcess(), STANDARD_RIGHTS_READ | READ_CONTROL | TOKEN_QUERY, &threadtok)) {
175
return apr_get_os_error();
179
if (!GetTokenInformation(threadtok, TokenUser, NULL, 0, &needed)
180
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
181
&& (usr = apr_palloc(p, needed))
182
&& GetTokenInformation(threadtok, TokenUser, usr, needed, &needed))
183
*uid = usr->User.Sid;
185
return apr_get_os_error();
187
if (!GetTokenInformation(threadtok, TokenPrimaryGroup, NULL, 0, &needed)
188
&& (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
189
&& (grp = apr_palloc(p, needed))
190
&& GetTokenInformation(threadtok, TokenPrimaryGroup, grp, needed, &needed))
191
*gid = grp->PrimaryGroup;
193
return apr_get_os_error();
199
APR_DECLARE(apr_status_t) apr_uid_get(apr_uid_t *uid, apr_gid_t *gid,
200
const char *username, apr_pool_t *p)
205
SID_NAME_USE sidtype;
209
DWORD domlen = sizeof(anydomain);
213
if (pos = strchr(username, '/')) {
214
domain = apr_pstrndup(p, username, pos - username);
217
else if (pos = strchr(username, '\\')) {
218
domain = apr_pstrndup(p, username, pos - username);
224
/* Get nothing on the first pass ... need to size the sid buffer
226
rv = LookupAccountName(domain, username, domain, &sidlen,
227
anydomain, &domlen, &sidtype);
229
/* Give it back on the second pass
231
*uid = apr_palloc(p, sidlen);
232
domlen = sizeof(anydomain);
233
rv = LookupAccountName(domain, username, *uid, &sidlen,
234
anydomain, &domlen, &sidtype);
236
if (!sidlen || !rv) {
237
return apr_get_os_error();
239
/* There doesn't seem to be a simple way to retrieve the primary group sid
246
APR_DECLARE(apr_status_t) apr_uid_name_get(char **username, apr_uid_t userid,
250
*username = apr_pstrdup(p, "Administrator");
254
char name[MAX_PATH], domain[MAX_PATH];
255
DWORD cbname = sizeof(name), cbdomain = sizeof(domain);
258
if (!LookupAccountSid(NULL, userid, name, &cbname, domain, &cbdomain, &type))
259
return apr_get_os_error();
260
if (type != SidTypeUser && type != SidTypeAlias && type != SidTypeWellKnownGroup)
262
*username = apr_pstrdup(p, name);
267
APR_DECLARE(apr_status_t) apr_uid_compare(apr_uid_t left, apr_uid_t right)
272
if (!IsValidSid(left) || !IsValidSid(right))
274
if (!EqualSid(left, right))
275
return APR_EMISMATCH;