06f3f9195f94e2b7d5737421a5aeaf90d690e674
[kai/samba-autobuild/.git] / source3 / services / svc_winreg_glue.c
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 struct security_descriptor* svcctl_gen_service_sd(TALLOC_CTX *mem_ctx)
35 {
36         struct security_descriptor *sd = NULL;
37         struct security_acl *theacl = NULL;
38         struct security_ace ace[4];
39         size_t sd_size;
40         size_t i = 0;
41
42         /* Basic access for everyone */
43         init_sec_ace(&ace[i++], &global_sid_World,
44                 SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_READ_ACCESS, 0);
45
46         init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users,
47                         SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_EXECUTE_ACCESS, 0);
48
49         init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators,
50                 SEC_ACE_TYPE_ACCESS_ALLOWED, SERVICE_ALL_ACCESS, 0);
51         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         theacl = make_sec_acl(mem_ctx,
56                               NT4_ACL_REVISION,
57                               i,
58                               ace);
59         if (theacl == NULL) {
60                 return NULL;
61         }
62
63         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         if (sd == NULL) {
72                 return NULL;
73         }
74
75         return sd;
76 }
77
78 struct security_descriptor *svcctl_get_secdesc(TALLOC_CTX *mem_ctx,
79                                                struct messaging_context *msg_ctx,
80                                                const struct auth_serversupplied_info *session_info,
81                                                const char *name)
82 {
83         struct dcerpc_binding_handle *h = NULL;
84         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
85         struct policy_handle hive_hnd, key_hnd;
86         struct security_descriptor *sd = NULL;
87         char *key = NULL;
88         NTSTATUS status;
89         WERROR result = WERR_OK;
90
91         key = talloc_asprintf(mem_ctx,
92                               "%s\\%s\\Security",
93                               TOP_LEVEL_SERVICES_KEY, name);
94         if (key == NULL) {
95                 return NULL;
96         }
97
98         status = dcerpc_winreg_int_hklm_openkey(mem_ctx,
99                                                 session_info,
100                                                 msg_ctx,
101                                                 &h,
102                                                 key,
103                                                 false,
104                                                 access_mask,
105                                                 &hive_hnd,
106                                                 &key_hnd,
107                                                 &result);
108         if (!NT_STATUS_IS_OK(status)) {
109                 DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n",
110                           key, nt_errstr(status)));
111                 return NULL;
112         }
113         if (!W_ERROR_IS_OK(result)) {
114                 DEBUG(2, ("svcctl_set_secdesc: Could not open %s - %s\n",
115                           key, win_errstr(result)));
116                 return NULL;
117         }
118
119         status = dcerpc_winreg_query_sd(mem_ctx,
120                                         h,
121                                         &key_hnd,
122                                         "Security",
123                                         &sd,
124                                         &result);
125         if (!NT_STATUS_IS_OK(status)) {
126                 DEBUG(2, ("svcctl_get_secdesc: error getting value 'Security': "
127                           "%s\n", nt_errstr(status)));
128                 return NULL;
129         }
130         if (W_ERROR_EQUAL(result, WERR_BADFILE)) {
131                 goto fallback_to_default_sd;
132         } else if (!W_ERROR_IS_OK(result)) {
133                 DEBUG(2, ("svcctl_get_secdesc: error getting value 'Security': "
134                           "%s\n", win_errstr(result)));
135                 return NULL;
136         }
137
138         goto done;
139
140 fallback_to_default_sd:
141         DEBUG(6, ("svcctl_get_secdesc: constructing default secdesc for "
142                   "service [%s]\n", name));
143         sd = svcctl_gen_service_sd(mem_ctx);
144
145 done:
146         return sd;
147 }
148
149 bool svcctl_set_secdesc(struct messaging_context *msg_ctx,
150                         const struct auth_serversupplied_info *session_info,
151                         const char *name,
152                         struct security_descriptor *sd)
153 {
154         struct dcerpc_binding_handle *h = NULL;
155         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
156         struct policy_handle hive_hnd;
157         struct policy_handle key_hnd = { 0, };
158         char *key = NULL;
159         bool ok = false;
160         TALLOC_CTX *tmp_ctx;
161         NTSTATUS status;
162         WERROR result = WERR_OK;
163
164         tmp_ctx = talloc_stackframe();
165         if (tmp_ctx == NULL) {
166                 return false;
167         }
168
169         key = talloc_asprintf(tmp_ctx, "%s\\%s", TOP_LEVEL_SERVICES_KEY, name);
170         if (key == NULL) {
171                 goto done;
172         }
173
174         status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
175                                                 session_info,
176                                                 msg_ctx,
177                                                 &h,
178                                                 key,
179                                                 false,
180                                                 access_mask,
181                                                 &hive_hnd,
182                                                 &key_hnd,
183                                                 &result);
184         if (!NT_STATUS_IS_OK(status)) {
185                 DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
186                           key, nt_errstr(status)));
187                 goto done;
188         }
189         if (!W_ERROR_IS_OK(result)) {
190                 DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
191                           key, win_errstr(result)));
192                 goto done;
193         }
194
195         if (is_valid_policy_hnd(&key_hnd)) {
196                 dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
197         }
198
199         {
200                 enum winreg_CreateAction action = REG_ACTION_NONE;
201                 struct winreg_String wkey = { 0, };
202                 struct winreg_String wkeyclass;
203
204                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\Security", key);
205                 if (wkey.name == NULL) {
206                         result = WERR_NOMEM;
207                         goto done;
208                 }
209
210                 ZERO_STRUCT(wkeyclass);
211                 wkeyclass.name = "";
212
213                 status = dcerpc_winreg_CreateKey(h,
214                                                  tmp_ctx,
215                                                  &hive_hnd,
216                                                  wkey,
217                                                  wkeyclass,
218                                                  0,
219                                                  access_mask,
220                                                  NULL,
221                                                  &key_hnd,
222                                                  &action,
223                                                  &result);
224                 if (!NT_STATUS_IS_OK(status)) {
225                         DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
226                                 wkey.name, nt_errstr(status)));
227                         goto done;
228                 }
229                 if (!W_ERROR_IS_OK(result)) {
230                         DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
231                                 wkey.name, win_errstr(result)));
232                         goto done;
233                 }
234
235                 status = dcerpc_winreg_set_sd(tmp_ctx,
236                                               h,
237                                               &key_hnd,
238                                               "Security",
239                                               sd,
240                                               &result);
241                 if (!NT_STATUS_IS_OK(status)) {
242                         goto done;
243                 }
244                 if (!W_ERROR_IS_OK(result)) {
245                         goto done;
246                 }
247         }
248
249         ok = true;
250
251 done:
252         if (is_valid_policy_hnd(&key_hnd)) {
253                 dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
254         }
255
256         talloc_free(tmp_ctx);
257         return ok;
258 }
259
260 const char *svcctl_get_string_value(TALLOC_CTX *mem_ctx,
261                                     struct messaging_context *msg_ctx,
262                                     const struct auth_serversupplied_info *session_info,
263                                     const char *key_name,
264                                     const char *value_name)
265 {
266         struct dcerpc_binding_handle *h = NULL;
267         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
268         struct policy_handle hive_hnd, key_hnd;
269         const char *data = NULL;
270         char *path = NULL;
271         TALLOC_CTX *tmp_ctx;
272         NTSTATUS status;
273         WERROR result = WERR_OK;
274
275         tmp_ctx = talloc_stackframe();
276         if (tmp_ctx == NULL) {
277                 return NULL;
278         }
279
280         path = talloc_asprintf(tmp_ctx, "%s\\%s",
281                                         TOP_LEVEL_SERVICES_KEY, key_name);
282         if (path == NULL) {
283                 goto done;
284         }
285
286         status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
287                                                 session_info,
288                                                 msg_ctx,
289                                                 &h,
290                                                 path,
291                                                 false,
292                                                 access_mask,
293                                                 &hive_hnd,
294                                                 &key_hnd,
295                                                 &result);
296         if (!NT_STATUS_IS_OK(status)) {
297                 DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
298                           path, nt_errstr(status)));
299                 goto done;
300         }
301         if (!W_ERROR_IS_OK(result)) {
302                 DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
303                           path, win_errstr(result)));
304                 goto done;
305         }
306
307         status = dcerpc_winreg_query_sz(mem_ctx,
308                                         h,
309                                         &key_hnd,
310                                         value_name,
311                                         &data,
312                                         &result);
313
314 done:
315         talloc_free(tmp_ctx);
316         return data;
317 }
318
319 /********************************************************************
320 ********************************************************************/
321
322 const char *svcctl_lookup_dispname(TALLOC_CTX *mem_ctx,
323                                    struct messaging_context *msg_ctx,
324                                    const struct auth_serversupplied_info *session_info,
325                                    const char *name)
326 {
327         const char *display_name = NULL;
328
329         display_name = svcctl_get_string_value(mem_ctx,
330                                                msg_ctx,
331                                                session_info,
332                                                name,
333                                                "DisplayName");
334
335         if (display_name == NULL) {
336                 display_name = talloc_strdup(mem_ctx, name);
337         }
338
339         return display_name;
340 }
341
342 /********************************************************************
343 ********************************************************************/
344
345 const char *svcctl_lookup_description(TALLOC_CTX *mem_ctx,
346                                       struct messaging_context *msg_ctx,
347                                       const struct auth_serversupplied_info *session_info,
348                                       const char *name)
349 {
350         const char *description = NULL;
351
352         description = svcctl_get_string_value(mem_ctx,
353                                               msg_ctx,
354                                               session_info,
355                                               name,
356                                               "Description");
357
358         if (description == NULL) {
359                 description = talloc_strdup(mem_ctx, "Unix Service");
360         }
361
362         return description;
363 }
364
365 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */