Print this page
NEX-5260 smbd segfaults while running smbtorture:rpc.lsa.lookupnames
NEX-5261 smbd segfaults while running smbtorture:rpc.winreg
NEX-5262 smbd segfaults while running smbtorture:rpc.samba3
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/winreg_svc.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
13 13 * When distributing Covered Code, include this CDDL HEADER in each
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21
22 22 /*
23 23 * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
24 + * Copyright 2016 Nexenta Systems, Inc. All rights reserved.
24 25 */
25 26
26 27 /*
27 28 * Windows Registry RPC (WINREG) server-side interface.
28 29 *
29 30 * The registry is a database with a hierarchical structure similar to
30 31 * a file system, with keys in place of directories and values in place
31 32 * of files. The top level keys are known as root keys and each key can
32 33 * contain subkeys and values. As with directories and sub-directories,
33 34 * the terms key and subkey are used interchangeably. Values, analogous
34 35 * to files, contain data.
35 36 *
36 37 * A specific subkey can be identifies by its fully qualified name (FQN),
37 38 * which is analogous to a file system path. In the registry, the key
38 39 * separator is the '\' character, which is reserved and cannot appear
39 40 * in key or value names. Registry names are case-insensitive.
40 41 *
41 42 * For example: HKEY_LOCAL_MACHINE\System\CurrentControlSet
42 43 *
43 44 * The HKEY_LOCAL_MACHINE root key contains a subkey called System, and
44 45 * System contains a subkey called CurrentControlSet.
45 46 *
46 47 * The WINREG RPC interface returns Win32 error codes.
47 48 */
48 49
49 50 #include <sys/utsname.h>
50 51 #include <strings.h>
51 52
52 53 #include <smbsrv/libsmb.h>
53 54 #include <smbsrv/nmpipes.h>
54 55 #include <smbsrv/libmlsvc.h>
55 56 #include <smbsrv/ndl/winreg.ndl>
56 57
57 58 /*
58 59 * List of supported registry keys (case-insensitive).
59 60 */
60 61 static char *winreg_keys[] = {
61 62 "HKLM",
62 63 "HKU",
63 64 "HKLM\\SOFTWARE",
64 65 "HKLM\\SYSTEM",
65 66 "System",
66 67 "CurrentControlSet",
67 68 "SunOS",
68 69 "Solaris",
69 70 "System\\CurrentControlSet\\Services\\Eventlog",
70 71 "System\\CurrentControlSet\\Control\\ProductOptions",
71 72 "SOFTWARE",
72 73 "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion"
73 74 };
74 75
75 76 static char *winreg_eventlog = "System\\CurrentControlSet\\Services\\Eventlog";
76 77
77 78 static char *winreg_log[] = {
78 79 "Application",
79 80 "Security",
80 81 "System",
81 82 "smbd",
82 83 "smbrdr"
83 84 };
84 85
85 86 typedef struct winreg_subkey {
86 87 list_node_t sk_lnd;
87 88 ndr_hdid_t sk_handle;
88 89 char sk_name[MAXPATHLEN];
89 90 boolean_t sk_predefined;
90 91 } winreg_subkey_t;
91 92
92 93 typedef struct winreg_keylist {
93 94 list_t kl_list;
94 95 int kl_count;
95 96 } winreg_keylist_t;
96 97
97 98 static winreg_keylist_t winreg_keylist;
98 99 static mutex_t winreg_mutex;
99 100
100 101 static void winreg_add_predefined(const char *);
101 102 static ndr_hdid_t *winreg_alloc_id(ndr_xa_t *, const char *);
102 103 static void winreg_dealloc_id(ndr_xa_t *, ndr_hdid_t *);
103 104 static boolean_t winreg_key_has_subkey(const char *);
104 105 static char *winreg_enum_subkey(ndr_xa_t *, const char *, uint32_t);
105 106 static char *winreg_lookup_value(const char *);
106 107 static uint32_t winreg_sd_format(smb_sd_t *);
107 108 uint32_t srvsvc_sd_set_relative(smb_sd_t *, uint8_t *);
108 109
109 110 static int winreg_s_OpenHKCR(void *, ndr_xa_t *);
110 111 static int winreg_s_OpenHKCU(void *, ndr_xa_t *);
111 112 static int winreg_s_OpenHKLM(void *, ndr_xa_t *);
112 113 static int winreg_s_OpenHKPD(void *, ndr_xa_t *);
113 114 static int winreg_s_OpenHKU(void *, ndr_xa_t *);
114 115 static int winreg_s_OpenHKCC(void *, ndr_xa_t *);
115 116 static int winreg_s_OpenHKDD(void *, ndr_xa_t *);
116 117 static int winreg_s_OpenHKPT(void *, ndr_xa_t *);
117 118 static int winreg_s_OpenHKPN(void *, ndr_xa_t *);
118 119 static int winreg_s_OpenHK(void *, ndr_xa_t *, const char *);
119 120 static int winreg_s_Close(void *, ndr_xa_t *);
120 121 static int winreg_s_CreateKey(void *, ndr_xa_t *);
121 122 static int winreg_s_DeleteKey(void *, ndr_xa_t *);
122 123 static int winreg_s_DeleteValue(void *, ndr_xa_t *);
123 124 static int winreg_s_EnumKey(void *, ndr_xa_t *);
124 125 static int winreg_s_EnumValue(void *, ndr_xa_t *);
125 126 static int winreg_s_FlushKey(void *, ndr_xa_t *);
126 127 static int winreg_s_GetKeySec(void *, ndr_xa_t *);
127 128 static int winreg_s_NotifyChange(void *, ndr_xa_t *);
128 129 static int winreg_s_OpenKey(void *, ndr_xa_t *);
129 130 static int winreg_s_QueryKey(void *, ndr_xa_t *);
130 131 static int winreg_s_QueryValue(void *, ndr_xa_t *);
131 132 static int winreg_s_SetKeySec(void *, ndr_xa_t *);
132 133 static int winreg_s_CreateValue(void *, ndr_xa_t *);
133 134 static int winreg_s_Shutdown(void *, ndr_xa_t *);
134 135 static int winreg_s_AbortShutdown(void *, ndr_xa_t *);
135 136 static int winreg_s_GetVersion(void *, ndr_xa_t *);
136 137
137 138 static ndr_stub_table_t winreg_stub_table[] = {
138 139 { winreg_s_OpenHKCR, WINREG_OPNUM_OpenHKCR },
139 140 { winreg_s_OpenHKCU, WINREG_OPNUM_OpenHKCU },
140 141 { winreg_s_OpenHKLM, WINREG_OPNUM_OpenHKLM },
141 142 { winreg_s_OpenHKPD, WINREG_OPNUM_OpenHKPD },
142 143 { winreg_s_OpenHKU, WINREG_OPNUM_OpenHKUsers },
143 144 { winreg_s_Close, WINREG_OPNUM_Close },
144 145 { winreg_s_CreateKey, WINREG_OPNUM_CreateKey },
145 146 { winreg_s_DeleteKey, WINREG_OPNUM_DeleteKey },
146 147 { winreg_s_DeleteValue, WINREG_OPNUM_DeleteValue },
147 148 { winreg_s_EnumKey, WINREG_OPNUM_EnumKey },
148 149 { winreg_s_EnumValue, WINREG_OPNUM_EnumValue },
149 150 { winreg_s_FlushKey, WINREG_OPNUM_FlushKey },
150 151 { winreg_s_GetKeySec, WINREG_OPNUM_GetKeySec },
151 152 { winreg_s_NotifyChange, WINREG_OPNUM_NotifyChange },
152 153 { winreg_s_OpenKey, WINREG_OPNUM_OpenKey },
153 154 { winreg_s_QueryKey, WINREG_OPNUM_QueryKey },
154 155 { winreg_s_QueryValue, WINREG_OPNUM_QueryValue },
155 156 { winreg_s_SetKeySec, WINREG_OPNUM_SetKeySec },
156 157 { winreg_s_CreateValue, WINREG_OPNUM_CreateValue },
157 158 { winreg_s_Shutdown, WINREG_OPNUM_Shutdown },
158 159 { winreg_s_AbortShutdown, WINREG_OPNUM_AbortShutdown },
159 160 { winreg_s_GetVersion, WINREG_OPNUM_GetVersion },
160 161 { winreg_s_OpenHKCC, WINREG_OPNUM_OpenHKCC },
161 162 { winreg_s_OpenHKDD, WINREG_OPNUM_OpenHKDD },
162 163 { winreg_s_OpenHKPT, WINREG_OPNUM_OpenHKPT },
163 164 { winreg_s_OpenHKPN, WINREG_OPNUM_OpenHKPN },
164 165 {0}
165 166 };
166 167
167 168 static ndr_service_t winreg_service = {
168 169 "Winreg", /* name */
169 170 "Windows Registry", /* desc */
170 171 "\\winreg", /* endpoint */
171 172 PIPE_WINREG, /* sec_addr_port */
172 173 "338cd001-2244-31f1-aaaa-900038001003", 1, /* abstract */
173 174 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */
174 175 0, /* no bind_instance_size */
175 176 0, /* no bind_req() */
176 177 0, /* no unbind_and_close() */
177 178 0, /* use generic_call_stub() */
178 179 &TYPEINFO(winreg_interface), /* interface ti */
179 180 winreg_stub_table /* stub_table */
180 181 };
181 182
182 183 static char winreg_sysname[SYS_NMLN];
183 184 static char winreg_sysver[SMB_VERSTR_LEN];
184 185
185 186 /*
186 187 * winreg_initialize
187 188 *
188 189 * Initialize and register the WINREG RPC interface with the RPC runtime
189 190 * library. It must be called in order to use either the client side
190 191 * or the server side functions.
191 192 */
192 193 void
193 194 winreg_initialize(void)
194 195 {
195 196 smb_version_t version;
196 197 struct utsname name;
197 198 char subkey[MAXPATHLEN];
198 199 char *sysname;
199 200 int i;
200 201
201 202 (void) mutex_lock(&winreg_mutex);
202 203
203 204 list_create(&winreg_keylist.kl_list, sizeof (winreg_subkey_t),
204 205 offsetof(winreg_subkey_t, sk_lnd));
205 206 winreg_keylist.kl_count = 0;
206 207
207 208 for (i = 0; i < sizeof (winreg_keys)/sizeof (winreg_keys[0]); ++i)
208 209 winreg_add_predefined(winreg_keys[i]);
209 210
210 211 for (i = 0; i < sizeof (winreg_log)/sizeof (winreg_log[0]); ++i) {
211 212 (void) snprintf(subkey, MAXPATHLEN, "%s", winreg_log[i]);
212 213 winreg_add_predefined(subkey);
213 214
214 215 (void) snprintf(subkey, MAXPATHLEN, "%s\\%s",
215 216 winreg_eventlog, winreg_log[i]);
216 217 winreg_add_predefined(subkey);
217 218
218 219 (void) snprintf(subkey, MAXPATHLEN, "%s\\%s\\%s",
219 220 winreg_eventlog, winreg_log[i], winreg_log[i]);
220 221 winreg_add_predefined(subkey);
221 222 }
222 223
223 224 (void) mutex_unlock(&winreg_mutex);
224 225
225 226 if (uname(&name) < 0)
226 227 sysname = "Solaris";
227 228 else
228 229 sysname = name.sysname;
229 230
230 231 (void) strlcpy(winreg_sysname, sysname, SYS_NMLN);
231 232
232 233 smb_config_get_version(&version);
233 234 (void) snprintf(winreg_sysver, SMB_VERSTR_LEN, "%d.%d",
234 235 version.sv_major, version.sv_minor);
235 236
236 237 (void) ndr_svc_register(&winreg_service);
237 238 }
238 239
239 240 static void
240 241 winreg_add_predefined(const char *subkey)
241 242 {
242 243 winreg_subkey_t *key;
243 244
244 245 if ((key = malloc(sizeof (winreg_subkey_t))) != NULL) {
245 246 bzero(key, sizeof (winreg_subkey_t));
246 247 (void) strlcpy(key->sk_name, subkey, MAXPATHLEN);
247 248 key->sk_predefined = B_TRUE;
248 249
249 250 list_insert_tail(&winreg_keylist.kl_list, key);
250 251 ++winreg_keylist.kl_count;
251 252 }
252 253 }
253 254
254 255 static int
255 256 winreg_s_OpenHKCR(void *arg, ndr_xa_t *mxa)
256 257 {
257 258 return (winreg_s_OpenHK(arg, mxa, "HKCR"));
258 259 }
259 260
260 261 static int
261 262 winreg_s_OpenHKCU(void *arg, ndr_xa_t *mxa)
262 263 {
263 264 return (winreg_s_OpenHK(arg, mxa, "HKCU"));
264 265 }
265 266
266 267 static int
267 268 winreg_s_OpenHKLM(void *arg, ndr_xa_t *mxa)
268 269 {
269 270 return (winreg_s_OpenHK(arg, mxa, "HKLM"));
270 271 }
271 272
272 273 static int
273 274 winreg_s_OpenHKPD(void *arg, ndr_xa_t *mxa)
274 275 {
275 276 return (winreg_s_OpenHK(arg, mxa, "HKPD"));
276 277 }
277 278
278 279 static int
279 280 winreg_s_OpenHKU(void *arg, ndr_xa_t *mxa)
280 281 {
281 282 return (winreg_s_OpenHK(arg, mxa, "HKU"));
282 283 }
283 284
284 285 static int
285 286 winreg_s_OpenHKCC(void *arg, ndr_xa_t *mxa)
286 287 {
287 288 return (winreg_s_OpenHK(arg, mxa, "HKCC"));
288 289 }
289 290
290 291 static int
291 292 winreg_s_OpenHKDD(void *arg, ndr_xa_t *mxa)
292 293 {
293 294 return (winreg_s_OpenHK(arg, mxa, "HKDD"));
294 295 }
295 296
296 297 static int
297 298 winreg_s_OpenHKPT(void *arg, ndr_xa_t *mxa)
298 299 {
299 300 return (winreg_s_OpenHK(arg, mxa, "HKPT"));
300 301 }
301 302
302 303 static int
303 304 winreg_s_OpenHKPN(void *arg, ndr_xa_t *mxa)
304 305 {
305 306 return (winreg_s_OpenHK(arg, mxa, "HKPN"));
306 307 }
307 308
308 309 /*
309 310 * winreg_s_OpenHK
310 311 *
311 312 * Common code to open root HKEYs.
312 313 */
313 314 static int
314 315 winreg_s_OpenHK(void *arg, ndr_xa_t *mxa, const char *hkey)
315 316 {
316 317 struct winreg_OpenHKCR *param = arg;
317 318 ndr_hdid_t *id;
318 319
319 320 (void) mutex_lock(&winreg_mutex);
320 321
321 322 if ((id = winreg_alloc_id(mxa, hkey)) == NULL) {
322 323 bzero(¶m->handle, sizeof (winreg_handle_t));
323 324 param->status = ERROR_ACCESS_DENIED;
324 325 } else {
325 326 bcopy(id, ¶m->handle, sizeof (winreg_handle_t));
326 327 param->status = ERROR_SUCCESS;
327 328 }
328 329
329 330 (void) mutex_unlock(&winreg_mutex);
330 331 return (NDR_DRC_OK);
331 332 }
332 333
333 334 /*
334 335 * winreg_s_Close
335 336 *
336 337 * This is a request to close the WINREG interface specified by the
337 338 * handle. We don't track handles (yet), so just zero out the handle
338 339 * and return NDR_DRC_OK. Setting the handle to zero appears to be
339 340 * standard behaviour.
340 341 */
341 342 static int
342 343 winreg_s_Close(void *arg, ndr_xa_t *mxa)
343 344 {
344 345 struct winreg_Close *param = arg;
345 346 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
346 347
347 348 (void) mutex_lock(&winreg_mutex);
348 349 winreg_dealloc_id(mxa, id);
349 350 (void) mutex_unlock(&winreg_mutex);
350 351
351 352 bzero(¶m->result_handle, sizeof (winreg_handle_t));
352 353 param->status = ERROR_SUCCESS;
353 354 return (NDR_DRC_OK);
354 355 }
355 356
356 357 static ndr_hdid_t *
357 358 winreg_alloc_id(ndr_xa_t *mxa, const char *key)
358 359 {
359 360 ndr_handle_t *hd;
360 361 ndr_hdid_t *id;
361 362 char *data;
362 363
363 364 if ((data = strdup(key)) == NULL)
364 365 return (NULL);
365 366
366 367 if ((id = ndr_hdalloc(mxa, data)) == NULL) {
367 368 free(data);
368 369 return (NULL);
369 370 }
370 371
371 372 if ((hd = ndr_hdlookup(mxa, id)) != NULL)
372 373 hd->nh_data_free = free;
373 374
374 375 return (id);
375 376 }
376 377
377 378 static void
378 379 winreg_dealloc_id(ndr_xa_t *mxa, ndr_hdid_t *id)
379 380 {
380 381 ndr_handle_t *hd;
381 382
382 383 if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
383 384 free(hd->nh_data);
384 385 hd->nh_data = NULL;
385 386 }
386 387
387 388 ndr_hdfree(mxa, id);
388 389 }
389 390
390 391 /*
391 392 * winreg_s_CreateKey
392 393 */
393 394 static int
394 395 winreg_s_CreateKey(void *arg, ndr_xa_t *mxa)
395 396 {
396 397 struct winreg_CreateKey *param = arg;
397 398 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
398 399 ndr_handle_t *hd;
399 400 winreg_subkey_t *key;
400 401 char *subkey;
401 402 DWORD *action;
402 403
403 404 subkey = (char *)param->subkey.str;
404 405
405 406 if (!ndr_is_admin(mxa) || (subkey == NULL)) {
406 407 bzero(param, sizeof (struct winreg_CreateKey));
407 408 param->status = ERROR_ACCESS_DENIED;
408 409 return (NDR_DRC_OK);
409 410 }
410 411
411 412 (void) mutex_lock(&winreg_mutex);
412 413
413 414 hd = ndr_hdlookup(mxa, id);
414 415 if (hd == NULL) {
415 416 (void) mutex_unlock(&winreg_mutex);
416 417 bzero(param, sizeof (struct winreg_CreateKey));
417 418 param->status = ERROR_INVALID_HANDLE;
418 419 return (NDR_DRC_OK);
419 420 }
420 421
421 422 if ((action = NDR_NEW(mxa, DWORD)) == NULL) {
422 423 (void) mutex_unlock(&winreg_mutex);
423 424 bzero(param, sizeof (struct winreg_CreateKey));
424 425 param->status = ERROR_NOT_ENOUGH_MEMORY;
425 426 return (NDR_DRC_OK);
426 427 }
427 428
428 429 if (list_is_empty(&winreg_keylist.kl_list))
429 430 goto new_key;
430 431
431 432 /*
432 433 * Check for an existing key.
433 434 */
434 435 key = list_head(&winreg_keylist.kl_list);
435 436 do {
436 437 if (strcasecmp(subkey, key->sk_name) == 0) {
437 438 bcopy(&key->sk_handle, ¶m->result_handle,
438 439 sizeof (winreg_handle_t));
439 440
440 441 (void) mutex_unlock(&winreg_mutex);
441 442 *action = WINREG_ACTION_EXISTING_KEY;
442 443 param->action = action;
443 444 param->status = ERROR_SUCCESS;
444 445 return (NDR_DRC_OK);
445 446 }
446 447 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
447 448
448 449 new_key:
449 450 /*
450 451 * Create a new key.
451 452 */
452 453 if ((id = winreg_alloc_id(mxa, subkey)) == NULL)
453 454 goto no_memory;
454 455
455 456 if ((key = malloc(sizeof (winreg_subkey_t))) == NULL) {
456 457 winreg_dealloc_id(mxa, id);
457 458 goto no_memory;
458 459 }
459 460
460 461 bcopy(id, &key->sk_handle, sizeof (ndr_hdid_t));
461 462 (void) strlcpy(key->sk_name, subkey, MAXPATHLEN);
462 463 key->sk_predefined = B_FALSE;
463 464 list_insert_tail(&winreg_keylist.kl_list, key);
464 465 ++winreg_keylist.kl_count;
465 466
466 467 bcopy(id, ¶m->result_handle, sizeof (winreg_handle_t));
467 468
468 469 (void) mutex_unlock(&winreg_mutex);
469 470 *action = WINREG_ACTION_NEW_KEY;
470 471 param->action = action;
471 472 param->status = ERROR_SUCCESS;
472 473 return (NDR_DRC_OK);
473 474
474 475 no_memory:
475 476 (void) mutex_unlock(&winreg_mutex);
476 477 bzero(param, sizeof (struct winreg_CreateKey));
477 478 param->status = ERROR_NOT_ENOUGH_MEMORY;
478 479 return (NDR_DRC_OK);
479 480 }
480 481
481 482 /*
482 483 * winreg_s_DeleteKey
483 484 */
484 485 static int
485 486 winreg_s_DeleteKey(void *arg, ndr_xa_t *mxa)
486 487 {
487 488 struct winreg_DeleteKey *param = arg;
488 489 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
489 490 winreg_subkey_t *key;
490 491 char *subkey;
491 492
492 493 subkey = (char *)param->subkey.str;
493 494
494 495 if (!ndr_is_admin(mxa) || (subkey == NULL)) {
495 496 param->status = ERROR_ACCESS_DENIED;
496 497 return (NDR_DRC_OK);
497 498 }
498 499
499 500 (void) mutex_lock(&winreg_mutex);
500 501
501 502 if ((ndr_hdlookup(mxa, id) == NULL) ||
502 503 list_is_empty(&winreg_keylist.kl_list) ||
503 504 winreg_key_has_subkey(subkey)) {
504 505 (void) mutex_unlock(&winreg_mutex);
505 506 param->status = ERROR_ACCESS_DENIED;
506 507 return (NDR_DRC_OK);
507 508 }
508 509
509 510 key = list_head(&winreg_keylist.kl_list);
510 511 do {
511 512 if (strcasecmp(subkey, key->sk_name) == 0) {
512 513 if (key->sk_predefined == B_TRUE) {
513 514 /* Predefined keys cannot be deleted */
514 515 break;
515 516 }
516 517
517 518 list_remove(&winreg_keylist.kl_list, key);
518 519 --winreg_keylist.kl_count;
519 520 winreg_dealloc_id(mxa, &key->sk_handle);
520 521 free(key);
521 522
522 523 (void) mutex_unlock(&winreg_mutex);
523 524 param->status = ERROR_SUCCESS;
524 525 return (NDR_DRC_OK);
525 526 }
526 527 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
527 528
528 529 (void) mutex_unlock(&winreg_mutex);
529 530 param->status = ERROR_ACCESS_DENIED;
530 531 return (NDR_DRC_OK);
531 532 }
532 533
533 534 /*
534 535 * Call with the winreg_mutex held.
535 536 */
536 537 static boolean_t
537 538 winreg_key_has_subkey(const char *subkey)
538 539 {
539 540 winreg_subkey_t *key;
540 541 int keylen;
541 542
542 543 if (list_is_empty(&winreg_keylist.kl_list))
543 544 return (B_FALSE);
544 545
545 546 keylen = strlen(subkey);
546 547
547 548 key = list_head(&winreg_keylist.kl_list);
548 549 do {
549 550 if (strncasecmp(subkey, key->sk_name, keylen) == 0) {
550 551 /*
551 552 * Potential match. If sk_name is longer than
552 553 * subkey, then sk_name is a subkey of our key.
553 554 */
554 555 if (keylen < strlen(key->sk_name))
555 556 return (B_TRUE);
556 557 }
557 558 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
558 559
559 560 return (B_FALSE);
560 561 }
561 562
562 563 /*
563 564 * Call with the winreg_mutex held.
564 565 */
565 566 static char *
566 567 winreg_enum_subkey(ndr_xa_t *mxa, const char *subkey, uint32_t index)
567 568 {
568 569 winreg_subkey_t *key;
569 570 char *entry;
570 571 char *p;
571 572 int subkeylen;
572 573 int count = 0;
573 574
574 575 if (subkey == NULL)
575 576 return (NULL);
576 577
577 578 if (list_is_empty(&winreg_keylist.kl_list))
578 579 return (NULL);
579 580
580 581 subkeylen = strlen(subkey);
581 582
582 583 for (key = list_head(&winreg_keylist.kl_list);
583 584 key != NULL; key = list_next(&winreg_keylist.kl_list, key)) {
584 585 if (strncasecmp(subkey, key->sk_name, subkeylen) == 0) {
585 586 p = key->sk_name + subkeylen;
586 587
587 588 if ((*p != '\\') || (*p == '\0')) {
588 589 /*
589 590 * Not the same subkey or an exact match.
590 591 * We're looking for children of subkey.
591 592 */
592 593 continue;
593 594 }
594 595
595 596 ++p;
596 597
597 598 if (count < index) {
598 599 ++count;
599 600 continue;
600 601 }
601 602
602 603 if ((entry = NDR_STRDUP(mxa, p)) == NULL)
603 604 return (NULL);
604 605
605 606 if ((p = strchr(entry, '\\')) != NULL)
606 607 *p = '\0';
607 608
608 609 return (entry);
609 610 }
610 611 }
611 612
612 613 return (NULL);
613 614 }
614 615
615 616 /*
616 617 * winreg_s_DeleteValue
617 618 */
618 619 /*ARGSUSED*/
619 620 static int
620 621 winreg_s_DeleteValue(void *arg, ndr_xa_t *mxa)
621 622 {
622 623 struct winreg_DeleteValue *param = arg;
623 624
624 625 param->status = ERROR_ACCESS_DENIED;
625 626 return (NDR_DRC_OK);
626 627 }
627 628
628 629 /*
629 630 * winreg_s_EnumKey
630 631 */
631 632 static int
632 633 winreg_s_EnumKey(void *arg, ndr_xa_t *mxa)
633 634 {
634 635 struct winreg_EnumKey *param = arg;
635 636 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
636 637 ndr_handle_t *hd;
637 638 char *subkey;
638 639 char *name = NULL;
639 640
640 641 (void) mutex_lock(&winreg_mutex);
641 642
642 643 if ((hd = ndr_hdlookup(mxa, id)) != NULL)
643 644 name = hd->nh_data;
644 645
645 646 if (hd == NULL || name == NULL) {
646 647 (void) mutex_unlock(&winreg_mutex);
647 648 bzero(param, sizeof (struct winreg_EnumKey));
648 649 param->status = ERROR_NO_MORE_ITEMS;
649 650 return (NDR_DRC_OK);
650 651 }
651 652
652 653 subkey = winreg_enum_subkey(mxa, name, param->index);
653 654 if (subkey == NULL) {
654 655 (void) mutex_unlock(&winreg_mutex);
655 656 bzero(param, sizeof (struct winreg_EnumKey));
656 657 param->status = ERROR_NO_MORE_ITEMS;
657 658 return (NDR_DRC_OK);
658 659 }
659 660
660 661 if (NDR_MSTRING(mxa, subkey, (ndr_mstring_t *)¶m->name_out) == -1) {
661 662 (void) mutex_unlock(&winreg_mutex);
662 663 bzero(param, sizeof (struct winreg_EnumKey));
663 664 param->status = ERROR_NOT_ENOUGH_MEMORY;
664 665 return (NDR_DRC_OK);
665 666 }
666 667
667 668 (void) mutex_unlock(&winreg_mutex);
668 669
669 670 /*
670 671 * This request requires that the length includes the null.
671 672 */
672 673 param->name_out.length = param->name_out.allosize;
673 674 param->status = ERROR_SUCCESS;
674 675 return (NDR_DRC_OK);
675 676 }
676 677
677 678 /*
678 679 * winreg_s_EnumValue
679 680 */
680 681 static int
681 682 winreg_s_EnumValue(void *arg, ndr_xa_t *mxa)
682 683 {
683 684 struct winreg_EnumValue *param = arg;
684 685 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
685 686
686 687 if (ndr_hdlookup(mxa, id) == NULL) {
687 688 bzero(param, sizeof (struct winreg_EnumValue));
688 689 param->status = ERROR_NO_MORE_ITEMS;
689 690 return (NDR_DRC_OK);
690 691 }
691 692
692 693 bzero(param, sizeof (struct winreg_EnumValue));
693 694 param->status = ERROR_NO_MORE_ITEMS;
694 695 return (NDR_DRC_OK);
695 696 }
696 697
697 698 /*
698 699 * winreg_s_FlushKey
699 700 *
700 701 * Flush the attributes associated with the specified open key to disk.
701 702 */
702 703 static int
703 704 winreg_s_FlushKey(void *arg, ndr_xa_t *mxa)
704 705 {
705 706 struct winreg_FlushKey *param = arg;
706 707 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
707 708
708 709 if (ndr_hdlookup(mxa, id) == NULL)
709 710 param->status = ERROR_INVALID_HANDLE;
710 711 else
711 712 param->status = ERROR_SUCCESS;
712 713
713 714 return (NDR_DRC_OK);
714 715 }
715 716
716 717 /*
717 718 * winreg_s_GetKeySec
718 719 */
719 720 static int
720 721 winreg_s_GetKeySec(void *arg, ndr_xa_t *mxa)
721 722 {
722 723 static struct winreg_secdesc error_sd;
723 724 struct winreg_GetKeySec *param = arg;
724 725 struct winreg_value *sd_buf;
725 726 smb_sd_t sd;
726 727 uint32_t sd_len;
727 728 uint32_t status;
728 729
729 730 bzero(&sd, sizeof (smb_sd_t));
730 731
731 732 if ((status = winreg_sd_format(&sd)) != ERROR_SUCCESS)
732 733 goto winreg_getkeysec_error;
733 734
734 735 sd_len = smb_sd_len(&sd, SMB_ALL_SECINFO);
735 736 sd_buf = NDR_MALLOC(mxa, sd_len + sizeof (struct winreg_value));
736 737
737 738 param->sd = NDR_MALLOC(mxa, sizeof (struct winreg_secdesc));
738 739 if ((param->sd == NULL) || (sd_buf == NULL)) {
739 740 status = ERROR_NOT_ENOUGH_MEMORY;
740 741 goto winreg_getkeysec_error;
741 742 }
742 743
743 744 param->sd->sd_len = sd_len;
744 745 param->sd->sd_size = sd_len;
745 746 param->sd->sd_buf = sd_buf;
746 747
747 748 sd_buf->vc_first_is = 0;
748 749 sd_buf->vc_length_is = sd_len;
749 750 param->status = srvsvc_sd_set_relative(&sd, sd_buf->value);
750 751
751 752 smb_sd_term(&sd);
752 753 return (NDR_DRC_OK);
753 754
754 755 winreg_getkeysec_error:
755 756 smb_sd_term(&sd);
756 757 bzero(param, sizeof (struct winreg_GetKeySec));
757 758 param->sd = &error_sd;
758 759 param->status = status;
759 760 return (NDR_DRC_OK);
760 761 }
761 762
762 763 static uint32_t
763 764 winreg_sd_format(smb_sd_t *sd)
764 765 {
765 766 smb_fssd_t fs_sd;
766 767 acl_t *acl;
767 768 uint32_t status = ERROR_SUCCESS;
768 769
769 770 if (acl_fromtext("owner@:rwxpdDaARWcCos::allow", &acl) != 0)
770 771 return (ERROR_NOT_ENOUGH_MEMORY);
771 772
772 773 smb_fssd_init(&fs_sd, SMB_ALL_SECINFO, SMB_FSSD_FLAGS_DIR);
773 774 fs_sd.sd_uid = 0;
774 775 fs_sd.sd_gid = 0;
775 776 fs_sd.sd_zdacl = acl;
776 777 fs_sd.sd_zsacl = NULL;
777 778
778 779 if (smb_sd_fromfs(&fs_sd, sd) != NT_STATUS_SUCCESS)
779 780 status = ERROR_ACCESS_DENIED;
780 781 smb_fssd_term(&fs_sd);
781 782 return (status);
782 783 }
783 784
784 785 /*
785 786 * winreg_s_NotifyChange
786 787 */
787 788 static int
788 789 winreg_s_NotifyChange(void *arg, ndr_xa_t *mxa)
789 790 {
790 791 struct winreg_NotifyChange *param = arg;
791 792
792 793 if (ndr_is_admin(mxa))
793 794 param->status = ERROR_SUCCESS;
794 795 else
795 796 param->status = ERROR_ACCESS_DENIED;
796 797
797 798 return (NDR_DRC_OK);
798 799 }
799 800
800 801 /*
801 802 * winreg_s_OpenKey
802 803 *
803 804 * This is a request to open a windows registry key.
804 805 * If we recognize the key, we return a handle.
805 806 *
806 807 * Returns:
807 808 * ERROR_SUCCESS Valid handle returned.
808 809 * ERROR_FILE_NOT_FOUND No key or unable to allocate a handle.
809 810 */
810 811 static int
811 812 winreg_s_OpenKey(void *arg, ndr_xa_t *mxa)
812 813 {
813 814 struct winreg_OpenKey *param = arg;
814 815 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
815 816 ndr_handle_t *hd;
816 817 char *subkey = (char *)param->name.str;
817 818 winreg_subkey_t *key;
818 819
819 820 (void) mutex_lock(&winreg_mutex);
820 821
821 822 if (subkey == NULL || *subkey == '\0') {
822 823 if ((hd = ndr_hdlookup(mxa, id)) != NULL)
823 824 subkey = hd->nh_data;
824 825 }
825 826
826 827 id = NULL;
827 828
828 829 if (subkey == NULL || list_is_empty(&winreg_keylist.kl_list)) {
829 830 (void) mutex_unlock(&winreg_mutex);
830 831 bzero(¶m->result_handle, sizeof (winreg_handle_t));
831 832 param->status = ERROR_FILE_NOT_FOUND;
832 833 return (NDR_DRC_OK);
833 834 }
834 835
835 836 key = list_head(&winreg_keylist.kl_list);
836 837 do {
837 838 if (strcasecmp(subkey, key->sk_name) == 0) {
838 839 if (key->sk_predefined == B_TRUE)
839 840 id = winreg_alloc_id(mxa, subkey);
840 841 else
841 842 id = &key->sk_handle;
842 843
843 844 if (id == NULL)
844 845 break;
845 846
846 847 bcopy(id, ¶m->result_handle,
847 848 sizeof (winreg_handle_t));
848 849
849 850 (void) mutex_unlock(&winreg_mutex);
850 851 param->status = ERROR_SUCCESS;
851 852 return (NDR_DRC_OK);
852 853 }
853 854 } while ((key = list_next(&winreg_keylist.kl_list, key)) != NULL);
854 855
855 856 (void) mutex_unlock(&winreg_mutex);
856 857 bzero(¶m->result_handle, sizeof (winreg_handle_t));
857 858 param->status = ERROR_FILE_NOT_FOUND;
858 859 return (NDR_DRC_OK);
859 860 }
860 861
861 862 /*
862 863 * winreg_s_QueryKey
863 864 */
864 865 /*ARGSUSED*/
865 866 static int
866 867 winreg_s_QueryKey(void *arg, ndr_xa_t *mxa)
867 868 {
868 869 struct winreg_QueryKey *param = arg;
869 870 int rc;
870 871 winreg_string_t *name;
871 872
872 873 name = (winreg_string_t *)¶m->name;
873 874 bzero(param, sizeof (struct winreg_QueryKey));
874 875
875 876 if ((name = NDR_NEW(mxa, winreg_string_t)) != NULL)
876 877 rc = NDR_MSTRING(mxa, "", (ndr_mstring_t *)name);
877 878
878 879 if ((name == NULL) || (rc != 0)) {
879 880 bzero(param, sizeof (struct winreg_QueryKey));
880 881 param->status = ERROR_NOT_ENOUGH_MEMORY;
881 882 return (NDR_DRC_OK);
882 883 }
883 884
884 885 param->status = ERROR_SUCCESS;
885 886 return (NDR_DRC_OK);
886 887 }
887 888
888 889 /*
889 890 * winreg_s_QueryValue
890 891 *
891 892 * This is a request to get the value associated with a specified name.
892 893 *
893 894 * Returns:
894 895 * ERROR_SUCCESS Value returned.
895 896 * ERROR_FILE_NOT_FOUND PrimaryModule is not supported.
896 897 * ERROR_CANTREAD No such name or memory problem.
897 898 */
898 899 static int
899 900 winreg_s_QueryValue(void *arg, ndr_xa_t *mxa)
|
↓ open down ↓ |
866 lines elided |
↑ open up ↑ |
900 901 {
901 902 struct winreg_QueryValue *param = arg;
902 903 struct winreg_value *pv;
903 904 char *name;
904 905 char *value;
905 906 DWORD slen;
906 907 DWORD msize;
907 908
908 909 name = (char *)param->value_name.str;
909 910
910 - if (strcasecmp(name, "PrimaryModule") == 0) {
911 + if (name == NULL ||
912 + strcasecmp(name, "PrimaryModule") == 0) {
911 913 param->status = ERROR_FILE_NOT_FOUND;
912 914 return (NDR_DRC_OK);
913 915 }
914 916
915 917 if ((value = winreg_lookup_value(name)) == NULL) {
916 918 param->status = ERROR_CANTREAD;
917 919 return (NDR_DRC_OK);
918 920 }
919 921
920 922 slen = smb_wcequiv_strlen(value) + sizeof (smb_wchar_t);
921 923 msize = sizeof (struct winreg_value) + slen;
922 924
923 925 param->value = (struct winreg_value *)NDR_MALLOC(mxa, msize);
924 926 param->type = NDR_NEW(mxa, DWORD);
925 927 param->value_size = NDR_NEW(mxa, DWORD);
926 928 param->value_size_total = NDR_NEW(mxa, DWORD);
927 929
928 930 if (param->value == NULL || param->type == NULL ||
929 931 param->value_size == NULL || param->value_size_total == NULL) {
930 932 param->status = ERROR_CANTREAD;
931 933 return (NDR_DRC_OK);
932 934 }
933 935
934 936 bzero(param->value, msize);
935 937 pv = param->value;
936 938 pv->vc_first_is = 0;
937 939 pv->vc_length_is = slen;
938 940 /*LINTED E_BAD_PTR_CAST_ALIGN*/
939 941 (void) ndr_mbstowcs(NULL, (smb_wchar_t *)pv->value, value, slen);
940 942
941 943 *param->type = 1;
942 944 *param->value_size = slen;
943 945 *param->value_size_total = slen;
944 946
945 947 param->status = ERROR_SUCCESS;
946 948 return (NDR_DRC_OK);
947 949 }
948 950
949 951 /*
950 952 * Lookup a name in the registry and return the associated value.
951 953 * Our registry is a case-insensitive, name-value pair table.
952 954 *
953 955 * Windows ProductType: WinNT, ServerNT, LanmanNT.
954 956 * Windows NT4.0 workstation: WinNT
955 957 * Windows NT4.0 server: ServerNT
956 958 *
957 959 * If LanmanNT is used here, Windows 2000 sends LsarQueryInfoPolicy
958 960 * with info level 6, which we don't support. If we use ServerNT
959 961 * (as reported by NT4.0 Server) Windows 2000 send requests for
960 962 * levels 3 and 5, which are support.
961 963 *
962 964 * On success, returns a pointer to the value. Otherwise returns
963 965 * a null pointer.
964 966 */
965 967 static char *
966 968 winreg_lookup_value(const char *name)
967 969 {
968 970 static struct registry {
969 971 char *name;
970 972 char *value;
971 973 } registry[] = {
972 974 { "SystemRoot", "C:\\" },
973 975 { "CurrentVersion", winreg_sysver },
974 976 { "ProductType", "ServerNT" },
975 977 { "Sources", winreg_sysname }, /* product name */
976 978 { "EventMessageFile", "C:\\windows\\system32\\eventlog.dll" }
977 979 };
978 980
979 981 int i;
980 982
981 983 for (i = 0; i < sizeof (registry)/sizeof (registry[0]); ++i) {
982 984 if (strcasecmp(registry[i].name, name) == 0)
983 985 return (registry[i].value);
984 986 }
985 987
986 988 return (NULL);
987 989 }
988 990
989 991 /*
990 992 * winreg_s_SetKeySec
991 993 */
992 994 /*ARGSUSED*/
993 995 static int
994 996 winreg_s_SetKeySec(void *arg, ndr_xa_t *mxa)
995 997 {
996 998 struct winreg_SetKeySec *param = arg;
997 999
998 1000 param->status = ERROR_ACCESS_DENIED;
999 1001 return (NDR_DRC_OK);
1000 1002 }
1001 1003
1002 1004 /*
1003 1005 * winreg_s_CreateValue
1004 1006 */
1005 1007 /*ARGSUSED*/
1006 1008 static int
1007 1009 winreg_s_CreateValue(void *arg, ndr_xa_t *mxa)
1008 1010 {
1009 1011 struct winreg_CreateValue *param = arg;
1010 1012
1011 1013 param->status = ERROR_ACCESS_DENIED;
1012 1014 return (NDR_DRC_OK);
1013 1015 }
1014 1016
1015 1017 /*
1016 1018 * winreg_s_Shutdown
1017 1019 *
1018 1020 * Attempt to shutdown or reboot the system: access denied.
1019 1021 */
1020 1022 /*ARGSUSED*/
1021 1023 static int
1022 1024 winreg_s_Shutdown(void *arg, ndr_xa_t *mxa)
1023 1025 {
1024 1026 struct winreg_Shutdown *param = arg;
1025 1027
1026 1028 param->status = ERROR_ACCESS_DENIED;
1027 1029 return (NDR_DRC_OK);
1028 1030 }
1029 1031
1030 1032 /*
1031 1033 * winreg_s_AbortShutdown
1032 1034 *
1033 1035 * Abort a shutdown request.
1034 1036 */
1035 1037 static int
1036 1038 winreg_s_AbortShutdown(void *arg, ndr_xa_t *mxa)
1037 1039 {
1038 1040 struct winreg_AbortShutdown *param = arg;
1039 1041
1040 1042 if (ndr_is_admin(mxa))
1041 1043 param->status = ERROR_SUCCESS;
1042 1044 else
1043 1045 param->status = ERROR_ACCESS_DENIED;
1044 1046
1045 1047 return (NDR_DRC_OK);
1046 1048 }
1047 1049
1048 1050 /*
1049 1051 * winreg_s_GetVersion
1050 1052 *
1051 1053 * Return the windows registry version. The current version is 5.
1052 1054 * This call is usually made prior to enumerating or querying registry
1053 1055 * keys or values.
1054 1056 */
1055 1057 /*ARGSUSED*/
1056 1058 static int
1057 1059 winreg_s_GetVersion(void *arg, ndr_xa_t *mxa)
1058 1060 {
1059 1061 struct winreg_GetVersion *param = arg;
1060 1062
1061 1063 param->version = 5;
1062 1064 param->status = ERROR_SUCCESS;
1063 1065 return (NDR_DRC_OK);
1064 1066 }
|
↓ open down ↓ |
144 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX