Line data Source code
1 : /*
2 : * Unix SMB/CIFS implementation.
3 : * RPC Pipe client / server routines
4 : *
5 : * Copyright (C) Gerald Carter 2002-2006.
6 : *
7 : * This program is free software; you can redistribute it and/or modify
8 : * it under the terms of the GNU General Public License as published by
9 : * the Free Software Foundation; either version 3 of the License, or
10 : * (at your option) any later version.
11 : *
12 : * This program is distributed in the hope that it will be useful,
13 : * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 : * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 : * GNU General Public License for more details.
16 : *
17 : * You should have received a copy of the GNU General Public License
18 : * along with this program; if not, see <http://www.gnu.org/licenses/>.
19 : */
20 :
21 : /* Implementation of registry functions. */
22 :
23 : #include "includes.h"
24 : #include "ntdomain.h"
25 : #include "librpc/rpc/dcesrv_core.h"
26 : #include "librpc/gen_ndr/ndr_winreg.h"
27 : #include "librpc/gen_ndr/ndr_winreg_scompat.h"
28 : #include "registry.h"
29 : #include "registry/reg_api.h"
30 : #include "registry/reg_perfcount.h"
31 : #include "rpc_misc.h"
32 : #include "auth.h"
33 : #include "lib/privileges.h"
34 : #include "libcli/security/secdesc.h"
35 :
36 : #undef DBGC_CLASS
37 : #define DBGC_CLASS DBGC_RPC_SRV
38 :
39 : enum handle_types { HTYPE_REGVAL, HTYPE_REGKEY };
40 :
41 : /******************************************************************
42 : Find a registry key handle and return a struct registry_key *
43 : *****************************************************************/
44 :
45 3315 : static struct registry_key *find_regkey_by_hnd(struct pipes_struct *p,
46 : struct policy_handle *hnd,
47 : enum handle_types type)
48 : {
49 3315 : struct registry_key *regkey = NULL;
50 : NTSTATUS status;
51 :
52 3315 : regkey = find_policy_by_hnd(p,
53 : hnd,
54 : type,
55 : struct registry_key,
56 : &status);
57 3315 : if (!NT_STATUS_IS_OK(status)) {
58 0 : DEBUG(2,("find_regkey_index_by_hnd: Registry Key not found: "));
59 0 : return NULL;
60 : }
61 :
62 3315 : return regkey;
63 : }
64 :
65 : /*******************************************************************
66 : Function for open a new registry handle and creating a handle
67 : Note that P should be valid & hnd should already have space
68 :
69 : When we open a key, we store the full path to the key as
70 : HK[LM|U]\<key>\<key>\...
71 : *******************************************************************/
72 :
73 232 : static WERROR open_registry_key(struct pipes_struct *p,
74 : struct policy_handle *hnd,
75 : struct registry_key *parent,
76 : const char *subkeyname,
77 : uint32_t access_desired)
78 : {
79 232 : struct dcesrv_call_state *dce_call = p->dce_call;
80 150 : struct auth_session_info *session_info =
81 82 : dcesrv_call_session_info(dce_call);
82 232 : WERROR result = WERR_OK;
83 : struct registry_key *key;
84 :
85 232 : if (parent == NULL) {
86 104 : result = reg_openhive(p->mem_ctx, subkeyname, access_desired,
87 104 : session_info->security_token, &key);
88 : }
89 : else {
90 128 : result = reg_openkey(p->mem_ctx, parent, subkeyname,
91 : access_desired, &key);
92 : }
93 :
94 232 : if ( !W_ERROR_IS_OK(result) ) {
95 42 : return result;
96 : }
97 :
98 190 : if ( !create_policy_hnd( p, hnd, HTYPE_REGKEY, key ) ) {
99 0 : return WERR_FILE_NOT_FOUND;
100 : }
101 :
102 190 : return WERR_OK;
103 : }
104 :
105 : /*******************************************************************
106 : Function for open a new registry handle and creating a handle
107 : Note that P should be valid & hnd should already have space
108 : *******************************************************************/
109 :
110 439 : static bool close_registry_key(struct pipes_struct *p,
111 : struct policy_handle *hnd,
112 : enum handle_types type)
113 : {
114 439 : struct registry_key *regkey = find_regkey_by_hnd(p, hnd, type);
115 :
116 439 : if ( !regkey ) {
117 0 : DEBUG(2,("close_registry_key: Invalid handle (%s:%u:%u)\n",
118 : OUR_HANDLE(hnd)));
119 0 : return False;
120 : }
121 :
122 439 : close_policy_hnd(p, hnd);
123 :
124 439 : return True;
125 : }
126 :
127 : /********************************************************************
128 : _winreg_CloseKey
129 : ********************************************************************/
130 :
131 439 : WERROR _winreg_CloseKey(struct pipes_struct *p,
132 : struct winreg_CloseKey *r)
133 : {
134 : bool ok;
135 :
136 : /* close the policy handle */
137 :
138 439 : ok = close_registry_key(p, r->in.handle, HTYPE_REGKEY);
139 439 : if (!ok) {
140 0 : return WERR_INVALID_HANDLE;
141 : }
142 :
143 439 : ZERO_STRUCTP(r->out.handle);
144 :
145 439 : return WERR_OK;
146 : }
147 :
148 : /*******************************************************************
149 : _winreg_OpenHKLM
150 : ********************************************************************/
151 :
152 95 : WERROR _winreg_OpenHKLM(struct pipes_struct *p,
153 : struct winreg_OpenHKLM *r)
154 : {
155 95 : return open_registry_key(p, r->out.handle, NULL, KEY_HKLM, r->in.access_mask);
156 : }
157 :
158 : /*******************************************************************
159 : _winreg_OpenHKPD
160 : ********************************************************************/
161 :
162 0 : WERROR _winreg_OpenHKPD(struct pipes_struct *p,
163 : struct winreg_OpenHKPD *r)
164 : {
165 0 : return open_registry_key(p, r->out.handle, NULL, KEY_HKPD, r->in.access_mask);
166 : }
167 :
168 : /*******************************************************************
169 : _winreg_OpenHKPT
170 : ********************************************************************/
171 :
172 0 : WERROR _winreg_OpenHKPT(struct pipes_struct *p,
173 : struct winreg_OpenHKPT *r)
174 : {
175 0 : return open_registry_key(p, r->out.handle, NULL, KEY_HKPT, r->in.access_mask);
176 : }
177 :
178 : /*******************************************************************
179 : _winreg_OpenHKCR
180 : ********************************************************************/
181 :
182 3 : WERROR _winreg_OpenHKCR(struct pipes_struct *p,
183 : struct winreg_OpenHKCR *r)
184 : {
185 3 : return open_registry_key(p, r->out.handle, NULL, KEY_HKCR, r->in.access_mask);
186 : }
187 :
188 : /*******************************************************************
189 : _winreg_OpenHKU
190 : ********************************************************************/
191 :
192 3 : WERROR _winreg_OpenHKU(struct pipes_struct *p,
193 : struct winreg_OpenHKU *r)
194 : {
195 3 : return open_registry_key(p, r->out.handle, NULL, KEY_HKU, r->in.access_mask);
196 : }
197 :
198 : /*******************************************************************
199 : _winreg_OpenHKCU
200 : ********************************************************************/
201 :
202 3 : WERROR _winreg_OpenHKCU(struct pipes_struct *p,
203 : struct winreg_OpenHKCU *r)
204 : {
205 3 : return open_registry_key(p, r->out.handle, NULL, KEY_HKCU, r->in.access_mask);
206 : }
207 :
208 : /*******************************************************************
209 : _winreg_OpenHKCC
210 : ********************************************************************/
211 :
212 0 : WERROR _winreg_OpenHKCC(struct pipes_struct *p,
213 : struct winreg_OpenHKCC *r)
214 : {
215 0 : return open_registry_key(p, r->out.handle, NULL, KEY_HKCC, r->in.access_mask);
216 : }
217 :
218 : /*******************************************************************
219 : _winreg_OpenHKDD
220 : ********************************************************************/
221 :
222 0 : WERROR _winreg_OpenHKDD(struct pipes_struct *p,
223 : struct winreg_OpenHKDD *r)
224 : {
225 0 : return open_registry_key(p, r->out.handle, NULL, KEY_HKDD, r->in.access_mask);
226 : }
227 :
228 : /*******************************************************************
229 : _winreg_OpenHKPN
230 : ********************************************************************/
231 :
232 0 : WERROR _winreg_OpenHKPN(struct pipes_struct *p,
233 : struct winreg_OpenHKPN *r)
234 : {
235 0 : return open_registry_key(p, r->out.handle, NULL, KEY_HKPN, r->in.access_mask);
236 : }
237 :
238 : /*******************************************************************
239 : _winreg_OpenKey
240 : ********************************************************************/
241 :
242 128 : WERROR _winreg_OpenKey(struct pipes_struct *p,
243 : struct winreg_OpenKey *r)
244 : {
245 128 : struct registry_key *parent = find_regkey_by_hnd(p,
246 : r->in.parent_handle,
247 : HTYPE_REGKEY);
248 :
249 128 : if ( !parent )
250 0 : return WERR_INVALID_HANDLE;
251 :
252 128 : return open_registry_key(p, r->out.handle, parent, r->in.keyname.name, r->in.access_mask);
253 : }
254 :
255 : /*******************************************************************
256 : _winreg_QueryValue
257 : ********************************************************************/
258 :
259 606 : WERROR _winreg_QueryValue(struct pipes_struct *p,
260 : struct winreg_QueryValue *r)
261 : {
262 606 : WERROR status = WERR_FILE_NOT_FOUND;
263 606 : struct registry_key *regkey = find_regkey_by_hnd(p,
264 : r->in.handle,
265 : HTYPE_REGKEY);
266 : prs_struct prs_hkpd;
267 :
268 606 : uint8_t *outbuf = NULL;
269 606 : uint32_t outbuf_size = 0;
270 :
271 606 : bool free_buf = False;
272 606 : bool free_prs = False;
273 :
274 606 : if ( !regkey )
275 0 : return WERR_INVALID_HANDLE;
276 :
277 606 : if (r->in.value_name->name == NULL) {
278 84 : return WERR_INVALID_PARAMETER;
279 : }
280 :
281 522 : if ((r->out.data_length == NULL) || (r->out.type == NULL) || (r->out.data_size == NULL)) {
282 189 : return WERR_INVALID_PARAMETER;
283 : }
284 :
285 333 : DEBUG(7,("_winreg_QueryValue: policy key name = [%s]\n", regkey->key->name));
286 333 : DEBUG(7,("_winreg_QueryValue: policy key type = [%08x]\n", regkey->key->type));
287 :
288 : /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */
289 333 : if(regkey->key->type == REG_KEY_HKPD)
290 : {
291 0 : if (strequal(r->in.value_name->name, "Global")) {
292 0 : if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
293 0 : return WERR_NOT_ENOUGH_MEMORY;
294 0 : status = reg_perfcount_get_hkpd(
295 0 : &prs_hkpd, *r->in.data_size, &outbuf_size, NULL);
296 0 : outbuf = (uint8_t *)prs_hkpd.data_p;
297 0 : free_prs = True;
298 : }
299 0 : else if (strequal(r->in.value_name->name, "Counter 009")) {
300 0 : outbuf_size = reg_perfcount_get_counter_names(
301 : reg_perfcount_get_base_index(),
302 : (char **)(void *)&outbuf);
303 0 : free_buf = True;
304 : }
305 0 : else if (strequal(r->in.value_name->name, "Explain 009")) {
306 0 : outbuf_size = reg_perfcount_get_counter_help(
307 : reg_perfcount_get_base_index(),
308 : (char **)(void *)&outbuf);
309 0 : free_buf = True;
310 : }
311 0 : else if (isdigit(r->in.value_name->name[0])) {
312 : /* we probably have a request for a specific object
313 : * here */
314 0 : if (!prs_init(&prs_hkpd, *r->in.data_size, p->mem_ctx, MARSHALL))
315 0 : return WERR_NOT_ENOUGH_MEMORY;
316 0 : status = reg_perfcount_get_hkpd(
317 0 : &prs_hkpd, *r->in.data_size, &outbuf_size,
318 0 : r->in.value_name->name);
319 0 : outbuf = (uint8_t *)prs_hkpd.data_p;
320 0 : free_prs = True;
321 : }
322 : else {
323 0 : DEBUG(3,("Unsupported key name [%s] for HKPD.\n",
324 : r->in.value_name->name));
325 0 : return WERR_FILE_NOT_FOUND;
326 : }
327 :
328 0 : *r->out.type = REG_BINARY;
329 : }
330 : else {
331 : struct registry_value *val;
332 :
333 333 : status = reg_queryvalue(p->mem_ctx, regkey, r->in.value_name->name,
334 : &val);
335 333 : if (!W_ERROR_IS_OK(status)) {
336 :
337 54 : DEBUG(10,("_winreg_QueryValue: reg_queryvalue failed with: %s\n",
338 : win_errstr(status)));
339 :
340 54 : if (r->out.data_size) {
341 54 : *r->out.data_size = 0;
342 : }
343 54 : if (r->out.data_length) {
344 54 : *r->out.data_length = 0;
345 : }
346 54 : return status;
347 : }
348 :
349 279 : outbuf = val->data.data;
350 279 : outbuf_size = val->data.length;
351 279 : *r->out.type = val->type;
352 : }
353 :
354 279 : status = WERR_FILE_NOT_FOUND;
355 :
356 279 : if (*r->in.data_size < outbuf_size) {
357 168 : *r->out.data_size = outbuf_size;
358 168 : status = r->in.data ? WERR_MORE_DATA : WERR_OK;
359 : } else {
360 111 : *r->out.data_length = outbuf_size;
361 111 : *r->out.data_size = outbuf_size;
362 111 : if (r->out.data) {
363 111 : memcpy(r->out.data, outbuf, outbuf_size);
364 : }
365 111 : status = WERR_OK;
366 : }
367 :
368 279 : if (free_prs) prs_mem_free(&prs_hkpd);
369 279 : if (free_buf) SAFE_FREE(outbuf);
370 :
371 279 : return status;
372 : }
373 :
374 : /*****************************************************************************
375 : _winreg_QueryInfoKey
376 : ****************************************************************************/
377 :
378 74 : WERROR _winreg_QueryInfoKey(struct pipes_struct *p,
379 : struct winreg_QueryInfoKey *r)
380 : {
381 74 : WERROR status = WERR_OK;
382 74 : struct registry_key *regkey = find_regkey_by_hnd(p,
383 : r->in.handle,
384 : HTYPE_REGKEY);
385 :
386 74 : if ( !regkey )
387 0 : return WERR_INVALID_HANDLE;
388 :
389 74 : r->out.classname->name = NULL;
390 :
391 74 : status = reg_queryinfokey(regkey, r->out.num_subkeys, r->out.max_subkeylen,
392 : r->out.max_classlen, r->out.num_values, r->out.max_valnamelen,
393 : r->out.max_valbufsize, r->out.secdescsize,
394 : r->out.last_changed_time);
395 74 : if (!W_ERROR_IS_OK(status)) {
396 0 : return status;
397 : }
398 :
399 : /*
400 : * These calculations account for the registry buffers being
401 : * UTF-16. They are inexact at best, but so far they worked.
402 : */
403 :
404 74 : *r->out.max_subkeylen *= 2;
405 :
406 74 : *r->out.max_valnamelen += 1;
407 74 : *r->out.max_valnamelen *= 2;
408 :
409 74 : return WERR_OK;
410 : }
411 :
412 :
413 : /*****************************************************************************
414 : _winreg_GetVersion
415 : ****************************************************************************/
416 :
417 12 : WERROR _winreg_GetVersion(struct pipes_struct *p,
418 : struct winreg_GetVersion *r)
419 : {
420 12 : struct registry_key *regkey = find_regkey_by_hnd(p,
421 : r->in.handle,
422 : HTYPE_REGKEY);
423 :
424 12 : if ( !regkey )
425 0 : return WERR_INVALID_HANDLE;
426 :
427 12 : return reg_getversion(r->out.version);
428 : }
429 :
430 :
431 : /*****************************************************************************
432 : _winreg_EnumKey
433 : ****************************************************************************/
434 :
435 201 : WERROR _winreg_EnumKey(struct pipes_struct *p,
436 : struct winreg_EnumKey *r)
437 : {
438 201 : WERROR err = WERR_OK;
439 201 : struct registry_key *key = find_regkey_by_hnd(p,
440 : r->in.handle,
441 : HTYPE_REGKEY);
442 : char *name;
443 :
444 201 : if ( !key )
445 0 : return WERR_INVALID_HANDLE;
446 :
447 201 : if ( !r->in.name || !r->in.keyclass )
448 0 : return WERR_INVALID_PARAMETER;
449 :
450 201 : DEBUG(8,("_winreg_EnumKey: enumerating key [%s]\n", key->key->name));
451 :
452 201 : err = reg_enumkey(p->mem_ctx, key, r->in.enum_index, &name,
453 : r->out.last_changed_time);
454 201 : if (!W_ERROR_IS_OK(err)) {
455 12 : return err;
456 : }
457 189 : r->out.name->name = name;
458 189 : r->out.keyclass->name = "";
459 189 : return WERR_OK;
460 : }
461 :
462 : /*****************************************************************************
463 : _winreg_EnumValue
464 : ****************************************************************************/
465 :
466 24 : WERROR _winreg_EnumValue(struct pipes_struct *p,
467 : struct winreg_EnumValue *r)
468 : {
469 24 : WERROR err = WERR_OK;
470 24 : struct registry_key *key = find_regkey_by_hnd(p,
471 : r->in.handle,
472 : HTYPE_REGKEY);
473 24 : char *valname = NULL;
474 24 : struct registry_value *val = NULL;
475 :
476 24 : if ( !key )
477 0 : return WERR_INVALID_HANDLE;
478 :
479 24 : if ( !r->in.name )
480 0 : return WERR_INVALID_PARAMETER;
481 :
482 24 : DEBUG(8,("_winreg_EnumValue: enumerating values for key [%s]\n",
483 : key->key->name));
484 :
485 24 : err = reg_enumvalue(p->mem_ctx, key, r->in.enum_index, &valname, &val);
486 24 : if (!W_ERROR_IS_OK(err)) {
487 24 : return err;
488 : }
489 :
490 0 : if (r->out.name != NULL) {
491 0 : r->out.name->name = valname;
492 : }
493 :
494 0 : if (r->out.type != NULL) {
495 0 : *r->out.type = val->type;
496 : }
497 :
498 0 : if (r->out.value != NULL) {
499 0 : if ((r->out.size == NULL) || (r->out.length == NULL)) {
500 0 : return WERR_INVALID_PARAMETER;
501 : }
502 :
503 0 : if (val->data.length > *r->out.size) {
504 0 : return WERR_MORE_DATA;
505 : }
506 :
507 0 : memcpy( r->out.value, val->data.data, val->data.length );
508 : }
509 :
510 0 : if (r->out.length != NULL) {
511 0 : *r->out.length = val->data.length;
512 : }
513 0 : if (r->out.size != NULL) {
514 0 : *r->out.size = val->data.length;
515 : }
516 :
517 0 : return WERR_OK;
518 : }
519 :
520 : /*******************************************************************
521 : _winreg_InitiateSystemShutdown
522 : ********************************************************************/
523 :
524 0 : WERROR _winreg_InitiateSystemShutdown(struct pipes_struct *p,
525 : struct winreg_InitiateSystemShutdown *r)
526 : {
527 : struct winreg_InitiateSystemShutdownEx s;
528 :
529 0 : s.in.hostname = r->in.hostname;
530 0 : s.in.message = r->in.message;
531 0 : s.in.timeout = r->in.timeout;
532 0 : s.in.force_apps = r->in.force_apps;
533 0 : s.in.do_reboot = r->in.do_reboot;
534 0 : s.in.reason = 0;
535 :
536 : /* thunk down to _winreg_InitiateSystemShutdownEx()
537 : (just returns a status) */
538 :
539 0 : return _winreg_InitiateSystemShutdownEx( p, &s );
540 : }
541 :
542 : /*******************************************************************
543 : _winreg_InitiateSystemShutdownEx
544 : ********************************************************************/
545 :
546 : #define SHUTDOWN_R_STRING "-r"
547 : #define SHUTDOWN_F_STRING "-f"
548 :
549 :
550 0 : WERROR _winreg_InitiateSystemShutdownEx(struct pipes_struct *p,
551 : struct winreg_InitiateSystemShutdownEx *r)
552 : {
553 0 : struct dcesrv_call_state *dce_call = p->dce_call;
554 0 : struct auth_session_info *session_info =
555 0 : dcesrv_call_session_info(dce_call);
556 0 : const struct loadparm_substitution *lp_sub =
557 0 : loadparm_s3_global_substitution();
558 0 : char *shutdown_script = NULL;
559 0 : char *chkmsg = NULL;
560 : fstring str_timeout;
561 : fstring str_reason;
562 : fstring do_reboot;
563 : fstring f;
564 0 : int ret = -1;
565 0 : bool can_shutdown = false;
566 :
567 0 : shutdown_script = lp_shutdown_script(p->mem_ctx, lp_sub);
568 0 : if (!shutdown_script) {
569 0 : return WERR_NOT_ENOUGH_MEMORY;
570 : }
571 0 : if (!*shutdown_script) {
572 0 : return WERR_ACCESS_DENIED;
573 : }
574 :
575 : /* pull the message string and perform necessary sanity checks on it */
576 :
577 0 : if ( r->in.message && r->in.message->string ) {
578 0 : chkmsg = talloc_alpha_strcpy(p->mem_ctx,
579 0 : r->in.message->string,
580 : NULL);
581 0 : if (chkmsg == NULL) {
582 0 : return WERR_NOT_ENOUGH_MEMORY;
583 : }
584 : }
585 :
586 0 : fstr_sprintf(str_timeout, "%d", r->in.timeout);
587 0 : fstr_sprintf(do_reboot, r->in.do_reboot ? SHUTDOWN_R_STRING : "");
588 0 : fstr_sprintf(f, r->in.force_apps ? SHUTDOWN_F_STRING : "");
589 0 : fstr_sprintf(str_reason, "%d", r->in.reason );
590 :
591 0 : shutdown_script = talloc_all_string_sub(p->mem_ctx,
592 : shutdown_script, "%z", chkmsg ? chkmsg : "");
593 0 : if (!shutdown_script) {
594 0 : return WERR_NOT_ENOUGH_MEMORY;
595 : }
596 0 : shutdown_script = talloc_all_string_sub(p->mem_ctx,
597 : shutdown_script, "%t", str_timeout);
598 0 : if (!shutdown_script) {
599 0 : return WERR_NOT_ENOUGH_MEMORY;
600 : }
601 0 : shutdown_script = talloc_all_string_sub(p->mem_ctx,
602 : shutdown_script, "%r", do_reboot);
603 0 : if (!shutdown_script) {
604 0 : return WERR_NOT_ENOUGH_MEMORY;
605 : }
606 0 : shutdown_script = talloc_all_string_sub(p->mem_ctx,
607 : shutdown_script, "%f", f);
608 0 : if (!shutdown_script) {
609 0 : return WERR_NOT_ENOUGH_MEMORY;
610 : }
611 0 : shutdown_script = talloc_all_string_sub(p->mem_ctx,
612 : shutdown_script, "%x", str_reason);
613 0 : if (!shutdown_script) {
614 0 : return WERR_NOT_ENOUGH_MEMORY;
615 : }
616 :
617 0 : can_shutdown = security_token_has_privilege(
618 0 : session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
619 :
620 : /* IF someone has privs, run the shutdown script as root. OTHERWISE run it as not root
621 : Take the error return from the script and provide it as the Windows return code. */
622 :
623 : /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
624 :
625 0 : if ( can_shutdown )
626 0 : become_root();
627 :
628 0 : ret = smbrun(shutdown_script, NULL, NULL);
629 :
630 0 : if ( can_shutdown )
631 0 : unbecome_root();
632 :
633 : /********** END SeRemoteShutdownPrivilege BLOCK **********/
634 :
635 0 : DEBUG(3,("_reg_shutdown_ex: Running the command `%s' gave %d\n",
636 : shutdown_script, ret));
637 :
638 0 : return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
639 : }
640 :
641 : /*******************************************************************
642 : _winreg_AbortSystemShutdown
643 : ********************************************************************/
644 :
645 0 : WERROR _winreg_AbortSystemShutdown(struct pipes_struct *p,
646 : struct winreg_AbortSystemShutdown *r)
647 : {
648 0 : struct dcesrv_call_state *dce_call = p->dce_call;
649 0 : struct auth_session_info *session_info =
650 0 : dcesrv_call_session_info(dce_call);
651 0 : const char *abort_shutdown_script = NULL;
652 0 : const struct loadparm_substitution *lp_sub =
653 0 : loadparm_s3_global_substitution();
654 0 : int ret = -1;
655 0 : bool can_shutdown = false;
656 :
657 0 : abort_shutdown_script = lp_abort_shutdown_script(talloc_tos(), lp_sub);
658 0 : if (!*abort_shutdown_script)
659 0 : return WERR_ACCESS_DENIED;
660 :
661 0 : can_shutdown = security_token_has_privilege(
662 0 : session_info->security_token, SEC_PRIV_REMOTE_SHUTDOWN);
663 :
664 : /********** BEGIN SeRemoteShutdownPrivilege BLOCK **********/
665 :
666 0 : if ( can_shutdown )
667 0 : become_root();
668 :
669 0 : ret = smbrun(abort_shutdown_script, NULL, NULL);
670 :
671 0 : if ( can_shutdown )
672 0 : unbecome_root();
673 :
674 : /********** END SeRemoteShutdownPrivilege BLOCK **********/
675 :
676 0 : DEBUG(3,("_winreg_AbortSystemShutdown: Running the command `%s' gave %d\n",
677 : abort_shutdown_script, ret));
678 :
679 0 : return (ret == 0) ? WERR_OK : WERR_ACCESS_DENIED;
680 : }
681 :
682 : /*******************************************************************
683 : _winreg_RestoreKey
684 : ********************************************************************/
685 :
686 0 : WERROR _winreg_RestoreKey(struct pipes_struct *p,
687 : struct winreg_RestoreKey *r)
688 : {
689 0 : struct registry_key *regkey = find_regkey_by_hnd(p,
690 : r->in.handle,
691 : HTYPE_REGKEY);
692 :
693 0 : if ( !regkey ) {
694 0 : return WERR_INVALID_HANDLE;
695 : }
696 0 : return WERR_BAD_PATHNAME;
697 : }
698 :
699 : /*******************************************************************
700 : _winreg_SaveKey
701 : ********************************************************************/
702 :
703 0 : WERROR _winreg_SaveKey(struct pipes_struct *p,
704 : struct winreg_SaveKey *r)
705 : {
706 0 : struct registry_key *regkey = find_regkey_by_hnd(p,
707 : r->in.handle,
708 : HTYPE_REGKEY);
709 :
710 0 : if ( !regkey ) {
711 0 : return WERR_INVALID_HANDLE;
712 : }
713 0 : return WERR_BAD_PATHNAME;
714 : }
715 :
716 : /*******************************************************************
717 : _winreg_SaveKeyEx
718 : ********************************************************************/
719 :
720 0 : WERROR _winreg_SaveKeyEx(struct pipes_struct *p,
721 : struct winreg_SaveKeyEx *r)
722 : {
723 : /* fill in your code here if you think this call should
724 : do anything */
725 :
726 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
727 0 : return WERR_NOT_SUPPORTED;
728 : }
729 :
730 : /*******************************************************************
731 : _winreg_CreateKey
732 : ********************************************************************/
733 :
734 383 : WERROR _winreg_CreateKey(struct pipes_struct *p,
735 : struct winreg_CreateKey *r)
736 : {
737 383 : struct registry_key *parent = find_regkey_by_hnd(p,
738 : r->in.handle,
739 : HTYPE_REGKEY);
740 383 : struct registry_key *new_key = NULL;
741 383 : WERROR result = WERR_OK;
742 :
743 383 : if ( !parent )
744 0 : return WERR_INVALID_HANDLE;
745 :
746 383 : DEBUG(10, ("_winreg_CreateKey called with parent key '%s' and "
747 : "subkey name '%s'\n", parent->key->name, r->in.name.name));
748 :
749 383 : result = reg_createkey(NULL, parent, r->in.name.name, r->in.access_mask,
750 : &new_key, r->out.action_taken);
751 383 : if (!W_ERROR_IS_OK(result)) {
752 0 : return result;
753 : }
754 :
755 383 : if (!create_policy_hnd(p, r->out.new_handle, HTYPE_REGKEY, new_key)) {
756 0 : TALLOC_FREE(new_key);
757 0 : return WERR_FILE_NOT_FOUND;
758 : }
759 :
760 383 : return WERR_OK;
761 : }
762 :
763 : /*******************************************************************
764 : _winreg_SetValue
765 : ********************************************************************/
766 :
767 1298 : WERROR _winreg_SetValue(struct pipes_struct *p,
768 : struct winreg_SetValue *r)
769 : {
770 1298 : struct registry_key *key = find_regkey_by_hnd(p,
771 : r->in.handle,
772 : HTYPE_REGKEY);
773 1298 : struct registry_value *val = NULL;
774 :
775 1298 : if ( !key )
776 0 : return WERR_INVALID_HANDLE;
777 :
778 1298 : DEBUG(8,("_winreg_SetValue: Setting value for [%s:%s]\n",
779 : key->key->name, r->in.name.name));
780 :
781 1298 : val = talloc_zero(p->mem_ctx, struct registry_value);
782 1298 : if (val == NULL) {
783 0 : return WERR_NOT_ENOUGH_MEMORY;
784 : }
785 :
786 1298 : val->type = r->in.type;
787 1298 : val->data = data_blob_talloc(p->mem_ctx, r->in.data, r->in.size);
788 :
789 1298 : return reg_setvalue(key, r->in.name.name, val);
790 : }
791 :
792 : /*******************************************************************
793 : _winreg_DeleteKey
794 : ********************************************************************/
795 :
796 96 : WERROR _winreg_DeleteKey(struct pipes_struct *p,
797 : struct winreg_DeleteKey *r)
798 : {
799 96 : struct registry_key *parent = find_regkey_by_hnd(p,
800 : r->in.handle,
801 : HTYPE_REGKEY);
802 :
803 96 : if ( !parent )
804 0 : return WERR_INVALID_HANDLE;
805 :
806 96 : return reg_deletekey(parent, r->in.key.name);
807 : }
808 :
809 :
810 : /*******************************************************************
811 : _winreg_DeleteValue
812 : ********************************************************************/
813 :
814 54 : WERROR _winreg_DeleteValue(struct pipes_struct *p,
815 : struct winreg_DeleteValue *r)
816 : {
817 54 : struct registry_key *key = find_regkey_by_hnd(p,
818 : r->in.handle,
819 : HTYPE_REGKEY);
820 :
821 54 : if ( !key )
822 0 : return WERR_INVALID_HANDLE;
823 :
824 54 : return reg_deletevalue(key, r->in.value.name);
825 : }
826 :
827 : /*******************************************************************
828 : _winreg_GetKeySecurity
829 : ********************************************************************/
830 :
831 0 : WERROR _winreg_GetKeySecurity(struct pipes_struct *p,
832 : struct winreg_GetKeySecurity *r)
833 : {
834 0 : struct registry_key *key = find_regkey_by_hnd(p,
835 : r->in.handle,
836 : HTYPE_REGKEY);
837 0 : WERROR err = WERR_OK;
838 0 : struct security_descriptor *secdesc = NULL;
839 0 : uint8_t *data = NULL;
840 0 : size_t len = 0;
841 :
842 0 : if ( !key )
843 0 : return WERR_INVALID_HANDLE;
844 :
845 : /* access checks first */
846 :
847 0 : if ( !(key->key->access_granted & SEC_STD_READ_CONTROL) )
848 0 : return WERR_ACCESS_DENIED;
849 :
850 0 : err = reg_getkeysecurity(p->mem_ctx, key, &secdesc);
851 0 : if (!W_ERROR_IS_OK(err)) {
852 0 : return err;
853 : }
854 :
855 0 : err = ntstatus_to_werror(marshall_sec_desc(p->mem_ctx, secdesc,
856 : &data, &len));
857 0 : if (!W_ERROR_IS_OK(err)) {
858 0 : return err;
859 : }
860 :
861 0 : if (len > r->out.sd->size) {
862 0 : r->out.sd->size = len;
863 0 : return WERR_INSUFFICIENT_BUFFER;
864 : }
865 :
866 0 : r->out.sd->size = len;
867 0 : r->out.sd->len = len;
868 0 : r->out.sd->data = data;
869 :
870 0 : return WERR_OK;
871 : }
872 :
873 : /*******************************************************************
874 : _winreg_SetKeySecurity
875 : ********************************************************************/
876 :
877 0 : WERROR _winreg_SetKeySecurity(struct pipes_struct *p,
878 : struct winreg_SetKeySecurity *r)
879 : {
880 0 : struct registry_key *key = find_regkey_by_hnd(p,
881 : r->in.handle,
882 : HTYPE_REGKEY);
883 0 : struct security_descriptor *secdesc = NULL;
884 0 : WERROR err = WERR_OK;
885 :
886 0 : if ( !key )
887 0 : return WERR_INVALID_HANDLE;
888 :
889 : /* access checks first */
890 :
891 0 : if ( !(key->key->access_granted & SEC_STD_WRITE_DAC) )
892 0 : return WERR_ACCESS_DENIED;
893 :
894 0 : err = ntstatus_to_werror(unmarshall_sec_desc(p->mem_ctx, r->in.sd->data,
895 0 : r->in.sd->len, &secdesc));
896 0 : if (!W_ERROR_IS_OK(err)) {
897 0 : return err;
898 : }
899 :
900 0 : return reg_setkeysecurity(key, secdesc);
901 : }
902 :
903 : /*******************************************************************
904 : _winreg_FlushKey
905 : ********************************************************************/
906 :
907 24 : WERROR _winreg_FlushKey(struct pipes_struct *p,
908 : struct winreg_FlushKey *r)
909 : {
910 : /* I'm just replying OK because there's not a lot
911 : here I see to do i --jerry */
912 :
913 24 : return WERR_OK;
914 : }
915 :
916 : /*******************************************************************
917 : _winreg_UnLoadKey
918 : ********************************************************************/
919 :
920 0 : WERROR _winreg_UnLoadKey(struct pipes_struct *p,
921 : struct winreg_UnLoadKey *r)
922 : {
923 : /* fill in your code here if you think this call should
924 : do anything */
925 :
926 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
927 0 : return WERR_NOT_SUPPORTED;
928 : }
929 :
930 : /*******************************************************************
931 : _winreg_ReplaceKey
932 : ********************************************************************/
933 :
934 0 : WERROR _winreg_ReplaceKey(struct pipes_struct *p,
935 : struct winreg_ReplaceKey *r)
936 : {
937 : /* fill in your code here if you think this call should
938 : do anything */
939 :
940 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
941 0 : return WERR_NOT_SUPPORTED;
942 : }
943 :
944 : /*******************************************************************
945 : _winreg_LoadKey
946 : ********************************************************************/
947 :
948 0 : WERROR _winreg_LoadKey(struct pipes_struct *p,
949 : struct winreg_LoadKey *r)
950 : {
951 : /* fill in your code here if you think this call should
952 : do anything */
953 :
954 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
955 0 : return WERR_NOT_SUPPORTED;
956 : }
957 :
958 : /*******************************************************************
959 : _winreg_NotifyChangeKeyValue
960 : ********************************************************************/
961 :
962 12 : WERROR _winreg_NotifyChangeKeyValue(struct pipes_struct *p,
963 : struct winreg_NotifyChangeKeyValue *r)
964 : {
965 12 : return WERR_NOT_SUPPORTED;
966 : }
967 :
968 : /*******************************************************************
969 : _winreg_QueryMultipleValues
970 : ********************************************************************/
971 :
972 0 : WERROR _winreg_QueryMultipleValues(struct pipes_struct *p,
973 : struct winreg_QueryMultipleValues *r)
974 : {
975 : struct winreg_QueryMultipleValues2 r2;
976 0 : uint32_t needed = 0;
977 :
978 0 : r2.in.key_handle = r->in.key_handle;
979 0 : r2.in.values_in = r->in.values_in;
980 0 : r2.in.num_values = r->in.num_values;
981 0 : r2.in.offered = r->in.buffer_size;
982 0 : r2.in.buffer = r->in.buffer;
983 0 : r2.out.values_out = r->out.values_out;
984 0 : r2.out.needed = &needed;
985 0 : r2.out.buffer = r->out.buffer;
986 :
987 0 : return _winreg_QueryMultipleValues2(p, &r2);
988 : }
989 :
990 : /*******************************************************************
991 : ********************************************************************/
992 :
993 0 : static WERROR construct_multiple_entry(TALLOC_CTX *mem_ctx,
994 : const char *valuename,
995 : uint32_t value_length,
996 : uint32_t offset,
997 : enum winreg_Type type,
998 : struct QueryMultipleValue *r)
999 : {
1000 0 : r->ve_valuename = talloc_zero(mem_ctx, struct winreg_ValNameBuf);
1001 0 : if (r->ve_valuename == NULL) {
1002 0 : return WERR_NOT_ENOUGH_MEMORY;
1003 : }
1004 :
1005 0 : r->ve_valuename->name = talloc_strdup(r->ve_valuename, valuename ? valuename : "");
1006 0 : if (r->ve_valuename->name == NULL) {
1007 0 : return WERR_NOT_ENOUGH_MEMORY;
1008 : }
1009 :
1010 0 : r->ve_valuename->size = strlen_m_term(r->ve_valuename->name)*2;
1011 0 : r->ve_valuelen = value_length;
1012 0 : r->ve_valueptr = offset;
1013 0 : r->ve_type = type;
1014 :
1015 0 : return WERR_OK;
1016 : }
1017 :
1018 : /*******************************************************************
1019 : _winreg_QueryMultipleValues2
1020 : ********************************************************************/
1021 :
1022 0 : WERROR _winreg_QueryMultipleValues2(struct pipes_struct *p,
1023 : struct winreg_QueryMultipleValues2 *r)
1024 : {
1025 0 : struct registry_key *regkey = find_regkey_by_hnd(p,
1026 : r->in.key_handle,
1027 : HTYPE_REGKEY);
1028 0 : struct registry_value *vals = NULL;
1029 0 : const char **names = NULL;
1030 0 : uint32_t offset = 0, num_vals = 0;
1031 0 : DATA_BLOB result = data_blob_null;
1032 0 : uint32_t i = 0;
1033 0 : WERROR err = WERR_OK;
1034 :
1035 0 : if (!regkey) {
1036 0 : return WERR_INVALID_HANDLE;
1037 : }
1038 :
1039 0 : names = talloc_zero_array(p->mem_ctx, const char *, r->in.num_values);
1040 0 : if (names == NULL) {
1041 0 : return WERR_NOT_ENOUGH_MEMORY;
1042 : }
1043 :
1044 0 : for (i=0; i < r->in.num_values; i++) {
1045 0 : if (r->in.values_in[i].ve_valuename &&
1046 0 : r->in.values_in[i].ve_valuename->name) {
1047 0 : names[i] = talloc_strdup(names,
1048 0 : r->in.values_in[i].ve_valuename->name);
1049 0 : if (names[i] == NULL) {
1050 0 : return WERR_NOT_ENOUGH_MEMORY;
1051 : }
1052 : }
1053 : }
1054 :
1055 0 : err = reg_querymultiplevalues(p->mem_ctx, regkey,
1056 : r->in.num_values, names,
1057 : &num_vals, &vals);
1058 0 : if (!W_ERROR_IS_OK(err)) {
1059 0 : return err;
1060 : }
1061 :
1062 0 : result = data_blob_talloc(p->mem_ctx, NULL, 0);
1063 :
1064 0 : for (i=0; i < r->in.num_values; i++) {
1065 0 : const char *valuename = NULL;
1066 :
1067 0 : if (vals[i].data.length > 0) {
1068 0 : if (!data_blob_append(p->mem_ctx, &result,
1069 0 : vals[i].data.data,
1070 0 : vals[i].data.length)) {
1071 0 : return WERR_NOT_ENOUGH_MEMORY;
1072 : }
1073 : }
1074 :
1075 0 : if (r->in.values_in[i].ve_valuename &&
1076 0 : r->in.values_in[i].ve_valuename->name) {
1077 0 : valuename = r->in.values_in[i].ve_valuename->name;
1078 : }
1079 :
1080 0 : err = construct_multiple_entry(r->out.values_out,
1081 : valuename,
1082 0 : vals[i].data.length,
1083 : offset,
1084 0 : vals[i].type,
1085 0 : &r->out.values_out[i]);
1086 0 : if (!W_ERROR_IS_OK(err)) {
1087 0 : return err;
1088 : }
1089 :
1090 0 : offset += vals[i].data.length;
1091 : }
1092 :
1093 0 : *r->out.needed = result.length;
1094 :
1095 0 : if (r->in.num_values != num_vals) {
1096 0 : return WERR_FILE_NOT_FOUND;
1097 : }
1098 :
1099 0 : if (*r->in.offered >= *r->out.needed) {
1100 0 : if (r->out.buffer) {
1101 0 : memcpy(r->out.buffer, result.data, MIN(result.length, *r->in.offered));
1102 : }
1103 0 : return WERR_OK;
1104 : } else {
1105 0 : return WERR_MORE_DATA;
1106 : }
1107 : }
1108 :
1109 : /*******************************************************************
1110 : _winreg_DeleteKeyEx
1111 : ********************************************************************/
1112 :
1113 0 : WERROR _winreg_DeleteKeyEx(struct pipes_struct *p,
1114 : struct winreg_DeleteKeyEx *r)
1115 : {
1116 : /* fill in your code here if you think this call should
1117 : do anything */
1118 :
1119 0 : p->fault_state = DCERPC_FAULT_OP_RNG_ERROR;
1120 0 : return WERR_NOT_SUPPORTED;
1121 : }
1122 :
1123 : /* include the generated boilerplate */
1124 : #include "librpc/gen_ndr/ndr_winreg_scompat.c"
|