1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
3
* The contents of this file are subject to the Mozilla Public
4
* License Version 1.1 (the "License"); you may not use this file
5
* except in compliance with the License. You may obtain a copy of
6
* the License at http://www.mozilla.org/MPL/
8
* Software distributed under the License is distributed on an "AS
9
* IS" basis, WITHOUT WARRANTY OF ANY KIND, either express or
10
* implied. See the License for the specific language governing
11
* rights and limitations under the License.
13
* The Original Code is the Netscape Portable Runtime (NSPR).
15
* The Initial Developer of the Original Code is Netscape
16
* Communications Corporation. Portions created by Netscape are
17
* Copyright (C) 2000 Netscape Communications Corporation. All
22
* Alternatively, the contents of this file may be used under the
23
* terms of the GNU General Public License Version 2 or later (the
24
* "GPL"), in which case the provisions of the GPL are applicable
25
* instead of those above. If you wish to allow use of your
26
* version of this file only under the terms of the GPL and not to
27
* allow others to use your version of this file under the MPL,
28
* indicate your decision by deleting the provisions above and
29
* replace them with the notice and other provisions required by
30
* the GPL. If you do not delete the provisions above, a recipient
31
* may use your version of this file under either the MPL or the
40
* Implement the POSIX-style mode bits (access permissions) for
41
* files and other securable objects in Windows NT using Windows
42
* NT's security descriptors with appropriate discretionary
43
* access-control lists.
47
* The security identifiers (SIDs) for owner, primary group,
48
* and the Everyone (World) group.
50
* These SIDs are looked up during NSPR initialization and
51
* saved in this global structure (see _PR_NT_InitSids) so
52
* that _PR_NT_MakeSecurityDescriptorACL doesn't need to
53
* look them up every time.
62
* Initialize the SIDs for owner, primary group, and the Everyone
63
* group in the _pr_nt_sids structure.
65
* This function needs to be called by NSPR initialization.
67
void _PR_NT_InitSids(void)
69
SID_IDENTIFIER_AUTHORITY SIDAuthWorld = SECURITY_WORLD_SID_AUTHORITY;
70
HANDLE hToken = NULL; /* initialized to an arbitrary value to
71
* silence a Purify UMR warning */
72
UCHAR infoBuffer[1024];
73
PTOKEN_OWNER pTokenOwner = (PTOKEN_OWNER) infoBuffer;
74
PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup
75
= (PTOKEN_PRIMARY_GROUP) infoBuffer;
80
* Look up and make a copy of the owner and primary group
81
* SIDs in the access token of the calling process.
83
rv = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
86
* On non-NT systems, this function is not implemented
87
* (error code ERROR_CALL_NOT_IMPLEMENTED), and neither are
88
* the other security functions. There is no point in
91
* A process with insufficient access permissions may fail
92
* with the error code ERROR_ACCESS_DENIED.
94
PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
95
("_PR_NT_InitSids: OpenProcessToken() failed. Error: %d",
100
rv = GetTokenInformation(hToken, TokenOwner, infoBuffer,
101
sizeof(infoBuffer), &dwLength);
103
dwLength = GetLengthSid(pTokenOwner->Owner);
104
_pr_nt_sids.owner = (PSID) PR_Malloc(dwLength);
105
PR_ASSERT(_pr_nt_sids.owner != NULL);
106
rv = CopySid(dwLength, _pr_nt_sids.owner, pTokenOwner->Owner);
109
rv = GetTokenInformation(hToken, TokenPrimaryGroup, infoBuffer,
110
sizeof(infoBuffer), &dwLength);
112
dwLength = GetLengthSid(pTokenPrimaryGroup->PrimaryGroup);
113
_pr_nt_sids.group = (PSID) PR_Malloc(dwLength);
114
PR_ASSERT(_pr_nt_sids.group != NULL);
115
rv = CopySid(dwLength, _pr_nt_sids.group,
116
pTokenPrimaryGroup->PrimaryGroup);
119
rv = CloseHandle(hToken);
122
/* Create a well-known SID for the Everyone group. */
123
rv = AllocateAndInitializeSid(&SIDAuthWorld, 1,
126
&_pr_nt_sids.everyone);
131
* Free the SIDs for owner, primary group, and the Everyone group
132
* in the _pr_nt_sids structure.
134
* This function needs to be called by NSPR cleanup.
137
_PR_NT_FreeSids(void)
139
if (_pr_nt_sids.owner) {
140
PR_Free(_pr_nt_sids.owner);
142
if (_pr_nt_sids.group) {
143
PR_Free(_pr_nt_sids.group);
145
if (_pr_nt_sids.everyone) {
146
FreeSid(_pr_nt_sids.everyone);
151
* Construct a security descriptor whose discretionary access-control
152
* list implements the specified mode bits. The SIDs for owner, group,
153
* and everyone are obtained from the global _pr_nt_sids structure.
154
* Both the security descriptor and access-control list are returned
155
* and should be freed by a _PR_NT_FreeSecurityDescriptorACL call.
157
* The accessTable array maps NSPR's read, write, and execute access
158
* rights to the corresponding NT access rights for the securable
162
_PR_NT_MakeSecurityDescriptorACL(
165
PSECURITY_DESCRIPTOR *resultSD,
168
PSECURITY_DESCRIPTOR pSD = NULL;
170
DWORD cbACL; /* size of ACL */
173
if (_pr_nt_sids.owner == NULL) {
174
PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
178
pSD = (PSECURITY_DESCRIPTOR) PR_Malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
180
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
183
if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
184
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
187
if (!SetSecurityDescriptorOwner(pSD, _pr_nt_sids.owner, FALSE)) {
188
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
191
if (!SetSecurityDescriptorGroup(pSD, _pr_nt_sids.group, FALSE)) {
192
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
197
* Construct a discretionary access-control list with three
198
* access-control entries, one each for owner, primary group,
203
+ 3 * (sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD))
204
+ GetLengthSid(_pr_nt_sids.owner)
205
+ GetLengthSid(_pr_nt_sids.group)
206
+ GetLengthSid(_pr_nt_sids.everyone);
207
pACL = (PACL) PR_Malloc(cbACL);
209
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
212
if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
213
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
217
if (mode & 00400) accessMask |= accessTable[0];
218
if (mode & 00200) accessMask |= accessTable[1];
219
if (mode & 00100) accessMask |= accessTable[2];
220
if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask,
221
_pr_nt_sids.owner)) {
222
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
226
if (mode & 00040) accessMask |= accessTable[0];
227
if (mode & 00020) accessMask |= accessTable[1];
228
if (mode & 00010) accessMask |= accessTable[2];
229
if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask,
230
_pr_nt_sids.group)) {
231
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
235
if (mode & 00004) accessMask |= accessTable[0];
236
if (mode & 00002) accessMask |= accessTable[1];
237
if (mode & 00001) accessMask |= accessTable[2];
238
if (accessMask && !AddAccessAllowedAce(pACL, ACL_REVISION, accessMask,
239
_pr_nt_sids.everyone)) {
240
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
244
if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) {
245
_PR_MD_MAP_DEFAULT_ERROR(GetLastError());
264
* Free the specified security descriptor and access-control list
265
* previously created by _PR_NT_MakeSecurityDescriptorACL.
268
_PR_NT_FreeSecurityDescriptorACL(PSECURITY_DESCRIPTOR pSD, PACL pACL)