Coverage Report

Created: 2025-11-16 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/samba/source3/registry/reg_dispatcher.c
Line
Count
Source
1
/*
2
 *  Unix SMB/CIFS implementation.
3
 *  Virtual Windows Registry Layer
4
 *  Copyright (C) Gerald Carter                     2002-2005
5
 *  Copyright (C) Michael Adam                      2006-2008
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
/*
22
 * Implementation of registry frontend view functions.
23
 * Functions moved from reg_frontend.c to minimize linker deps.
24
 */
25
26
#include "includes.h"
27
#include "system/passwd.h" /* uid_wrapper */
28
#include "registry.h"
29
#include "reg_dispatcher.h"
30
#include "../libcli/security/security.h"
31
32
#undef DBGC_CLASS
33
0
#define DBGC_CLASS DBGC_REGISTRY
34
35
static const struct generic_mapping reg_generic_map =
36
  { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL };
37
38
/********************************************************************
39
********************************************************************/
40
41
static WERROR construct_registry_sd(TALLOC_CTX *ctx, struct security_descriptor **psd)
42
0
{
43
0
  struct security_ace ace[3] = {};
44
0
  size_t i = 0;
45
0
  struct security_descriptor *sd;
46
0
  struct security_acl *theacl;
47
0
  size_t sd_size;
48
49
  /* basic access for Everyone */
50
51
0
  init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED,
52
0
         REG_KEY_READ, 0);
53
54
  /* Full Access 'BUILTIN\Administrators' */
55
56
0
  init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators,
57
0
         SEC_ACE_TYPE_ACCESS_ALLOWED, REG_KEY_ALL, 0);
58
59
  /* Full Access 'NT Authority\System' */
60
61
0
  init_sec_ace(&ace[i++], &global_sid_System, SEC_ACE_TYPE_ACCESS_ALLOWED,
62
0
         REG_KEY_ALL, 0);
63
64
  /* create the security descriptor */
65
66
0
  theacl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace);
67
0
  if (theacl == NULL) {
68
0
    return WERR_NOT_ENOUGH_MEMORY;
69
0
  }
70
71
0
  sd = make_sec_desc(ctx, SD_REVISION, SEC_DESC_SELF_RELATIVE,
72
0
         &global_sid_Builtin_Administrators,
73
0
         &global_sid_System, NULL, theacl,
74
0
         &sd_size);
75
0
  if (sd == NULL) {
76
0
    return WERR_NOT_ENOUGH_MEMORY;
77
0
  }
78
79
0
  *psd = sd;
80
0
  return WERR_OK;
81
0
}
82
83
/***********************************************************************
84
 High level wrapper function for storing registry subkeys
85
 ***********************************************************************/
86
87
bool store_reg_keys(struct registry_key_handle *key,
88
        struct regsubkey_ctr *subkeys)
89
0
{
90
0
  if (key->ops && key->ops->store_subkeys)
91
0
    return key->ops->store_subkeys(key->name, subkeys);
92
93
0
  return false;
94
0
}
95
96
/***********************************************************************
97
 High level wrapper function for storing registry values
98
 ***********************************************************************/
99
100
bool store_reg_values(struct registry_key_handle *key, struct regval_ctr *val)
101
0
{
102
0
  if (key->ops && key->ops->store_values)
103
0
    return key->ops->store_values(key->name, val);
104
105
0
  return false;
106
0
}
107
108
WERROR create_reg_subkey(struct registry_key_handle *key, const char *subkey)
109
0
{
110
0
  if (key->ops && key->ops->create_subkey) {
111
0
    return key->ops->create_subkey(key->name, subkey);
112
0
  }
113
114
0
  return WERR_NOT_SUPPORTED;
115
0
}
116
117
WERROR delete_reg_subkey(struct registry_key_handle *key, const char *subkey, bool lazy)
118
0
{
119
0
  if (key->ops && key->ops->delete_subkey) {
120
0
    return key->ops->delete_subkey(key->name, subkey, lazy);
121
0
  }
122
123
0
  return WERR_NOT_SUPPORTED;
124
0
}
125
126
/***********************************************************************
127
 High level wrapper function for enumerating registry subkeys
128
 Initialize the TALLOC_CTX if necessary
129
 ***********************************************************************/
130
131
int fetch_reg_keys(struct registry_key_handle *key,
132
       struct regsubkey_ctr *subkey_ctr)
133
0
{
134
0
  int result = -1;
135
136
0
  if (key->ops && key->ops->fetch_subkeys)
137
0
    result = key->ops->fetch_subkeys(key->name, subkey_ctr);
138
139
0
  return result;
140
0
}
141
142
/***********************************************************************
143
 High level wrapper function for enumerating registry values
144
 ***********************************************************************/
145
146
int fetch_reg_values(struct registry_key_handle *key, struct regval_ctr *val)
147
0
{
148
0
  int result = -1;
149
150
0
  DEBUG(10, ("fetch_reg_values called for key '%s' (ops %p)\n", key->name,
151
0
       (key->ops) ? (void *)key->ops : NULL));
152
153
0
  if (key->ops && key->ops->fetch_values)
154
0
    result = key->ops->fetch_values(key->name, val);
155
156
0
  return result;
157
0
}
158
159
/***********************************************************************
160
 High level access check for passing the required access mask to the
161
 underlying registry backend
162
 ***********************************************************************/
163
164
bool regkey_access_check(struct registry_key_handle *key, uint32_t requested,
165
       uint32_t *granted,
166
       const struct security_token *token )
167
0
{
168
0
  struct security_descriptor *sec_desc;
169
0
  NTSTATUS status;
170
0
  WERROR err;
171
172
  /* root free-pass, like we have on all other pipes like samr, lsa, etc. */
173
0
  if (root_mode()) {
174
0
    *granted = REG_KEY_ALL;
175
0
    return true;
176
0
  }
177
178
  /* use the default security check if the backend has not defined its
179
   * own */
180
181
0
  if (key->ops && key->ops->reg_access_check) {
182
0
    return key->ops->reg_access_check(key->name, requested,
183
0
              granted, token);
184
0
  }
185
186
0
  err = regkey_get_secdesc(talloc_tos(), key, &sec_desc);
187
188
0
  if (!W_ERROR_IS_OK(err)) {
189
0
    return false;
190
0
  }
191
192
0
  se_map_generic( &requested, &reg_generic_map );
193
194
0
  status =se_access_check(sec_desc, token, requested, granted);
195
0
  TALLOC_FREE(sec_desc);
196
0
  if (!NT_STATUS_IS_OK(status)) {
197
0
    return false;
198
0
  }
199
200
0
  return NT_STATUS_IS_OK(status);
201
0
}
202
203
WERROR regkey_get_secdesc(TALLOC_CTX *mem_ctx, struct registry_key_handle *key,
204
        struct security_descriptor **psecdesc)
205
0
{
206
0
  struct security_descriptor *secdesc;
207
0
  WERROR werr;
208
209
0
  if (key->ops && key->ops->get_secdesc) {
210
0
    werr = key->ops->get_secdesc(mem_ctx, key->name, psecdesc);
211
0
    if (W_ERROR_IS_OK(werr)) {
212
0
      return WERR_OK;
213
0
    }
214
0
  }
215
216
0
  werr = construct_registry_sd(mem_ctx, &secdesc);
217
0
  if (!W_ERROR_IS_OK(werr)) {
218
0
    return werr;
219
0
  }
220
221
0
  *psecdesc = secdesc;
222
0
  return WERR_OK;
223
0
}
224
225
WERROR regkey_set_secdesc(struct registry_key_handle *key,
226
        struct security_descriptor *psecdesc)
227
0
{
228
0
  if (key->ops && key->ops->set_secdesc) {
229
0
    return key->ops->set_secdesc(key->name, psecdesc);
230
0
  }
231
232
0
  return WERR_ACCESS_DENIED;
233
0
}
234
235
/**
236
 * Check whether the in-memory version of the subkyes of a
237
 * registry key needs update from disk.
238
 */
239
bool reg_subkeys_need_update(struct registry_key_handle *key,
240
           struct regsubkey_ctr *subkeys)
241
0
{
242
0
  if (key->ops && key->ops->subkeys_need_update)
243
0
  {
244
0
    return key->ops->subkeys_need_update(subkeys);
245
0
  }
246
247
0
  return true;
248
0
}
249
250
/**
251
 * Check whether the in-memory version of the values of a
252
 * registry key needs update from disk.
253
 */
254
bool reg_values_need_update(struct registry_key_handle *key,
255
          struct regval_ctr *values)
256
0
{
257
0
  if (key->ops && key->ops->values_need_update)
258
0
  {
259
0
    return key->ops->values_need_update(values);
260
0
  }
261
262
0
  return true;
263
0
}
264