Rename libnet_reg_createkey_internal() to libnet_smbconf_reg_createkey_internal().
[ira/wip.git] / source / libnet / libnet_conf.c
1 /*
2  *  Unix SMB/CIFS implementation.
3  *  libnet smbconf registry Support
4  *  Copyright (C) Michael Adam 2007
5  *  Copyright (C) Guenther Deschner 2007
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 #include "includes.h"
22
23 /**********************************************************************
24  *
25  * Helper functions (mostly registry related)
26  * TODO: These should be eventually static.
27
28  **********************************************************************/
29
30 /*
31  * Open a subkey of KEY_SMBCONF (i.e a service)
32  * - variant without error output (q = quiet)-
33  */
34 static WERROR libnet_smbconf_open_path_q(TALLOC_CTX *ctx,
35                                          const char *subkeyname,
36                                          uint32 desired_access,
37                                          struct registry_key **key)
38 {
39         WERROR werr = WERR_OK;
40         char *path = NULL;
41         NT_USER_TOKEN *token;
42
43         if (!(token = registry_create_admin_token(ctx))) {
44                 DEBUG(1, ("Error creating admin token\n"));
45                 goto done;
46         }
47
48         if (subkeyname == NULL) {
49                 path = talloc_strdup(ctx, KEY_SMBCONF);
50         } else {
51                 path = talloc_asprintf(ctx, "%s\\%s", KEY_SMBCONF, subkeyname);
52         }
53
54         werr = reg_open_path(ctx, path, desired_access,
55                              token, key);
56
57 done:
58         TALLOC_FREE(path);
59         return werr;
60 }
61
62 /*
63  * check if a subkey of KEY_SMBCONF of a given name exists
64  */
65 bool libnet_smbconf_key_exists(TALLOC_CTX *ctx, const char *subkeyname)
66 {
67         bool ret = False;
68         WERROR werr = WERR_OK;
69         TALLOC_CTX *mem_ctx;
70         struct registry_key *key;
71
72         if (!(mem_ctx = talloc_new(ctx))) {
73                 d_fprintf(stderr, "ERROR: Out of memory...!\n");
74                 goto done;
75         }
76
77         werr = libnet_smbconf_open_path_q(mem_ctx, subkeyname, REG_KEY_READ, &key);
78         if (W_ERROR_IS_OK(werr)) {
79                 ret = True;
80         }
81
82 done:
83         TALLOC_FREE(mem_ctx);
84         return ret;
85 }
86
87 static bool libnet_smbconf_value_exists(TALLOC_CTX *ctx,
88                                         struct registry_key *key,
89                                         const char *param)
90 {
91         bool ret = False;
92         WERROR werr = WERR_OK;
93         struct registry_value *value = NULL;
94
95         werr = reg_queryvalue(ctx, key, param, &value);
96         if (W_ERROR_IS_OK(werr)) {
97                 ret = True;
98         }
99
100         TALLOC_FREE(value);
101         return ret;
102 }
103
104 /*
105  * Open a subkey of KEY_SMBCONF (i.e a service)
106  * - variant with error output -
107  */
108 WERROR libnet_smbconf_open_path(TALLOC_CTX *ctx, const char *subkeyname,
109                                 uint32 desired_access,
110                                 struct registry_key **key)
111 {
112         WERROR werr = WERR_OK;
113
114         werr = libnet_smbconf_open_path_q(ctx, subkeyname, desired_access, key);
115         if (!W_ERROR_IS_OK(werr)) {
116                 d_fprintf(stderr, "Error opening registry path '%s\\%s': %s\n",
117                           KEY_SMBCONF,
118                           (subkeyname == NULL) ? "" : subkeyname,
119                           dos_errstr(werr));
120         }
121
122         return werr;
123 }
124
125 /*
126  * open the base key KEY_SMBCONF
127  */
128 WERROR libnet_smbconf_open_basepath(TALLOC_CTX *ctx, uint32 desired_access,
129                                     struct registry_key **key)
130 {
131         return libnet_smbconf_open_path(ctx, NULL, desired_access, key);
132 }
133
134 /*
135  * create a subkey of KEY_SMBCONF
136  */
137 WERROR libnet_smbconf_reg_createkey_internal(TALLOC_CTX *ctx,
138                                              const char * subkeyname,
139                                              struct registry_key **newkey)
140 {
141         WERROR werr = WERR_OK;
142         struct registry_key *create_parent = NULL;
143         TALLOC_CTX *create_ctx;
144         enum winreg_CreateAction action = REG_ACTION_NONE;
145
146         /* create a new talloc ctx for creation. it will hold
147          * the intermediate parent key (SMBCONF) for creation
148          * and will be destroyed when leaving this function... */
149         if (!(create_ctx = talloc_new(ctx))) {
150                 werr = WERR_NOMEM;
151                 goto done;
152         }
153
154         werr = libnet_smbconf_open_basepath(create_ctx, REG_KEY_WRITE, &create_parent);
155         if (!W_ERROR_IS_OK(werr)) {
156                 goto done;
157         }
158
159         werr = reg_createkey(ctx, create_parent, subkeyname,
160                              REG_KEY_WRITE, newkey, &action);
161         if (W_ERROR_IS_OK(werr) && (action != REG_CREATED_NEW_KEY)) {
162                 d_fprintf(stderr, "Key '%s' already exists.\n", subkeyname);
163                 werr = WERR_ALREADY_EXISTS;
164         }
165         if (!W_ERROR_IS_OK(werr)) {
166                 d_fprintf(stderr, "Error creating key %s: %s\n",
167                          subkeyname, dos_errstr(werr));
168         }
169
170 done:
171         TALLOC_FREE(create_ctx);
172         return werr;
173 }
174
175 /*
176  * add a value to a key.
177  */
178 WERROR libnet_smbconf_reg_setvalue_internal(struct registry_key *key,
179                                                    const char *valname,
180                                                    const char *valstr)
181 {
182         struct registry_value val;
183         WERROR werr = WERR_OK;
184         char *subkeyname;
185         const char *canon_valname;
186         const char *canon_valstr;
187
188         if (!lp_canonicalize_parameter_with_value(valname, valstr,
189                                                   &canon_valname,
190                                                   &canon_valstr))
191         {
192                 if (canon_valname == NULL) {
193                         d_fprintf(stderr, "invalid parameter '%s' given\n",
194                                   valname);
195                 } else {
196                         d_fprintf(stderr, "invalid value '%s' given for "
197                                   "parameter '%s'\n", valstr, valname);
198                 }
199                 werr = WERR_INVALID_PARAM;
200                 goto done;
201         }
202
203         ZERO_STRUCT(val);
204
205         val.type = REG_SZ;
206         val.v.sz.str = CONST_DISCARD(char *, canon_valstr);
207         val.v.sz.len = strlen(canon_valstr) + 1;
208
209         if (registry_smbconf_valname_forbidden(canon_valname)) {
210                 d_fprintf(stderr, "Parameter '%s' not allowed in registry.\n",
211                           canon_valname);
212                 werr = WERR_INVALID_PARAM;
213                 goto done;
214         }
215
216         subkeyname = strrchr_m(key->key->name, '\\');
217         if ((subkeyname == NULL) || (*(subkeyname +1) == '\0')) {
218                 d_fprintf(stderr, "Invalid registry key '%s' given as "
219                           "smbconf section.\n", key->key->name);
220                 werr = WERR_INVALID_PARAM;
221                 goto done;
222         }
223         subkeyname++;
224         if (!strequal(subkeyname, GLOBAL_NAME) &&
225             lp_parameter_is_global(valname))
226         {
227                 d_fprintf(stderr, "Global paramter '%s' not allowed in "
228                           "service definition ('%s').\n", canon_valname,
229                           subkeyname);
230                 werr = WERR_INVALID_PARAM;
231                 goto done;
232         }
233
234         werr = reg_setvalue(key, canon_valname, &val);
235         if (!W_ERROR_IS_OK(werr)) {
236                 d_fprintf(stderr,
237                           "Error adding value '%s' to "
238                           "key '%s': %s\n",
239                           canon_valname, key->key->name, dos_errstr(werr));
240         }
241
242 done:
243         return werr;
244 }
245
246 /**********************************************************************
247  *
248  * The actual net conf api functions, that are exported.
249  *
250  **********************************************************************/
251
252 WERROR libnet_smbconf_setparm(TALLOC_CTX *mem_ctx,
253                               const char *service,
254                               const char *param,
255                               const char *valstr)
256 {
257         WERROR werr;
258         struct registry_key *key = NULL;
259
260         if (!libnet_smbconf_key_exists(mem_ctx, service)) {
261                 werr = libnet_smbconf_reg_createkey_internal(mem_ctx, service,
262                                                              &key);
263         } else {
264                 werr = libnet_smbconf_open_path(mem_ctx, service, REG_KEY_WRITE,
265                                                 &key);
266         }
267         W_ERROR_NOT_OK_RETURN(werr);
268
269         werr = libnet_smbconf_reg_setvalue_internal(key, param, valstr);
270
271         return werr;
272 }
273
274 WERROR libnet_smbconf_delparm(TALLOC_CTX *mem_ctx,
275                               const char *service,
276                               const char *param)
277 {
278         struct registry_key *key = NULL;
279         WERROR werr = WERR_OK;
280
281         if (!libnet_smbconf_key_exists(mem_ctx, service)) {
282                 return WERR_NO_SUCH_SERVICE;
283         }
284
285         werr = libnet_smbconf_open_path(mem_ctx, service, REG_KEY_READ, &key);
286         W_ERROR_NOT_OK_RETURN(werr);
287
288         if (!libnet_smbconf_value_exists(mem_ctx, key, param)) {
289                 return WERR_INVALID_PARAM;
290         }
291
292         werr = reg_deletevalue(key, param);
293         W_ERROR_NOT_OK_RETURN(werr);
294
295         return WERR_OK;
296 }
297
298
299 /**********************************************************************
300  *
301  * Convenience functions, that are also exportet.
302  *
303  **********************************************************************/
304
305 WERROR libnet_smbconf_set_global_param(TALLOC_CTX *mem_ctx,
306                                        const char *param,
307                                        const char *val)
308 {
309         return libnet_smbconf_setparm(mem_ctx, GLOBAL_NAME, param, val);
310 }
311