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