reindent-20030715
[openafs.git] / src / util / secutil_nt.c
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  * 
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 /* Security related utilities for the Windows platform */
11
12 #include <afs/param.h>
13 #include <afsconfig.h>
14
15 RCSID
16     ("$Header$");
17
18 #include <afs/stds.h>
19
20 #include <stddef.h>
21 #include <stdlib.h>
22 #include <errno.h>
23
24 #include <windows.h>
25 #include <aclapi.h>
26
27 #include "secutil_nt.h"
28
29
30
31 /* local declarations */
32
33 static BOOL WorldGroupSidAllocate(PSID * sidPP);
34
35 static BOOL LocalAdminsGroupSidAllocate(PSID * sidPP);
36
37 static void
38   BuildExplicitAccessWithSid(PEXPLICIT_ACCESS explicitAccessP,
39                              PSID trusteeSidP, DWORD accessPerm,
40                              ACCESS_MODE accessMode, DWORD inheritance);
41
42
43
44 /* --------------------  Exported functions ------------------------ */
45
46
47
48 /*
49  * ObjectDaclEntryAdd() -- add an access-control entry to an object's DACL.
50  *
51  *     Notes: The accessPerm, accessMode, and inheritance args must be correct
52  *                for an EXPLICIT_ACCESS structure describing a DACL entry.
53  *            Caller must have READ_CONTRL/WRITE_DAC rights for object handle.
54  *
55  * RETURN CODES: Win32 status code (ERROR_SUCCESS if succeeds)
56  */
57 DWORD
58 ObjectDaclEntryAdd(HANDLE objectHandle, SE_OBJECT_TYPE objectType,
59                    WELLKNOWN_TRUSTEE_ID trustee, DWORD accessPerm,
60                    ACCESS_MODE accessMode, DWORD inheritance)
61 {
62     DWORD status = ERROR_SUCCESS;
63     PSID trusteeSidP;
64
65     /* allocate SID for (well-known) trustee */
66
67     if (trustee == WorldGroup) {
68         if (!WorldGroupSidAllocate(&trusteeSidP)) {
69             status = GetLastError();
70         }
71     } else if (trustee == LocalAdministratorsGroup) {
72         if (!LocalAdminsGroupSidAllocate(&trusteeSidP)) {
73             status = GetLastError();
74         }
75     } else {
76         status = ERROR_INVALID_PARAMETER;
77     }
78
79     if (status == ERROR_SUCCESS) {
80         EXPLICIT_ACCESS accessEntry;
81         PACL curDaclP, newDaclP;
82         PSECURITY_DESCRIPTOR secP;
83
84         /* initialize access information for trustee */
85
86         BuildExplicitAccessWithSid(&accessEntry, trusteeSidP, accessPerm,
87                                    accessMode, inheritance);
88
89         /* get object's current DACL */
90
91         status =
92             GetSecurityInfo(objectHandle, objectType,
93                             DACL_SECURITY_INFORMATION, NULL, NULL, &curDaclP,
94                             NULL, &secP);
95
96         if (status == ERROR_SUCCESS) {
97             /* merge access information into current DACL to form new DACL */
98             status = SetEntriesInAcl(1, &accessEntry, curDaclP, &newDaclP);
99
100             if (status == ERROR_SUCCESS) {
101                 /* replace object's current DACL with newly formed DACL */
102
103                 /* MS SP4 introduced a bug into SetSecurityInfo() so that it
104                  * no longer operates correctly with named pipes.  Work around
105                  * this problem by using "low-level" access control functions
106                  * for kernel objects (of which named pipes are one example).
107                  */
108
109                 if (objectType != SE_KERNEL_OBJECT) {
110                     status =
111                         SetSecurityInfo(objectHandle, objectType,
112                                         DACL_SECURITY_INFORMATION, NULL, NULL,
113                                         newDaclP, NULL);
114                 } else {
115                     if (!SetSecurityDescriptorDacl
116                         (secP, TRUE, newDaclP, FALSE)
117                         || !SetKernelObjectSecurity(objectHandle,
118                                                     DACL_SECURITY_INFORMATION,
119                                                     secP)) {
120                         status = GetLastError();
121                     }
122                 }
123
124                 (void)LocalFree((HLOCAL) newDaclP);
125             }
126
127             (void)LocalFree((HLOCAL) secP);
128         }
129
130         FreeSid(trusteeSidP);
131     }
132
133     return status;
134 }
135
136
137
138
139 /* --------------------  Local functions ------------------------ */
140
141 /*
142  * WorldGroupSidAllocate() -- allocate and initialize SID for the
143  *     well-known World group representing all users.
144  *
145  *     SID is freed via FreeSid()
146  *
147  * RETURN CODES: TRUE success, FALSE failure  (GetLastError() indicates why)
148  */
149 static BOOL
150 WorldGroupSidAllocate(PSID * sidPP)
151 {
152     SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_WORLD_SID_AUTHORITY;
153
154     return AllocateAndInitializeSid(&sidAuth, 1, SECURITY_WORLD_RID, 0, 0, 0,
155                                     0, 0, 0, 0, sidPP);
156 }
157
158
159 /*
160  * LocalAdminsGroupSidAllocate() -- allocate and initialize SID for the
161  *     well-known local Administrators group.
162  *
163  *     SID is freed via FreeSid()
164  *
165  * RETURN CODES: TRUE success, FALSE failure  (GetLastError() indicates why)
166  */
167 static BOOL
168 LocalAdminsGroupSidAllocate(PSID * sidPP)
169 {
170     SID_IDENTIFIER_AUTHORITY sidAuth = SECURITY_NT_AUTHORITY;
171
172     return AllocateAndInitializeSid(&sidAuth, 2, SECURITY_BUILTIN_DOMAIN_RID,
173                                     DOMAIN_ALIAS_RID_ADMINS, 0, 0, 0, 0, 0, 0,
174                                     sidPP);
175 }
176
177
178 /*
179  * BuildExplicitAccessWithSid() - counterpart to the Win32 API function
180  *     BuildExplicitAccessWithName() (surprisingly, MS doesn't provide this).
181  */
182 static void
183 BuildExplicitAccessWithSid(PEXPLICIT_ACCESS explicitAccessP, PSID trusteeSidP,
184                            DWORD accessPerm, ACCESS_MODE accessMode,
185                            DWORD inheritance)
186 {
187     if (explicitAccessP != NULL) {
188         explicitAccessP->grfAccessPermissions = accessPerm;
189         explicitAccessP->grfAccessMode = accessMode;
190         explicitAccessP->grfInheritance = inheritance;
191         BuildTrusteeWithSid(&explicitAccessP->Trustee, trusteeSidP);
192     }
193 }