Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : *
4 : * SVC winreg glue
5 : *
6 : * Copyright (c) 2005 Marcin Krzysztof Porwit
7 : * Copyright (c) 2005 Gerald (Jerry) Carter
8 : * Copyright (c) 2011 Andreas Schneider <asn@samba.org>
9 : *
10 : * This program is free software; you can redistribute it and/or modify
11 : * it under the terms of the GNU General Public License as published by
12 : * the Free Software Foundation; either version 3 of the License, or
13 : * (at your option) any later version.
14 : *
15 : * This program is distributed in the hope that it will be useful,
16 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 : * GNU General Public License for more details.
19 : *
20 : * You should have received a copy of the GNU General Public License
21 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
22 : */
23 :
24 : #include "includes.h"
25 : #include "services/services.h"
26 : #include "services/svc_winreg_glue.h"
27 : #include "rpc_client/cli_winreg_int.h"
28 : #include "rpc_client/cli_winreg.h"
29 : #include "../librpc/gen_ndr/ndr_winreg_c.h"
30 : #include "../libcli/security/security.h"
31 :
32 : #define TOP_LEVEL_SERVICES_KEY "SYSTEM\\CurrentControlSet\\Services"
33 :
34 504 : struct security_descriptor* svcctl_gen_service_sd(TALLOC_CTX *mem_ctx)
35 : {
36 504 : struct security_descriptor *sd = NULL;
37 504 : struct security_acl *theacl = NULL;
38 0 : struct security_ace ace[4];
39 0 : size_t sd_size;
40 504 : size_t i = 0;
41 :
42 : /* Basic access for everyone */
43 504 : init_sec_ace(&ace[i++], &global_sid_World,
44 : SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_READ_ACCESS, 0);
45 :
46 504 : init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users,
47 : SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_EXECUTE_ACCESS, 0);
48 :
49 504 : init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators,
50 : SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
51 504 : init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
52 : SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
53 :
54 : /* Create the security descriptor */
55 504 : theacl = make_sec_acl(mem_ctx,
56 : NT4_ACL_REVISION,
57 : i,
58 : ace);
59 504 : if (theacl == NULL) {
60 0 : return NULL;
61 : }
62 :
63 504 : sd = make_sec_desc(mem_ctx,
64 : SECURITY_DESCRIPTOR_REVISION_1,
65 : SEC_DESC_SELF_RELATIVE,
66 : NULL,
67 : NULL,
68 : NULL,
69 : theacl,
70 : &sd_size);
71 504 : if (sd == NULL) {
72 0 : return NULL;
73 : }
74 :
75 504 : return sd;
76 : }
77 :
78 64 : WERROR svcctl_get_secdesc(struct messaging_context *msg_ctx,
79 : const struct auth_session_info *session_info,
80 : const char *name,
81 : TALLOC_CTX *mem_ctx,
82 : struct security_descriptor **psd)
83 : {
84 64 : struct dcerpc_binding_handle *h = NULL;
85 64 : uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
86 0 : struct policy_handle hive_hnd, key_hnd;
87 64 : struct security_descriptor *sd = NULL;
88 64 : char *key = NULL;
89 0 : NTSTATUS status;
90 64 : WERROR result = WERR_OK;
91 :
92 64 : key = talloc_asprintf(mem_ctx,
93 : "%s\\%s\\Security",
94 : TOP_LEVEL_SERVICES_KEY, name);
95 64 : if (key == NULL) {
96 0 : return WERR_NOT_ENOUGH_MEMORY;
97 : }
98 :
99 64 : status = dcerpc_winreg_int_hklm_openkey(mem_ctx,
100 : session_info,
101 : msg_ctx,
102 : &h,
103 : key,
104 : false,
105 : access_mask,
106 : &hive_hnd,
107 : &key_hnd,
108 : &result);
109 64 : if (!NT_STATUS_IS_OK(status)) {
110 0 : DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n",
111 : key, nt_errstr(status)));
112 0 : return WERR_INTERNAL_ERROR;
113 : }
114 64 : if (!W_ERROR_IS_OK(result)) {
115 0 : DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n",
116 : key, win_errstr(result)));
117 0 : return result;
118 : }
119 :
120 64 : status = dcerpc_winreg_query_sd(mem_ctx,
121 : h,
122 : &key_hnd,
123 : "Security",
124 : &sd,
125 : &result);
126 64 : if (!NT_STATUS_IS_OK(status)) {
127 0 : DEBUG(2, ("svcctl_get_secdesc: error getting value 'Security': "
128 : "%s\n", nt_errstr(status)));
129 0 : return WERR_INTERNAL_ERROR;
130 : }
131 64 : if (W_ERROR_EQUAL(result, WERR_FILE_NOT_FOUND)) {
132 0 : goto fallback_to_default_sd;
133 64 : } else if (!W_ERROR_IS_OK(result)) {
134 0 : DEBUG(2, ("svcctl_get_secdesc: error getting value 'Security': "
135 : "%s\n", win_errstr(result)));
136 0 : return result;
137 : }
138 :
139 64 : goto done;
140 :
141 0 : fallback_to_default_sd:
142 0 : DEBUG(6, ("svcctl_get_secdesc: constructing default secdesc for "
143 : "service [%s]\n", name));
144 0 : sd = svcctl_gen_service_sd(mem_ctx);
145 0 : if (sd == NULL) {
146 0 : return WERR_NOT_ENOUGH_MEMORY;
147 : }
148 :
149 0 : done:
150 64 : *psd = sd;
151 64 : return WERR_OK;
152 : }
153 :
154 4 : bool svcctl_set_secdesc(struct messaging_context *msg_ctx,
155 : const struct auth_session_info *session_info,
156 : const char *name,
157 : struct security_descriptor *sd)
158 : {
159 4 : struct dcerpc_binding_handle *h = NULL;
160 4 : uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
161 0 : struct policy_handle hive_hnd;
162 4 : struct policy_handle key_hnd = { 0, };
163 4 : char *key = NULL;
164 4 : bool ok = false;
165 0 : TALLOC_CTX *tmp_ctx;
166 0 : NTSTATUS status;
167 4 : WERROR result = WERR_OK;
168 :
169 4 : tmp_ctx = talloc_stackframe();
170 4 : if (tmp_ctx == NULL) {
171 0 : return false;
172 : }
173 :
174 4 : key = talloc_asprintf(tmp_ctx, "%s\\%s", TOP_LEVEL_SERVICES_KEY, name);
175 4 : if (key == NULL) {
176 0 : goto done;
177 : }
178 :
179 4 : status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
180 : session_info,
181 : msg_ctx,
182 : &h,
183 : key,
184 : false,
185 : access_mask,
186 : &hive_hnd,
187 : &key_hnd,
188 : &result);
189 4 : if (!NT_STATUS_IS_OK(status)) {
190 0 : DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
191 : key, nt_errstr(status)));
192 0 : goto done;
193 : }
194 4 : if (!W_ERROR_IS_OK(result)) {
195 0 : DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
196 : key, win_errstr(result)));
197 0 : goto done;
198 : }
199 :
200 4 : if (is_valid_policy_hnd(&key_hnd)) {
201 4 : dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
202 : }
203 :
204 : {
205 4 : enum winreg_CreateAction action = REG_ACTION_NONE;
206 4 : struct winreg_String wkey = { 0, };
207 0 : struct winreg_String wkeyclass;
208 :
209 4 : wkey.name = talloc_asprintf(tmp_ctx, "%s\\Security", key);
210 4 : if (wkey.name == NULL) {
211 0 : result = WERR_NOT_ENOUGH_MEMORY;
212 0 : goto done;
213 : }
214 :
215 4 : ZERO_STRUCT(wkeyclass);
216 4 : wkeyclass.name = "";
217 :
218 4 : status = dcerpc_winreg_CreateKey(h,
219 : tmp_ctx,
220 : &hive_hnd,
221 : wkey,
222 : wkeyclass,
223 : 0,
224 : access_mask,
225 : NULL,
226 : &key_hnd,
227 : &action,
228 : &result);
229 4 : if (!NT_STATUS_IS_OK(status)) {
230 0 : DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
231 : wkey.name, nt_errstr(status)));
232 0 : goto done;
233 : }
234 4 : if (!W_ERROR_IS_OK(result)) {
235 0 : DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
236 : wkey.name, win_errstr(result)));
237 0 : goto done;
238 : }
239 :
240 4 : status = dcerpc_winreg_set_sd(tmp_ctx,
241 : h,
242 : &key_hnd,
243 : "Security",
244 : sd,
245 : &result);
246 4 : if (!NT_STATUS_IS_OK(status)) {
247 0 : goto done;
248 : }
249 4 : if (!W_ERROR_IS_OK(result)) {
250 0 : goto done;
251 : }
252 : }
253 :
254 4 : ok = true;
255 :
256 4 : done:
257 4 : if (is_valid_policy_hnd(&key_hnd)) {
258 4 : dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
259 : }
260 :
261 4 : talloc_free(tmp_ctx);
262 4 : return ok;
263 : }
264 :
265 88 : const char *svcctl_get_string_value(TALLOC_CTX *mem_ctx,
266 : struct messaging_context *msg_ctx,
267 : const struct auth_session_info *session_info,
268 : const char *key_name,
269 : const char *value_name)
270 : {
271 88 : struct dcerpc_binding_handle *h = NULL;
272 88 : uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
273 0 : struct policy_handle hive_hnd, key_hnd;
274 88 : const char *data = NULL;
275 88 : char *path = NULL;
276 0 : TALLOC_CTX *tmp_ctx;
277 0 : NTSTATUS status;
278 88 : WERROR result = WERR_OK;
279 :
280 88 : tmp_ctx = talloc_stackframe();
281 88 : if (tmp_ctx == NULL) {
282 0 : return NULL;
283 : }
284 :
285 88 : path = talloc_asprintf(tmp_ctx, "%s\\%s",
286 : TOP_LEVEL_SERVICES_KEY, key_name);
287 88 : if (path == NULL) {
288 0 : goto done;
289 : }
290 :
291 88 : status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
292 : session_info,
293 : msg_ctx,
294 : &h,
295 : path,
296 : false,
297 : access_mask,
298 : &hive_hnd,
299 : &key_hnd,
300 : &result);
301 88 : if (!NT_STATUS_IS_OK(status)) {
302 0 : DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
303 : path, nt_errstr(status)));
304 0 : goto done;
305 : }
306 88 : if (!W_ERROR_IS_OK(result)) {
307 0 : DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
308 : path, win_errstr(result)));
309 0 : goto done;
310 : }
311 :
312 88 : status = dcerpc_winreg_query_sz(mem_ctx,
313 : h,
314 : &key_hnd,
315 : value_name,
316 : &data,
317 : &result);
318 :
319 88 : done:
320 88 : talloc_free(tmp_ctx);
321 88 : return data;
322 : }
323 :
324 : /********************************************************************
325 : ********************************************************************/
326 :
327 48 : const char *svcctl_lookup_dispname(TALLOC_CTX *mem_ctx,
328 : struct messaging_context *msg_ctx,
329 : const struct auth_session_info *session_info,
330 : const char *name)
331 : {
332 48 : const char *display_name = NULL;
333 :
334 48 : display_name = svcctl_get_string_value(mem_ctx,
335 : msg_ctx,
336 : session_info,
337 : name,
338 : "DisplayName");
339 :
340 48 : if (display_name == NULL) {
341 0 : display_name = talloc_strdup(mem_ctx, name);
342 : }
343 :
344 48 : return display_name;
345 : }
346 :
347 : /********************************************************************
348 : ********************************************************************/
349 :
350 8 : const char *svcctl_lookup_description(TALLOC_CTX *mem_ctx,
351 : struct messaging_context *msg_ctx,
352 : const struct auth_session_info *session_info,
353 : const char *name)
354 : {
355 8 : const char *description = NULL;
356 :
357 8 : description = svcctl_get_string_value(mem_ctx,
358 : msg_ctx,
359 : session_info,
360 : name,
361 : "Description");
362 :
363 8 : if (description == NULL) {
364 0 : description = talloc_strdup(mem_ctx, "Unix Service");
365 : }
366 :
367 8 : return description;
368 : }
369 :
370 : /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */
|