summaryrefslogtreecommitdiffstats
path: root/source3/registry/reg_dispatcher.c
blob: ab3fb24dc2ff4efc4955cf88bed979e037a8fa7e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/*
 *  Unix SMB/CIFS implementation.
 *  Virtual Windows Registry Layer
 *  Copyright (C) Gerald Carter                     2002-2005
 *  Copyright (C) Michael Adam                      2006-2008
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 3 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, see <http://www.gnu.org/licenses/>.
 */

/*
 * Implementation of registry frontend view functions.
 * Functions moved from reg_frontend.c to minimize linker deps.
 */

#include "includes.h"
#include "system/passwd.h" /* uid_wrapper */
#include "registry.h"
#include "reg_dispatcher.h"
#include "../libcli/security/security.h"

#undef DBGC_CLASS
#define DBGC_CLASS DBGC_REGISTRY

static const struct generic_mapping reg_generic_map =
	{ REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };

/********************************************************************
********************************************************************/

static WERROR construct_registry_sd(TALLOC_CTX *ctx, struct security_descriptor **psd)
{
	struct security_ace ace[3];
	size_t i = 0;
	struct security_descriptor *sd;
	struct security_acl *theacl;
	size_t sd_size;

	/* basic access for Everyone */

	init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
		     REG_KEY_READ, 0);

	/* Full Access 'BUILTIN\Administrators' */

	init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
		     SEC_ACE_TYPE_ACCESS_ALLOWED, REG_KEY_ALL, 0);

	/* Full Access 'NT Authority\System' */

	init_sec_ace(&ace[i++], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
		     REG_KEY_ALL, 0);

	/* create the security descriptor */

	theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace);
	if (theacl == NULL) {
		return WERR_NOT_ENOUGH_MEMORY;
	}

	sd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
			   &global_sid_Builtin_Administrators,
			   &global_sid_System, NULL, theacl,
			   &sd_size);
	if (sd == NULL) {
		return WERR_NOT_ENOUGH_MEMORY;
	}

	*psd = sd;
	return WERR_OK;
}

/***********************************************************************
 High level wrapper function for storing registry subkeys
 ***********************************************************************/

bool store_reg_keys(struct registry_key_handle *key,
		    struct regsubkey_ctr *subkeys)
{
	if (key->ops && key->ops->store_subkeys)
		return key->ops->store_subkeys(key->name, subkeys);

	return false;
}

/***********************************************************************
 High level wrapper function for storing registry values
 ***********************************************************************/

bool store_reg_values(struct registry_key_handle *key, struct regval_ctr *val)
{
	if (key->ops && key->ops->store_values)
		return key->ops->store_values(key->name, val);

	return false;
}

WERROR create_reg_subkey(struct registry_key_handle *key, const char *subkey)
{
	if (key->ops && key->ops->create_subkey) {
		return key->ops->create_subkey(key->name, subkey);
	}

	return WERR_NOT_SUPPORTED;
}

WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey, bool lazy)
{
	if (key->ops && key->ops->delete_subkey) {
		return key->ops->delete_subkey(key->name, subkey, lazy);
	}

	return WERR_NOT_SUPPORTED;
}

/***********************************************************************
 High level wrapper function for enumerating registry subkeys
 Initialize the TALLOC_CTX if necessary
 ***********************************************************************/

int fetch_reg_keys(struct registry_key_handle *key,
		   struct regsubkey_ctr *subkey_ctr)
{
	int result = -1;

	if (key->ops && key->ops->fetch_subkeys)
		result = key->ops->fetch_subkeys(key->name, subkey_ctr);

	return result;
}

/***********************************************************************
 High level wrapper function for enumerating registry values
 ***********************************************************************/

int fetch_reg_values(struct registry_key_handle *key, struct regval_ctr *val)
{
	int result = -1;

	DEBUG(10, ("fetch_reg_values called for key '%s' (ops %p)\n", key->name,
		   (key->ops) ? (void *)key->ops : NULL));

	if (key->ops && key->ops->fetch_values)
		result = key->ops->fetch_values(key->name, val);

	return result;
}

/***********************************************************************
 High level access check for passing the required access mask to the
 underlying registry backend
 ***********************************************************************/

bool regkey_access_check(struct registry_key_handle *key, uint32_t requested,
			 uint32_t *granted,
			 const struct security_token *token )
{
	struct security_descriptor *sec_desc;
	NTSTATUS status;
	WERROR err;

	/* root free-pass, like we have on all other pipes like samr, lsa, etc. */
	if (root_mode()) {
		*granted = REG_KEY_ALL;
		return true;
	}

	/* use the default security check if the backend has not defined its
	 * own */

	if (key->ops && key->ops->reg_access_check) {
		return key->ops->reg_access_check(key->name, requested,
						  granted, token);
	}

	err = regkey_get_secdesc(talloc_tos(), key, &sec_desc);

	if (!W_ERROR_IS_OK(err)) {
		return false;
	}

	se_map_generic( &requested, &reg_generic_map );

	status =se_access_check(sec_desc, token, requested, granted);
	TALLOC_FREE(sec_desc);
	if (!NT_STATUS_IS_OK(status)) {
		return false;
	}

	return NT_STATUS_IS_OK(status);
}

WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, struct registry_key_handle *key,
			  struct security_descriptor **psecdesc)
{
	struct security_descriptor *secdesc;
	WERROR werr;

	if (key->ops && key->ops->get_secdesc) {
		werr = key->ops->get_secdesc(mem_ctx, key->name, psecdesc);
		if (W_ERROR_IS_OK(werr)) {
			return WERR_OK;
		}
	}

	werr = construct_registry_sd(mem_ctx, &secdesc);
	if (!W_ERROR_IS_OK(werr)) {
		return werr;
	}

	*psecdesc = secdesc;
	return WERR_OK;
}

WERROR regkey_set_secdesc(struct registry_key_handle *key,
			  struct security_descriptor *psecdesc)
{
	if (key->ops && key->ops->set_secdesc) {
		return key->ops->set_secdesc(key->name, psecdesc);
	}

	return WERR_ACCESS_DENIED;
}

/**
 * Check whether the in-memory version of the subkyes of a
 * registry key needs update from disk.
 */
bool reg_subkeys_need_update(struct registry_key_handle *key,
			     struct regsubkey_ctr *subkeys)
{
	if (key->ops && key->ops->subkeys_need_update)
	{
		return key->ops->subkeys_need_update(subkeys);
	}

	return true;
}

/**
 * Check whether the in-memory version of the values of a
 * registry key needs update from disk.
 */
bool reg_values_need_update(struct registry_key_handle *key,
			    struct regval_ctr *values)
{
	if (key->ops && key->ops->values_need_update)
	{
		return key->ops->values_need_update(values);
	}

	return true;
}