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