1 /* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
2 /* This Source Code Form is subject to the terms of the Mozilla Public
3 * License, v. 2.0. If a copy of the MPL was not distributed with this
4 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
11 * Implement the POSIX-style mode bits (access permissions) for
12 * files and other securable objects in Windows NT using Windows
13 * NT's security descriptors with appropriate discretionary
14 * access-control lists.
18 * The security identifiers (SIDs) for owner, primary group,
19 * and the Everyone (World) group.
21 * These SIDs are looked up during NSPR initialization and
22 * saved in this global structure (see _PR_NT_InitSids) so
23 * that _PR_NT_MakeSecurityDescriptorACL doesn't need to
24 * look them up every time.
33 * Initialize the SIDs for owner, primary group, and the Everyone
34 * group in the _pr_nt_sids structure.
36 * This function needs to be called by NSPR initialization.
38 void _PR_NT_InitSids(void) {
39 #ifdef WINCE /* not supported */
42 SID_IDENTIFIER_AUTHORITY SIDAuthWorld
= SECURITY_WORLD_SID_AUTHORITY
;
43 HANDLE hToken
= NULL
; /* initialized to an arbitrary value to
44 * silence a Purify UMR warning */
45 PSID infoBuffer
[1024 / sizeof(PSID
)]; /* defined as an array of PSIDs
46 * to force proper alignment */
47 PTOKEN_OWNER pTokenOwner
= (PTOKEN_OWNER
)infoBuffer
;
48 PTOKEN_PRIMARY_GROUP pTokenPrimaryGroup
= (PTOKEN_PRIMARY_GROUP
)infoBuffer
;
53 * Look up and make a copy of the owner and primary group
54 * SIDs in the access token of the calling process.
56 rv
= OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY
, &hToken
);
59 * On non-NT systems, this function is not implemented
60 * (error code ERROR_CALL_NOT_IMPLEMENTED), and neither are
61 * the other security functions. There is no point in
64 * A process with insufficient access permissions may fail
65 * with the error code ERROR_ACCESS_DENIED.
67 PR_LOG(_pr_io_lm
, PR_LOG_DEBUG
,
68 ("_PR_NT_InitSids: OpenProcessToken() failed. Error: %d",
73 rv
= GetTokenInformation(hToken
, TokenOwner
, infoBuffer
, sizeof(infoBuffer
),
76 dwLength
= GetLengthSid(pTokenOwner
->Owner
);
77 _pr_nt_sids
.owner
= (PSID
)PR_Malloc(dwLength
);
78 PR_ASSERT(_pr_nt_sids
.owner
!= NULL
);
79 rv
= CopySid(dwLength
, _pr_nt_sids
.owner
, pTokenOwner
->Owner
);
82 rv
= GetTokenInformation(hToken
, TokenPrimaryGroup
, infoBuffer
,
83 sizeof(infoBuffer
), &dwLength
);
85 dwLength
= GetLengthSid(pTokenPrimaryGroup
->PrimaryGroup
);
86 _pr_nt_sids
.group
= (PSID
)PR_Malloc(dwLength
);
87 PR_ASSERT(_pr_nt_sids
.group
!= NULL
);
88 rv
= CopySid(dwLength
, _pr_nt_sids
.group
, pTokenPrimaryGroup
->PrimaryGroup
);
91 rv
= CloseHandle(hToken
);
94 /* Create a well-known SID for the Everyone group. */
95 rv
= AllocateAndInitializeSid(&SIDAuthWorld
, 1, SECURITY_WORLD_RID
, 0, 0, 0,
96 0, 0, 0, 0, &_pr_nt_sids
.everyone
);
102 * Free the SIDs for owner, primary group, and the Everyone group
103 * in the _pr_nt_sids structure.
105 * This function needs to be called by NSPR cleanup.
107 void _PR_NT_FreeSids(void) {
111 if (_pr_nt_sids
.owner
) {
112 PR_Free(_pr_nt_sids
.owner
);
114 if (_pr_nt_sids
.group
) {
115 PR_Free(_pr_nt_sids
.group
);
117 if (_pr_nt_sids
.everyone
) {
118 FreeSid(_pr_nt_sids
.everyone
);
124 * Construct a security descriptor whose discretionary access-control
125 * list implements the specified mode bits. The SIDs for owner, group,
126 * and everyone are obtained from the global _pr_nt_sids structure.
127 * Both the security descriptor and access-control list are returned
128 * and should be freed by a _PR_NT_FreeSecurityDescriptorACL call.
130 * The accessTable array maps NSPR's read, write, and execute access
131 * rights to the corresponding NT access rights for the securable
134 PRStatus
_PR_NT_MakeSecurityDescriptorACL(PRIntn mode
, DWORD accessTable
[],
135 PSECURITY_DESCRIPTOR
* resultSD
,
138 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
141 PSECURITY_DESCRIPTOR pSD
= NULL
;
143 DWORD cbACL
; /* size of ACL */
146 if (_pr_nt_sids
.owner
== NULL
) {
147 PR_SetError(PR_NOT_IMPLEMENTED_ERROR
, 0);
151 pSD
= (PSECURITY_DESCRIPTOR
)PR_Malloc(SECURITY_DESCRIPTOR_MIN_LENGTH
);
153 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
156 if (!InitializeSecurityDescriptor(pSD
, SECURITY_DESCRIPTOR_REVISION
)) {
157 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
160 if (!SetSecurityDescriptorOwner(pSD
, _pr_nt_sids
.owner
, FALSE
)) {
161 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
164 if (!SetSecurityDescriptorGroup(pSD
, _pr_nt_sids
.group
, FALSE
)) {
165 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
170 * Construct a discretionary access-control list with three
171 * access-control entries, one each for owner, primary group,
175 cbACL
= sizeof(ACL
) + 3 * (sizeof(ACCESS_ALLOWED_ACE
) - sizeof(DWORD
)) +
176 GetLengthSid(_pr_nt_sids
.owner
) + GetLengthSid(_pr_nt_sids
.group
) +
177 GetLengthSid(_pr_nt_sids
.everyone
);
178 pACL
= (PACL
)PR_Malloc(cbACL
);
180 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
183 if (!InitializeAcl(pACL
, cbACL
, ACL_REVISION
)) {
184 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
189 accessMask
|= accessTable
[0];
192 accessMask
|= accessTable
[1];
195 accessMask
|= accessTable
[2];
198 !AddAccessAllowedAce(pACL
, ACL_REVISION
, accessMask
, _pr_nt_sids
.owner
)) {
199 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
204 accessMask
|= accessTable
[0];
207 accessMask
|= accessTable
[1];
210 accessMask
|= accessTable
[2];
213 !AddAccessAllowedAce(pACL
, ACL_REVISION
, accessMask
, _pr_nt_sids
.group
)) {
214 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
219 accessMask
|= accessTable
[0];
222 accessMask
|= accessTable
[1];
225 accessMask
|= accessTable
[2];
227 if (accessMask
&& !AddAccessAllowedAce(pACL
, ACL_REVISION
, accessMask
,
228 _pr_nt_sids
.everyone
)) {
229 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
233 if (!SetSecurityDescriptorDacl(pSD
, TRUE
, pACL
, FALSE
)) {
234 _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
254 * Free the specified security descriptor and access-control list
255 * previously created by _PR_NT_MakeSecurityDescriptorACL.
257 void _PR_NT_FreeSecurityDescriptorACL(PSECURITY_DESCRIPTOR pSD
, PACL pACL
) {