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