65f03881674a319ba3ee5b80e7cba5db21b467df
[kai/samba.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, key_hnd;
157         char *key = NULL;
158         bool ok = false;
159         TALLOC_CTX *tmp_ctx;
160         NTSTATUS status;
161         WERROR result = WERR_OK;
162
163         tmp_ctx = talloc_stackframe();
164         if (tmp_ctx == NULL) {
165                 return false;
166         }
167
168         key = talloc_asprintf(tmp_ctx, "%s\\%s", TOP_LEVEL_SERVICES_KEY, name);
169         if (key == NULL) {
170                 goto done;
171         }
172
173         status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
174                                                 session_info,
175                                                 msg_ctx,
176                                                 &h,
177                                                 key,
178                                                 false,
179                                                 access_mask,
180                                                 &hive_hnd,
181                                                 &key_hnd,
182                                                 &result);
183         if (!NT_STATUS_IS_OK(status)) {
184                 DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
185                           key, nt_errstr(status)));
186                 goto done;
187         }
188         if (!W_ERROR_IS_OK(result)) {
189                 DEBUG(0, ("svcctl_set_secdesc: Could not open %s - %s\n",
190                           key, win_errstr(result)));
191                 goto done;
192         }
193
194         if (is_valid_policy_hnd(&key_hnd)) {
195                 dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
196         }
197
198         {
199                 enum winreg_CreateAction action = REG_ACTION_NONE;
200                 struct winreg_String wkey;
201                 struct winreg_String wkeyclass;
202
203                 wkey.name = talloc_asprintf(tmp_ctx, "%s\\Security", key);
204                 if (wkey.name == NULL) {
205                         result = WERR_NOMEM;
206                         goto done;
207                 }
208
209                 ZERO_STRUCT(wkeyclass);
210                 wkeyclass.name = "";
211
212                 status = dcerpc_winreg_CreateKey(h,
213                                                  tmp_ctx,
214                                                  &hive_hnd,
215                                                  wkey,
216                                                  wkeyclass,
217                                                  0,
218                                                  access_mask,
219                                                  NULL,
220                                                  &key_hnd,
221                                                  &action,
222                                                  &result);
223                 if (!NT_STATUS_IS_OK(status)) {
224                         DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
225                                 wkey.name, nt_errstr(status)));
226                         goto done;
227                 }
228                 if (!W_ERROR_IS_OK(result)) {
229                         DEBUG(2, ("svcctl_set_secdesc: Could not create key %s: %s\n",
230                                 wkey.name, win_errstr(result)));
231                         goto done;
232                 }
233
234                 status = dcerpc_winreg_set_sd(tmp_ctx,
235                                               h,
236                                               &key_hnd,
237                                               "Security",
238                                               sd,
239                                               &result);
240                 if (!NT_STATUS_IS_OK(status)) {
241                         goto done;
242                 }
243                 if (!W_ERROR_IS_OK(result)) {
244                         goto done;
245                 }
246         }
247
248         ok = true;
249
250 done:
251         if (is_valid_policy_hnd(&key_hnd)) {
252                 dcerpc_winreg_CloseKey(h, tmp_ctx, &key_hnd, &result);
253         }
254
255         talloc_free(tmp_ctx);
256         return ok;
257 }
258
259 const char *svcctl_get_string_value(TALLOC_CTX *mem_ctx,
260                                     struct messaging_context *msg_ctx,
261                                     const struct auth_serversupplied_info *session_info,
262                                     const char *key_name,
263                                     const char *value_name)
264 {
265         struct dcerpc_binding_handle *h = NULL;
266         uint32_t access_mask = SEC_FLAG_MAXIMUM_ALLOWED;
267         struct policy_handle hive_hnd, key_hnd;
268         const char *data = NULL;
269         char *path = NULL;
270         TALLOC_CTX *tmp_ctx;
271         NTSTATUS status;
272         WERROR result = WERR_OK;
273
274         tmp_ctx = talloc_stackframe();
275         if (tmp_ctx == NULL) {
276                 return NULL;
277         }
278
279         path = talloc_asprintf(tmp_ctx, "%s\\%s",
280                                         TOP_LEVEL_SERVICES_KEY, key_name);
281         if (path == NULL) {
282                 goto done;
283         }
284
285         status = dcerpc_winreg_int_hklm_openkey(tmp_ctx,
286                                                 session_info,
287                                                 msg_ctx,
288                                                 &h,
289                                                 path,
290                                                 false,
291                                                 access_mask,
292                                                 &hive_hnd,
293                                                 &key_hnd,
294                                                 &result);
295         if (!NT_STATUS_IS_OK(status)) {
296                 DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
297                           path, nt_errstr(status)));
298                 goto done;
299         }
300         if (!W_ERROR_IS_OK(result)) {
301                 DEBUG(2, ("svcctl_get_string_value: Could not open %s - %s\n",
302                           path, win_errstr(result)));
303                 goto done;
304         }
305
306         status = dcerpc_winreg_query_sz(mem_ctx,
307                                         h,
308                                         &key_hnd,
309                                         value_name,
310                                         &data,
311                                         &result);
312
313 done:
314         talloc_free(tmp_ctx);
315         return data;
316 }
317
318 /********************************************************************
319 ********************************************************************/
320
321 const char *svcctl_lookup_dispname(TALLOC_CTX *mem_ctx,
322                                    struct messaging_context *msg_ctx,
323                                    const struct auth_serversupplied_info *session_info,
324                                    const char *name)
325 {
326         const char *display_name = NULL;
327
328         display_name = svcctl_get_string_value(mem_ctx,
329                                                msg_ctx,
330                                                session_info,
331                                                name,
332                                                "DisplayName");
333
334         if (display_name == NULL) {
335                 display_name = talloc_strdup(mem_ctx, name);
336         }
337
338         return display_name;
339 }
340
341 /********************************************************************
342 ********************************************************************/
343
344 const char *svcctl_lookup_description(TALLOC_CTX *mem_ctx,
345                                       struct messaging_context *msg_ctx,
346                                       const struct auth_serversupplied_info *session_info,
347                                       const char *name)
348 {
349         const char *description = NULL;
350
351         description = svcctl_get_string_value(mem_ctx,
352                                               msg_ctx,
353                                               session_info,
354                                               name,
355                                               "Description");
356
357         if (description == NULL) {
358                 description = talloc_strdup(mem_ctx, "Unix Service");
359         }
360
361         return description;
362 }
363
364 /* vim: set ts=8 sw=8 noet cindent syntax=c.doxygen: */