~ubuntu-branches/ubuntu/precise/kompozer/precise

« back to all changes in this revision

Viewing changes to mozilla/nsprpub/pr/src/md/windows/ntsec.c

  • Committer: Bazaar Package Importer
  • Author(s): Anthony Yarusso
  • Date: 2007-08-27 01:11:03 UTC
  • Revision ID: james.westby@ubuntu.com-20070827011103-2jgf4s6532gqu2ka
Tags: upstream-0.7.10
ImportĀ upstreamĀ versionĀ 0.7.10

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
 
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/
 
7
 * 
 
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.
 
12
 * 
 
13
 * The Original Code is the Netscape Portable Runtime (NSPR).
 
14
 * 
 
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
 
18
 * Rights Reserved.
 
19
 * 
 
20
 * Contributor(s):
 
21
 * 
 
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
 
32
 * GPL.
 
33
 */
 
34
 
 
35
#include "primpl.h"
 
36
 
 
37
/*
 
38
 * ntsec.c
 
39
 *
 
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.
 
44
 */
 
45
 
 
46
/*
 
47
 * The security identifiers (SIDs) for owner, primary group,
 
48
 * and the Everyone (World) group.
 
49
 *
 
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.
 
54
 */
 
55
static struct {
 
56
    PSID owner;
 
57
    PSID group;
 
58
    PSID everyone;
 
59
} _pr_nt_sids;
 
60
 
 
61
/*
 
62
 * Initialize the SIDs for owner, primary group, and the Everyone
 
63
 * group in the _pr_nt_sids structure.
 
64
 *
 
65
 * This function needs to be called by NSPR initialization.
 
66
 */
 
67
void _PR_NT_InitSids(void)
 
68
{
 
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;
 
76
    DWORD dwLength;
 
77
    BOOL rv;
 
78
 
 
79
    /*
 
80
     * Look up and make a copy of the owner and primary group
 
81
     * SIDs in the access token of the calling process.
 
82
     */
 
83
    rv = OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken);
 
84
    if (rv == 0) {
 
85
        /*
 
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
 
89
         * going further.
 
90
         *
 
91
         * A process with insufficient access permissions may fail
 
92
         * with the error code ERROR_ACCESS_DENIED.
 
93
         */
 
94
        PR_LOG(_pr_io_lm, PR_LOG_DEBUG,
 
95
                ("_PR_NT_InitSids: OpenProcessToken() failed. Error: %d",
 
96
                GetLastError()));
 
97
        return;
 
98
    }
 
99
 
 
100
    rv = GetTokenInformation(hToken, TokenOwner, infoBuffer,
 
101
            sizeof(infoBuffer), &dwLength);
 
102
    PR_ASSERT(rv != 0);
 
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);
 
107
    PR_ASSERT(rv != 0);
 
108
 
 
109
    rv = GetTokenInformation(hToken, TokenPrimaryGroup, infoBuffer,
 
110
            sizeof(infoBuffer), &dwLength);
 
111
    PR_ASSERT(rv != 0);
 
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);
 
117
    PR_ASSERT(rv != 0);
 
118
 
 
119
    rv = CloseHandle(hToken);
 
120
    PR_ASSERT(rv != 0);
 
121
 
 
122
    /* Create a well-known SID for the Everyone group. */
 
123
    rv = AllocateAndInitializeSid(&SIDAuthWorld, 1,
 
124
            SECURITY_WORLD_RID,
 
125
            0, 0, 0, 0, 0, 0, 0,
 
126
            &_pr_nt_sids.everyone);
 
127
    PR_ASSERT(rv != 0);
 
128
}
 
129
 
 
130
/*
 
131
 * Free the SIDs for owner, primary group, and the Everyone group
 
132
 * in the _pr_nt_sids structure.
 
133
 *
 
134
 * This function needs to be called by NSPR cleanup.
 
135
 */
 
136
void
 
137
_PR_NT_FreeSids(void)
 
138
{
 
139
    if (_pr_nt_sids.owner) {
 
140
        PR_Free(_pr_nt_sids.owner);
 
141
    }
 
142
    if (_pr_nt_sids.group) {
 
143
        PR_Free(_pr_nt_sids.group);
 
144
    }
 
145
    if (_pr_nt_sids.everyone) {
 
146
        FreeSid(_pr_nt_sids.everyone);
 
147
    }
 
148
}
 
149
 
 
150
/*
 
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.
 
156
 *
 
157
 * The accessTable array maps NSPR's read, write, and execute access
 
158
 * rights to the corresponding NT access rights for the securable
 
159
 * object.
 
160
 */
 
161
PRStatus
 
162
_PR_NT_MakeSecurityDescriptorACL(
 
163
    PRIntn mode,
 
164
    DWORD accessTable[],
 
165
    PSECURITY_DESCRIPTOR *resultSD,
 
166
    PACL *resultACL)
 
167
{
 
168
    PSECURITY_DESCRIPTOR pSD = NULL;
 
169
    PACL pACL = NULL;
 
170
    DWORD cbACL;  /* size of ACL */
 
171
    DWORD accessMask;
 
172
 
 
173
    if (_pr_nt_sids.owner == NULL) {
 
174
        PR_SetError(PR_NOT_IMPLEMENTED_ERROR, 0);
 
175
        return PR_FAILURE;
 
176
    }
 
177
 
 
178
    pSD = (PSECURITY_DESCRIPTOR) PR_Malloc(SECURITY_DESCRIPTOR_MIN_LENGTH);
 
179
    if (pSD == NULL) {
 
180
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
181
        goto failed;
 
182
    }
 
183
    if (!InitializeSecurityDescriptor(pSD, SECURITY_DESCRIPTOR_REVISION)) {
 
184
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
185
        goto failed;
 
186
    }
 
187
    if (!SetSecurityDescriptorOwner(pSD, _pr_nt_sids.owner, FALSE)) {
 
188
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
189
        goto failed;
 
190
    }
 
191
    if (!SetSecurityDescriptorGroup(pSD, _pr_nt_sids.group, FALSE)) {
 
192
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
193
        goto failed;
 
194
    }
 
195
 
 
196
    /*
 
197
     * Construct a discretionary access-control list with three
 
198
     * access-control entries, one each for owner, primary group,
 
199
     * and Everyone.
 
200
     */
 
201
 
 
202
    cbACL = sizeof(ACL)
 
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);
 
208
    if (pACL == NULL) {
 
209
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
210
        goto failed;
 
211
    }
 
212
    if (!InitializeAcl(pACL, cbACL, ACL_REVISION)) {
 
213
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
214
        goto failed;
 
215
    }
 
216
    accessMask = 0;
 
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());
 
223
        goto failed;
 
224
    }
 
225
    accessMask = 0;
 
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());
 
232
        goto failed;
 
233
    }
 
234
    accessMask = 0;
 
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());
 
241
        goto failed;
 
242
    }
 
243
 
 
244
    if (!SetSecurityDescriptorDacl(pSD, TRUE, pACL, FALSE)) {
 
245
        _PR_MD_MAP_DEFAULT_ERROR(GetLastError());
 
246
        goto failed;
 
247
    }
 
248
 
 
249
    *resultSD = pSD;
 
250
    *resultACL = pACL;
 
251
    return PR_SUCCESS;
 
252
 
 
253
failed:
 
254
    if (pSD) {
 
255
        PR_Free(pSD);
 
256
    }
 
257
    if (pACL) {
 
258
        PR_Free(pACL);
 
259
    }
 
260
    return PR_FAILURE;
 
261
}
 
262
 
 
263
/*
 
264
 * Free the specified security descriptor and access-control list
 
265
 * previously created by _PR_NT_MakeSecurityDescriptorACL.
 
266
 */
 
267
void
 
268
_PR_NT_FreeSecurityDescriptorACL(PSECURITY_DESCRIPTOR pSD, PACL pACL)
 
269
{
 
270
    if (pSD) {
 
271
        PR_Free(pSD);
 
272
    }
 
273
    if (pACL) {
 
274
        PR_Free(pACL);
 
275
    }
 
276
}