Print this page
1575 untangle libmlrpc ... (smbsrv)
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/samr_svc.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/samr_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
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 24 * Copyright 2015 Nexenta Systems, Inc. All rights reserved.
25 25 */
26 26
27 27 /*
28 28 * Security Accounts Manager RPC (SAMR) server-side interface.
29 29 *
30 30 * The SAM is a hierarchical database:
31 31 * - If you want to talk to the SAM you need a SAM handle.
↓ open down ↓ |
31 lines elided |
↑ open up ↑ |
32 32 * - If you want to work with a domain, use the SAM handle.
33 33 * to obtain a domain handle.
34 34 * - Use domain handles to obtain user handles etc.
35 35 */
36 36
37 37 #include <strings.h>
38 38 #include <unistd.h>
39 39 #include <netdb.h>
40 40 #include <assert.h>
41 41 #include <grp.h>
42 +#include <libmlrpc/libmlrpc.h>
42 43 #include <smbsrv/libsmb.h>
43 -#include <smbsrv/libmlrpc.h>
44 44 #include <smbsrv/libmlsvc.h>
45 45 #include <smbsrv/smbinfo.h>
46 46 #include <smbsrv/nmpipes.h>
47 47 #include <smbsrv/ndl/samrpc.ndl>
48 48 #include <samlib.h>
49 49
50 50 /*
51 51 * The keys associated with the various handles dispensed by the SAMR
52 52 * server. These keys can be used to validate client activity.
53 53 * These values are never passed over the wire so security shouldn't
54 54 * be an issue.
55 55 */
56 56 typedef enum {
57 57 SAMR_KEY_NULL = 0,
58 58 SAMR_KEY_CONNECT,
59 59 SAMR_KEY_DOMAIN,
60 60 SAMR_KEY_USER,
61 61 SAMR_KEY_GROUP,
62 62 SAMR_KEY_ALIAS
63 63 } samr_key_t;
64 64
65 65 typedef struct samr_keydata {
66 66 samr_key_t kd_key;
67 67 smb_domain_type_t kd_type;
68 68 DWORD kd_rid;
69 69 } samr_keydata_t;
70 70
71 71 /*
72 72 * DomainDisplayUser All user objects (or those derived from user) with
73 73 * userAccountControl containing the UF_NORMAL_ACCOUNT bit.
74 74 *
75 75 * DomainDisplayMachine All user objects (or those derived from user) with
76 76 * userAccountControl containing the
77 77 * UF_WORKSTATION_TRUST_ACCOUNT or UF_SERVER_TRUST_ACCOUNT
78 78 * bit.
79 79 *
80 80 * DomainDisplayGroup All group objects (or those derived from group) with
81 81 * groupType equal to GROUP_TYPE_SECURITY_UNIVERSAL or
82 82 * GROUP_TYPE_SECURITY_ACCOUNT.
83 83 *
84 84 * DomainDisplayOemUser Same as DomainDisplayUser with OEM strings
85 85 *
86 86 * DomainDisplayOemGroup Same as DomainDisplayGroup with OEM strings
87 87 */
88 88 typedef enum {
89 89 DomainDisplayUser = 1,
90 90 DomainDisplayMachine,
91 91 DomainDispalyGroup,
92 92 DomainDisplayOemUser,
93 93 DomainDisplayOemGroup
94 94 } samr_displvl_t;
95 95
96 96 #define SAMR_VALID_DISPLEVEL(lvl) \
97 97 (((lvl) >= DomainDisplayUser) && ((lvl) <= DomainDisplayOemGroup))
98 98
99 99 #define SAMR_SUPPORTED_DISPLEVEL(lvl) (lvl == DomainDisplayUser)
100 100
101 101 static ndr_hdid_t *samr_hdalloc(ndr_xa_t *, samr_key_t, smb_domain_type_t,
102 102 DWORD);
103 103 static void samr_hdfree(ndr_xa_t *, ndr_hdid_t *);
104 104 static ndr_handle_t *samr_hdlookup(ndr_xa_t *, ndr_hdid_t *, samr_key_t);
105 105 static int samr_call_stub(ndr_xa_t *mxa);
106 106 static DWORD samr_s_enum_local_domains(struct samr_EnumLocalDomain *,
107 107 ndr_xa_t *);
108 108
109 109 static ndr_stub_table_t samr_stub_table[];
110 110
111 111 static ndr_service_t samr_service = {
112 112 "SAMR", /* name */
113 113 "Security Accounts Manager", /* desc */
114 114 "\\samr", /* endpoint */
115 115 PIPE_LSASS, /* sec_addr_port */
116 116 "12345778-1234-abcd-ef00-0123456789ac", 1, /* abstract */
117 117 NDR_TRANSFER_SYNTAX_UUID, 2, /* transfer */
118 118 0, /* no bind_instance_size */
119 119 NULL, /* no bind_req() */
120 120 NULL, /* no unbind_and_close() */
121 121 samr_call_stub, /* call_stub() */
122 122 &TYPEINFO(samr_interface), /* interface ti */
123 123 samr_stub_table /* stub_table */
124 124 };
125 125
126 126 /*
127 127 * samr_initialize
128 128 *
129 129 * This function registers the SAM RPC interface with the RPC runtime
130 130 * library. It must be called in order to use either the client side
131 131 * or the server side functions.
132 132 */
133 133 void
134 134 samr_initialize(void)
135 135 {
136 136 (void) ndr_svc_register(&samr_service);
137 137 }
138 138
139 139 /*
140 140 * Custom call_stub to set the stream string policy.
141 141 */
142 142 static int
143 143 samr_call_stub(ndr_xa_t *mxa)
144 144 {
145 145 NDS_SETF(&mxa->send_nds, NDS_F_NOTERM);
146 146 NDS_SETF(&mxa->recv_nds, NDS_F_NOTERM);
147 147
148 148 return (ndr_generic_call_stub(mxa));
149 149 }
150 150
151 151 /*
152 152 * Handle allocation wrapper to setup the local context.
153 153 */
154 154 static ndr_hdid_t *
155 155 samr_hdalloc(ndr_xa_t *mxa, samr_key_t key, smb_domain_type_t domain_type,
156 156 DWORD rid)
157 157 {
158 158 ndr_handle_t *hd;
159 159 ndr_hdid_t *id;
160 160 samr_keydata_t *data;
161 161
162 162 if ((data = malloc(sizeof (samr_keydata_t))) == NULL)
163 163 return (NULL);
164 164
165 165 data->kd_key = key;
166 166 data->kd_type = domain_type;
167 167 data->kd_rid = rid;
168 168
169 169 if ((id = ndr_hdalloc(mxa, data)) == NULL) {
170 170 free(data);
171 171 return (NULL);
172 172 }
173 173
174 174 if ((hd = ndr_hdlookup(mxa, id)) != NULL)
175 175 hd->nh_data_free = free;
176 176
177 177 return (id);
178 178 }
179 179
180 180 /*
181 181 * Handle deallocation wrapper to free the local context.
182 182 */
183 183 static void
184 184 samr_hdfree(ndr_xa_t *mxa, ndr_hdid_t *id)
185 185 {
186 186 ndr_handle_t *hd;
187 187
188 188 if ((hd = ndr_hdlookup(mxa, id)) != NULL) {
189 189 free(hd->nh_data);
190 190 hd->nh_data = NULL;
191 191 ndr_hdfree(mxa, id);
192 192 }
193 193 }
194 194
195 195 /*
196 196 * Handle lookup wrapper to validate the local context.
197 197 */
198 198 static ndr_handle_t *
199 199 samr_hdlookup(ndr_xa_t *mxa, ndr_hdid_t *id, samr_key_t key)
200 200 {
201 201 ndr_handle_t *hd;
202 202 samr_keydata_t *data;
203 203
204 204 if ((hd = ndr_hdlookup(mxa, id)) == NULL)
205 205 return (NULL);
206 206
207 207 if ((data = (samr_keydata_t *)hd->nh_data) == NULL)
208 208 return (NULL);
209 209
210 210 if (data->kd_key != key)
211 211 return (NULL);
212 212
213 213 return (hd);
214 214 }
215 215
216 216 /*
217 217 * samr_s_Connect
218 218 *
219 219 * This is a request to connect to the local SAM database. We don't
220 220 * support any form of update request and our database doesn't
221 221 * contain any private information, so there is little point in
222 222 * doing any access access checking here.
223 223 *
224 224 * Return a handle for use with subsequent SAM requests.
225 225 */
226 226 static int
227 227 samr_s_Connect(void *arg, ndr_xa_t *mxa)
228 228 {
229 229 struct samr_Connect *param = arg;
230 230 ndr_hdid_t *id;
231 231
232 232 id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
233 233 if (id) {
234 234 bcopy(id, ¶m->handle, sizeof (samr_handle_t));
235 235 param->status = 0;
236 236 } else {
237 237 bzero(¶m->handle, sizeof (samr_handle_t));
238 238 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
239 239 }
240 240
241 241 return (NDR_DRC_OK);
242 242 }
243 243
244 244 /*
245 245 * samr_s_CloseHandle
246 246 *
247 247 * Close the SAM interface specified by the handle.
248 248 * Free the handle and zero out the result handle for the client.
249 249 */
250 250 static int
251 251 samr_s_CloseHandle(void *arg, ndr_xa_t *mxa)
252 252 {
253 253 struct samr_CloseHandle *param = arg;
254 254 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
255 255
256 256 samr_hdfree(mxa, id);
257 257
258 258 bzero(¶m->result_handle, sizeof (samr_handle_t));
259 259 param->status = 0;
260 260 return (NDR_DRC_OK);
261 261 }
262 262
263 263 /*
264 264 * samr_s_LookupDomain
265 265 *
266 266 * This is a request to map a domain name to a domain SID. We can map
267 267 * the primary domain name, our local domain name (hostname) and the
268 268 * builtin domain names to the appropriate SID. Anything else will be
269 269 * rejected.
270 270 */
271 271 static int
272 272 samr_s_LookupDomain(void *arg, ndr_xa_t *mxa)
273 273 {
274 274 struct samr_LookupDomain *param = arg;
275 275 char *domain_name;
276 276 smb_domain_t di;
277 277
278 278 if ((domain_name = (char *)param->domain_name.str) == NULL) {
279 279 bzero(param, sizeof (struct samr_LookupDomain));
280 280 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
281 281 return (NDR_DRC_OK);
282 282 }
283 283
284 284 if (!smb_domain_lookup_name(domain_name, &di)) {
285 285 bzero(param, sizeof (struct samr_LookupDomain));
286 286 param->status = NT_SC_ERROR(NT_STATUS_NO_SUCH_DOMAIN);
287 287 return (NDR_DRC_OK);
288 288 }
289 289
290 290 param->sid = (struct samr_sid *)NDR_SIDDUP(mxa, di.di_binsid);
291 291 if (param->sid == NULL) {
292 292 bzero(param, sizeof (struct samr_LookupDomain));
293 293 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
294 294 return (NDR_DRC_OK);
295 295 }
296 296
297 297 param->status = NT_STATUS_SUCCESS;
298 298 return (NDR_DRC_OK);
299 299 }
300 300
301 301 /*
302 302 * samr_s_EnumLocalDomains
303 303 *
304 304 * This is a request for the local domains supported by this server.
305 305 * All we do here is validate the handle and set the status. The real
306 306 * work is done in samr_s_enum_local_domains.
307 307 */
308 308 static int
309 309 samr_s_EnumLocalDomains(void *arg, ndr_xa_t *mxa)
310 310 {
311 311 struct samr_EnumLocalDomain *param = arg;
312 312 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
313 313 DWORD status;
314 314
315 315 if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL)
316 316 status = NT_STATUS_ACCESS_DENIED;
317 317 else
318 318 status = samr_s_enum_local_domains(param, mxa);
319 319
320 320 if (status == NT_STATUS_SUCCESS) {
321 321 param->enum_context = param->info->entries_read;
322 322 param->total_entries = param->info->entries_read;
323 323 param->status = NT_STATUS_SUCCESS;
324 324 } else {
325 325 bzero(param, sizeof (struct samr_EnumLocalDomain));
326 326 param->status = NT_SC_ERROR(status);
327 327 }
328 328
329 329 return (NDR_DRC_OK);
330 330 }
331 331
332 332
333 333 /*
334 334 * samr_s_enum_local_domains
335 335 *
336 336 * This function should only be called via samr_s_EnumLocalDomains to
337 337 * ensure that the appropriate validation is performed. We will answer
338 338 * queries about two domains: the local domain, synonymous with the
339 339 * local hostname, and the BUILTIN domain. So we return these two
340 340 * strings.
341 341 *
342 342 * Returns NT status values.
343 343 */
344 344 static DWORD
345 345 samr_s_enum_local_domains(struct samr_EnumLocalDomain *param,
346 346 ndr_xa_t *mxa)
347 347 {
348 348 struct samr_LocalDomainInfo *info;
349 349 struct samr_LocalDomainEntry *entry;
350 350 char *hostname;
351 351
352 352 hostname = NDR_MALLOC(mxa, NETBIOS_NAME_SZ);
353 353 if (hostname == NULL)
354 354 return (NT_STATUS_NO_MEMORY);
355 355
356 356 if (smb_getnetbiosname(hostname, NETBIOS_NAME_SZ) != 0)
357 357 return (NT_STATUS_NO_MEMORY);
358 358
359 359 entry = NDR_NEWN(mxa, struct samr_LocalDomainEntry, 2);
360 360 if (entry == NULL)
361 361 return (NT_STATUS_NO_MEMORY);
362 362
363 363 bzero(entry, (sizeof (struct samr_LocalDomainEntry) * 2));
364 364 (void) NDR_MSTRING(mxa, hostname, (ndr_mstring_t *)&entry[0].name);
365 365 (void) NDR_MSTRING(mxa, "Builtin", (ndr_mstring_t *)&entry[1].name);
366 366
367 367 info = NDR_NEW(mxa, struct samr_LocalDomainInfo);
368 368 if (info == NULL)
369 369 return (NT_STATUS_NO_MEMORY);
370 370
371 371 info->entries_read = 2;
372 372 info->entry = entry;
373 373 param->info = info;
374 374 return (NT_STATUS_SUCCESS);
375 375 }
376 376
377 377 /*
378 378 * samr_s_OpenDomain
379 379 *
380 380 * This is a request to open a domain within the local SAM database.
381 381 * The caller must supply a valid connect handle.
382 382 * We return a handle to be used to access objects within this domain.
383 383 */
384 384 static int
385 385 samr_s_OpenDomain(void *arg, ndr_xa_t *mxa)
386 386 {
387 387 struct samr_OpenDomain *param = arg;
388 388 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
389 389 smb_domain_t domain;
390 390
391 391 if (samr_hdlookup(mxa, id, SAMR_KEY_CONNECT) == NULL) {
392 392 bzero(¶m->domain_handle, sizeof (samr_handle_t));
393 393 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
394 394 return (NDR_DRC_OK);
395 395 }
396 396
397 397 if (!smb_domain_lookup_sid((smb_sid_t *)param->sid, &domain)) {
398 398 bzero(¶m->domain_handle, sizeof (samr_handle_t));
399 399 param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
400 400 return (NDR_DRC_OK);
401 401 }
402 402
403 403 if ((domain.di_type != SMB_DOMAIN_BUILTIN) &&
404 404 (domain.di_type != SMB_DOMAIN_LOCAL)) {
405 405 bzero(¶m->domain_handle, sizeof (samr_handle_t));
406 406 param->status = NT_SC_ERROR(NT_STATUS_CANT_ACCESS_DOMAIN_INFO);
407 407 return (NDR_DRC_OK);
408 408 }
409 409
410 410 id = samr_hdalloc(mxa, SAMR_KEY_DOMAIN, domain.di_type, 0);
411 411 if (id) {
412 412 bcopy(id, ¶m->domain_handle, sizeof (samr_handle_t));
413 413 param->status = 0;
414 414 } else {
415 415 bzero(¶m->domain_handle, sizeof (samr_handle_t));
416 416 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
417 417 }
418 418
419 419 return (NDR_DRC_OK);
420 420 }
421 421
422 422 /*
423 423 * samr_s_QueryDomainInfo
424 424 *
425 425 * The caller should pass a domain handle.
426 426 *
427 427 * Windows 95 Server Manager sends requests for levels 6 and 7 when
428 428 * the services menu item is selected. Level 2 is basically for getting
429 429 * number of users, groups, and aliases in a domain.
430 430 * We have no information on what the various information levels mean.
431 431 */
432 432 static int
433 433 samr_s_QueryDomainInfo(void *arg, ndr_xa_t *mxa)
434 434 {
435 435 struct samr_QueryDomainInfo *param = arg;
436 436 struct samr_QueryDomainInfoRes *info;
437 437 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
438 438 ndr_handle_t *hd;
439 439 samr_keydata_t *data;
440 440 char *domain;
441 441 char hostname[NETBIOS_NAME_SZ];
442 442 int alias_cnt, user_cnt;
443 443 int rc = 0;
444 444
445 445 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
446 446 bzero(param, sizeof (struct samr_QueryDomainInfo));
447 447 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
448 448 return (NDR_DRC_OK);
449 449 }
450 450
451 451 info = NDR_NEW(mxa, struct samr_QueryDomainInfoRes);
452 452 if (info == NULL) {
453 453 bzero(param, sizeof (struct samr_QueryDomainInfo));
454 454 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
455 455 return (NDR_DRC_OK);
456 456 }
457 457 info->switch_value = param->info_level;
458 458 param->info = info;
459 459
460 460 data = (samr_keydata_t *)hd->nh_data;
461 461
462 462 switch (data->kd_type) {
463 463 case SMB_DOMAIN_BUILTIN:
464 464 domain = "BUILTIN";
465 465 user_cnt = 0;
466 466 alias_cnt = smb_sam_grp_cnt(data->kd_type);
467 467 break;
468 468
469 469 case SMB_DOMAIN_LOCAL:
470 470 rc = smb_getnetbiosname(hostname, sizeof (hostname));
471 471 if (rc == 0) {
472 472 domain = hostname;
473 473 user_cnt = smb_sam_usr_cnt();
474 474 alias_cnt = smb_sam_grp_cnt(data->kd_type);
475 475 }
476 476 break;
477 477
478 478 default:
479 479 bzero(param, sizeof (struct samr_QueryDomainInfo));
480 480 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
481 481 return (NDR_DRC_OK);
482 482 }
483 483
484 484 if (rc != 0) {
485 485 bzero(param, sizeof (struct samr_QueryDomainInfo));
486 486 param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
487 487 return (NDR_DRC_OK);
488 488 }
489 489
490 490 switch (param->info_level) {
491 491 case SAMR_QUERY_DOMAIN_INFO_6:
492 492 info->ru.info6.unknown1 = 0x00000000;
493 493 info->ru.info6.unknown2 = 0x00147FB0;
494 494 info->ru.info6.unknown3 = 0x00000000;
495 495 info->ru.info6.unknown4 = 0x00000000;
496 496 info->ru.info6.unknown5 = 0x00000000;
497 497 param->status = NT_STATUS_SUCCESS;
498 498 break;
499 499
500 500 case SAMR_QUERY_DOMAIN_INFO_7:
501 501 info->ru.info7.unknown1 = 0x00000003;
502 502 param->status = NT_STATUS_SUCCESS;
503 503 break;
504 504
505 505 case SAMR_QUERY_DOMAIN_INFO_2:
506 506 info->ru.info2.unknown1 = 0x00000000;
507 507 info->ru.info2.unknown2 = 0x80000000;
508 508
509 509 (void) NDR_MSTRING(mxa, "",
510 510 (ndr_mstring_t *)&(info->ru.info2.s1));
511 511 (void) NDR_MSTRING(mxa, domain,
512 512 (ndr_mstring_t *)&(info->ru.info2.domain));
513 513 (void) NDR_MSTRING(mxa, "",
514 514 (ndr_mstring_t *)&(info->ru.info2.s2));
515 515
516 516 info->ru.info2.sequence_num = 0x0000002B;
517 517 info->ru.info2.unknown3 = 0x00000000;
518 518 info->ru.info2.unknown4 = 0x00000001;
519 519 info->ru.info2.unknown5 = 0x00000003;
520 520 info->ru.info2.unknown6 = 0x00000001;
521 521 info->ru.info2.num_users = user_cnt;
522 522 info->ru.info2.num_groups = 0;
523 523 info->ru.info2.num_aliases = alias_cnt;
524 524 param->status = NT_STATUS_SUCCESS;
525 525 break;
526 526
527 527 default:
528 528 bzero(param, sizeof (struct samr_QueryDomainInfo));
529 529 return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
530 530 };
531 531
532 532 return (NDR_DRC_OK);
533 533 }
534 534
535 535 /*
536 536 * QueryInfoDomain2: Identical to QueryDomainInfo.
537 537 */
538 538 static int
539 539 samr_s_QueryInfoDomain2(void *arg, ndr_xa_t *mxa)
540 540 {
541 541 return (samr_s_QueryDomainInfo(arg, mxa));
542 542 }
543 543
544 544 /*
545 545 * Looks up the given name in the specified domain which could
546 546 * be either the built-in or local domain.
547 547 *
548 548 * CAVEAT: this function should be able to handle a list of
549 549 * names but currently it can only handle one name at a time.
550 550 */
551 551 static int
552 552 samr_s_LookupNames(void *arg, ndr_xa_t *mxa)
553 553 {
554 554 struct samr_LookupNames *param = arg;
555 555 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
556 556 ndr_handle_t *hd;
557 557 samr_keydata_t *data;
558 558 smb_account_t account;
559 559 smb_wka_t *wka;
560 560 uint32_t status = NT_STATUS_SUCCESS;
561 561
562 562 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL)
563 563 status = NT_STATUS_INVALID_HANDLE;
564 564
565 565 if (param->n_entry != 1)
566 566 status = NT_STATUS_ACCESS_DENIED;
567 567
568 568 if (param->name.str == NULL) {
569 569 /*
570 570 * Windows NT returns NT_STATUS_NONE_MAPPED.
571 571 * Windows 2000 returns STATUS_INVALID_ACCOUNT_NAME.
572 572 */
573 573 status = NT_STATUS_NONE_MAPPED;
574 574 }
575 575
576 576 if (status != NT_STATUS_SUCCESS) {
577 577 bzero(param, sizeof (struct samr_LookupNames));
578 578 param->status = NT_SC_ERROR(status);
579 579 return (NDR_DRC_OK);
580 580 }
581 581
582 582 param->rids.rid = NDR_NEW(mxa, DWORD);
583 583 param->rid_types.rid_type = NDR_NEW(mxa, DWORD);
584 584
585 585 data = (samr_keydata_t *)hd->nh_data;
586 586
587 587 switch (data->kd_type) {
588 588 case SMB_DOMAIN_BUILTIN:
589 589 wka = smb_wka_lookup_builtin((char *)param->name.str);
590 590 if (wka != NULL) {
591 591 param->rids.n_entry = 1;
592 592 (void) smb_sid_getrid(wka->wka_binsid,
593 593 ¶m->rids.rid[0]);
594 594 param->rid_types.n_entry = 1;
595 595 param->rid_types.rid_type[0] = wka->wka_type;
596 596 param->status = NT_STATUS_SUCCESS;
597 597 return (NDR_DRC_OK);
598 598 }
599 599 break;
600 600
601 601 case SMB_DOMAIN_LOCAL:
602 602 status = smb_sam_lookup_name(NULL, (char *)param->name.str,
603 603 SidTypeUnknown, &account);
604 604 if (status == NT_STATUS_SUCCESS) {
605 605 param->rids.n_entry = 1;
606 606 param->rids.rid[0] = account.a_rid;
607 607 param->rid_types.n_entry = 1;
608 608 param->rid_types.rid_type[0] = account.a_type;
609 609 param->status = NT_STATUS_SUCCESS;
610 610 smb_account_free(&account);
611 611 return (NDR_DRC_OK);
612 612 }
613 613 break;
614 614
615 615 default:
616 616 bzero(param, sizeof (struct samr_LookupNames));
617 617 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
618 618 return (NDR_DRC_OK);
619 619 }
620 620
621 621 param->rids.n_entry = 0;
622 622 param->rid_types.n_entry = 0;
623 623 param->status = NT_SC_ERROR(NT_STATUS_NONE_MAPPED);
624 624 return (NDR_DRC_OK);
625 625 }
626 626
627 627 /*
628 628 * samr_s_OpenUser
629 629 *
630 630 * This is a request to open a user within a specified domain in the
631 631 * local SAM database. The caller must supply a valid domain handle,
632 632 * obtained via a successful domain open request. The user is
633 633 * specified by the rid in the request.
634 634 */
635 635 static int
636 636 samr_s_OpenUser(void *arg, ndr_xa_t *mxa)
637 637 {
638 638 struct samr_OpenUser *param = arg;
639 639 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
640 640 ndr_handle_t *hd;
641 641 samr_keydata_t *data;
642 642
643 643 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
644 644 bzero(¶m->user_handle, sizeof (samr_handle_t));
645 645 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
646 646 return (NDR_DRC_OK);
647 647 }
648 648
649 649 data = (samr_keydata_t *)hd->nh_data;
650 650
651 651 id = samr_hdalloc(mxa, SAMR_KEY_USER, data->kd_type, param->rid);
652 652 if (id == NULL) {
653 653 bzero(¶m->user_handle, sizeof (samr_handle_t));
654 654 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
655 655 } else {
656 656 bcopy(id, ¶m->user_handle, sizeof (samr_handle_t));
657 657 param->status = NT_STATUS_SUCCESS;
658 658 }
659 659
660 660 return (NDR_DRC_OK);
661 661 }
662 662
663 663 /*
664 664 * samr_s_DeleteUser
665 665 *
666 666 * Request to delete a user within a specified domain in the local
667 667 * SAM database. The caller should supply a valid user handle.
668 668 */
669 669 /*ARGSUSED*/
670 670 static int
671 671 samr_s_DeleteUser(void *arg, ndr_xa_t *mxa)
672 672 {
673 673 struct samr_DeleteUser *param = arg;
674 674
675 675 bzero(param, sizeof (struct samr_DeleteUser));
676 676 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
677 677 return (NDR_DRC_OK);
678 678 }
679 679
680 680 /*
681 681 * samr_s_QueryUserInfo
682 682 *
683 683 * Returns:
684 684 * NT_STATUS_SUCCESS
685 685 * NT_STATUS_ACCESS_DENIED
686 686 * NT_STATUS_INVALID_INFO_CLASS
687 687 */
688 688 /*ARGSUSED*/
689 689 static int
690 690 samr_s_QueryUserInfo(void *arg, ndr_xa_t *mxa)
691 691 {
692 692 static uint16_t owf_buf[8];
693 693 static uint8_t hour_buf[SAMR_SET_USER_HOURS_SZ];
694 694 struct samr_QueryUserInfo *param = arg;
695 695 struct samr_QueryUserInfo21 *all_info;
696 696 ndr_hdid_t *id;
697 697 ndr_handle_t *hd;
698 698 samr_keydata_t *data;
699 699 smb_domain_t di;
700 700 smb_account_t account;
701 701 smb_sid_t *sid;
702 702 uint32_t status;
703 703
704 704 id = (ndr_hdid_t *)¶m->user_handle;
705 705 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
706 706 status = NT_STATUS_INVALID_HANDLE;
707 707 goto QueryUserInfoError;
708 708 }
709 709
710 710 data = (samr_keydata_t *)hd->nh_data;
711 711
712 712 if (param->switch_value != SAMR_QUERY_USER_ALL_INFO) {
713 713 status = NT_STATUS_ACCESS_DENIED;
714 714 goto QueryUserInfoError;
715 715 }
716 716
717 717 if (!smb_domain_lookup_type(SMB_DOMAIN_LOCAL, &di)) {
718 718 status = NT_STATUS_ACCESS_DENIED;
719 719 goto QueryUserInfoError;
720 720 }
721 721
722 722 if ((sid = smb_sid_splice(di.di_binsid, data->kd_rid)) == NULL) {
723 723 status = NT_STATUS_ACCESS_DENIED;
724 724 goto QueryUserInfoError;
725 725 }
726 726
727 727 if (smb_sam_lookup_sid(sid, &account) != NT_STATUS_SUCCESS) {
728 728 status = NT_STATUS_ACCESS_DENIED;
729 729 goto QueryUserInfoError;
730 730 }
731 731
732 732 all_info = ¶m->ru.info21;
733 733 bzero(all_info, sizeof (struct samr_QueryUserInfo21));
734 734
735 735 all_info->WhichFields = SAMR_USER_ALL_USERNAME | SAMR_USER_ALL_USERID;
736 736
737 737 (void) NDR_MSTRING(mxa, account.a_name,
738 738 (ndr_mstring_t *)&all_info->UserName);
739 739 all_info->UserId = data->kd_rid;
740 740
741 741 all_info->LmOwfPassword.length = 16;
742 742 all_info->LmOwfPassword.maxlen = 16;
743 743 all_info->LmOwfPassword.buf = owf_buf;
744 744 all_info->NtOwfPassword.length = 16;
745 745 all_info->NtOwfPassword.maxlen = 16;
746 746 all_info->NtOwfPassword.buf = owf_buf;
747 747 all_info->LogonHours.units_per_week = SAMR_HOURS_PER_WEEK;
748 748 all_info->LogonHours.hours = hour_buf;
749 749
750 750 param->address = 1;
751 751 param->switch_index = SAMR_QUERY_USER_ALL_INFO;
752 752 param->status = NT_STATUS_SUCCESS;
753 753 smb_account_free(&account);
754 754 smb_sid_free(sid);
755 755 return (NDR_DRC_OK);
756 756
757 757 QueryUserInfoError:
758 758 smb_sid_free(sid);
759 759 bzero(param, sizeof (struct samr_QueryUserInfo));
760 760 param->status = NT_SC_ERROR(status);
761 761 return (NDR_DRC_OK);
762 762 }
763 763
764 764 /*
765 765 * samr_s_QueryUserGroups
766 766 *
767 767 * Request the list of groups of which a user is a member.
768 768 * The user is identified from the handle, which contains an
769 769 * rid in the discriminator field. Note that this is a local user.
770 770 */
771 771 static int
772 772 samr_s_QueryUserGroups(void *arg, ndr_xa_t *mxa)
773 773 {
774 774 struct samr_QueryUserGroups *param = arg;
775 775 struct samr_UserGroupInfo *info;
776 776 struct samr_UserGroups *group;
777 777 ndr_hdid_t *id = (ndr_hdid_t *)¶m->user_handle;
778 778 ndr_handle_t *hd;
779 779 samr_keydata_t *data;
780 780 smb_sid_t *user_sid = NULL;
781 781 smb_group_t grp;
782 782 smb_giter_t gi;
783 783 smb_domain_t di;
784 784 uint32_t status;
785 785 int size;
786 786 int ngrp_max;
787 787
788 788 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_USER)) == NULL) {
789 789 status = NT_STATUS_ACCESS_DENIED;
790 790 goto query_error;
791 791 }
792 792
793 793 data = (samr_keydata_t *)hd->nh_data;
794 794 switch (data->kd_type) {
795 795 case SMB_DOMAIN_BUILTIN:
796 796 case SMB_DOMAIN_LOCAL:
797 797 if (!smb_domain_lookup_type(data->kd_type, &di)) {
798 798 status = NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
799 799 goto query_error;
800 800 }
801 801 break;
802 802 default:
803 803 status = NT_STATUS_INVALID_HANDLE;
804 804 goto query_error;
805 805 }
806 806
807 807 user_sid = smb_sid_splice(di.di_binsid, data->kd_rid);
808 808 if (user_sid == NULL) {
809 809 status = NT_STATUS_NO_MEMORY;
810 810 goto query_error;
811 811 }
812 812
813 813 info = NDR_NEW(mxa, struct samr_UserGroupInfo);
814 814 if (info == NULL) {
815 815 status = NT_STATUS_NO_MEMORY;
816 816 goto query_error;
817 817 }
818 818 bzero(info, sizeof (struct samr_UserGroupInfo));
819 819
820 820 size = 32 * 1024;
821 821 info->groups = NDR_MALLOC(mxa, size);
822 822 if (info->groups == NULL) {
823 823 status = NT_STATUS_NO_MEMORY;
824 824 goto query_error;
825 825 }
826 826 ngrp_max = size / sizeof (struct samr_UserGroups);
827 827
828 828 if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
829 829 status = NT_STATUS_INTERNAL_ERROR;
830 830 goto query_error;
831 831 }
832 832
833 833 info->n_entry = 0;
834 834 group = info->groups;
835 835 while ((info->n_entry < ngrp_max) &&
836 836 (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS)) {
837 837 if (smb_lgrp_is_member(&grp, user_sid)) {
838 838 group->rid = grp.sg_rid;
839 839 group->attr = grp.sg_attr;
840 840 group++;
841 841 info->n_entry++;
842 842 }
843 843 smb_lgrp_free(&grp);
844 844 }
845 845 smb_lgrp_iterclose(&gi);
846 846
847 847 free(user_sid);
848 848 param->info = info;
849 849 param->status = NT_STATUS_SUCCESS;
850 850 return (NDR_DRC_OK);
851 851
852 852 query_error:
853 853 free(user_sid);
854 854 bzero(param, sizeof (struct samr_QueryUserGroups));
855 855 param->status = NT_SC_ERROR(status);
856 856 return (NDR_DRC_OK);
857 857 }
858 858
859 859 /*
860 860 * samr_s_OpenGroup
861 861 *
862 862 * This is a request to open a group within the specified domain in the
863 863 * local SAM database. The caller must supply a valid domain handle,
864 864 * obtained via a successful domain open request. The group is
865 865 * specified by the rid in the request. If this is a local RID it
866 866 * should already be encoded with type information.
867 867 *
868 868 * We return a handle to be used to access information about this group.
869 869 */
870 870 static int
871 871 samr_s_OpenGroup(void *arg, ndr_xa_t *mxa)
872 872 {
873 873 struct samr_OpenGroup *param = arg;
874 874 ndr_hdid_t *id = (ndr_hdid_t *)¶m->handle;
875 875 ndr_handle_t *hd;
876 876 samr_keydata_t *data;
877 877
878 878 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
879 879 bzero(¶m->group_handle, sizeof (samr_handle_t));
880 880 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
881 881 return (NDR_DRC_OK);
882 882 }
883 883
884 884 data = (samr_keydata_t *)hd->nh_data;
885 885 id = samr_hdalloc(mxa, SAMR_KEY_GROUP, data->kd_type, param->rid);
886 886
887 887 if (id) {
888 888 bcopy(id, ¶m->group_handle, sizeof (samr_handle_t));
889 889 param->status = 0;
890 890 } else {
891 891 bzero(¶m->group_handle, sizeof (samr_handle_t));
892 892 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
893 893 }
894 894
895 895 return (NDR_DRC_OK);
896 896 }
897 897
898 898 /*
899 899 * samr_s_AddAliasMember
900 900 *
901 901 * Add a member to a local SAM group.
902 902 * The caller must supply a valid group handle.
903 903 * The member is specified by the sid in the request.
904 904 */
905 905 static int
906 906 samr_s_AddAliasMember(void *arg, ndr_xa_t *mxa)
907 907 {
908 908 struct samr_AddAliasMember *param = arg;
909 909 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
910 910 ndr_handle_t *hd;
911 911 samr_keydata_t *data;
912 912 smb_group_t grp;
913 913 uint32_t rc;
914 914 uint32_t status = NT_STATUS_SUCCESS;
915 915
916 916 if (param->sid == NULL) {
917 917 bzero(param, sizeof (struct samr_AddAliasMember));
918 918 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
919 919 return (NDR_DRC_OK);
920 920 }
921 921
922 922 if (!ndr_is_admin(mxa)) {
923 923 bzero(param, sizeof (struct samr_AddAliasMember));
924 924 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
925 925 return (NDR_DRC_OK);
926 926 }
927 927
928 928
929 929 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
930 930 bzero(param, sizeof (struct samr_AddAliasMember));
931 931 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
932 932 return (NDR_DRC_OK);
933 933 }
934 934
935 935 data = (samr_keydata_t *)hd->nh_data;
936 936 rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
937 937 if (rc != SMB_LGRP_SUCCESS) {
938 938 bzero(param, sizeof (struct samr_AddAliasMember));
939 939 status = smb_lgrp_err_to_ntstatus(rc);
940 940 param->status = NT_SC_ERROR(status);
941 941 return (NDR_DRC_OK);
942 942 }
943 943
944 944 rc = smb_lgrp_add_member(grp.sg_name,
945 945 (smb_sid_t *)param->sid, SidTypeUser);
946 946 if (rc != SMB_LGRP_SUCCESS) {
947 947 bzero(param, sizeof (struct samr_AddAliasMember));
948 948 status = smb_lgrp_err_to_ntstatus(rc);
949 949 param->status = NT_SC_ERROR(status);
950 950 }
951 951 smb_lgrp_free(&grp);
952 952
953 953 param->status = status;
954 954 return (NDR_DRC_OK);
955 955 }
956 956
957 957 /*
958 958 * samr_s_DeleteAliasMember
959 959 *
960 960 * Delete a member from a local SAM group.
961 961 * The caller must supply a valid group handle.
962 962 * The member is specified by the sid in the request.
963 963 */
964 964 static int
965 965 samr_s_DeleteAliasMember(void *arg, ndr_xa_t *mxa)
966 966 {
967 967 struct samr_DeleteAliasMember *param = arg;
968 968 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
969 969 ndr_handle_t *hd;
970 970 samr_keydata_t *data;
971 971 smb_group_t grp;
972 972 uint32_t rc;
973 973 uint32_t status = NT_STATUS_SUCCESS;
974 974
975 975 if (param->sid == NULL) {
976 976 bzero(param, sizeof (struct samr_DeleteAliasMember));
977 977 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
978 978 return (NDR_DRC_OK);
979 979 }
980 980
981 981 if (!ndr_is_admin(mxa)) {
982 982 bzero(param, sizeof (struct samr_DeleteAliasMember));
983 983 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
984 984 return (NDR_DRC_OK);
985 985 }
986 986
987 987 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
988 988 bzero(param, sizeof (struct samr_DeleteAliasMember));
989 989 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
990 990 return (NDR_DRC_OK);
991 991 }
992 992
993 993 data = (samr_keydata_t *)hd->nh_data;
994 994 rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
995 995 if (rc != SMB_LGRP_SUCCESS) {
996 996 bzero(param, sizeof (struct samr_DeleteAliasMember));
997 997 status = smb_lgrp_err_to_ntstatus(rc);
998 998 param->status = NT_SC_ERROR(status);
999 999 return (NDR_DRC_OK);
1000 1000 }
1001 1001
1002 1002 rc = smb_lgrp_del_member(grp.sg_name,
1003 1003 (smb_sid_t *)param->sid, SidTypeUser);
1004 1004 if (rc != SMB_LGRP_SUCCESS) {
1005 1005 bzero(param, sizeof (struct samr_DeleteAliasMember));
1006 1006 status = smb_lgrp_err_to_ntstatus(rc);
1007 1007 param->status = NT_SC_ERROR(status);
1008 1008 }
1009 1009 smb_lgrp_free(&grp);
1010 1010
1011 1011 param->status = status;
1012 1012 return (NDR_DRC_OK);
1013 1013 }
1014 1014
1015 1015 /*
1016 1016 * samr_s_ListAliasMembers
1017 1017 *
1018 1018 * List members from a local SAM group.
1019 1019 * The caller must supply a valid group handle.
1020 1020 * A list of user SIDs in the specified group is returned to the caller.
1021 1021 */
1022 1022 static int
1023 1023 samr_s_ListAliasMembers(void *arg, ndr_xa_t *mxa)
1024 1024 {
1025 1025 struct samr_ListAliasMembers *param = arg;
1026 1026 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1027 1027 ndr_handle_t *hd;
1028 1028 samr_keydata_t *data;
1029 1029 smb_group_t grp;
1030 1030 smb_gsid_t *members;
1031 1031 struct samr_SidInfo info;
1032 1032 struct samr_SidList *user;
1033 1033 uint32_t num = 0, size;
1034 1034 int i;
1035 1035 uint32_t rc;
1036 1036 uint32_t status = NT_STATUS_SUCCESS;
1037 1037
1038 1038 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1039 1039 bzero(param, sizeof (struct samr_ListAliasMembers));
1040 1040 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1041 1041 return (NDR_DRC_OK);
1042 1042 }
1043 1043
1044 1044 bzero(&info, sizeof (struct samr_SidInfo));
1045 1045 data = (samr_keydata_t *)hd->nh_data;
1046 1046 rc = smb_lgrp_getbyrid(data->kd_rid, data->kd_type, &grp);
1047 1047 if (rc != SMB_LGRP_SUCCESS) {
1048 1048 bzero(param, sizeof (struct samr_ListAliasMembers));
1049 1049 status = smb_lgrp_err_to_ntstatus(rc);
1050 1050 param->status = NT_SC_ERROR(status);
1051 1051 return (NDR_DRC_OK);
1052 1052 }
1053 1053
1054 1054 num = grp.sg_nmembers;
1055 1055 members = grp.sg_members;
1056 1056 size = num * sizeof (struct samr_SidList);
1057 1057 info.sidlist = NDR_MALLOC(mxa, size);
1058 1058 if (info.sidlist == NULL) {
1059 1059 bzero(param, sizeof (struct samr_ListAliasMembers));
1060 1060 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1061 1061 smb_lgrp_free(&grp);
1062 1062 return (NDR_DRC_OK);
1063 1063 }
1064 1064
1065 1065 info.n_entry = num;
1066 1066 user = info.sidlist;
1067 1067 for (i = 0; i < num; i++) {
1068 1068 user->sid = (struct samr_sid *)NDR_SIDDUP(mxa,
1069 1069 members[i].gs_sid);
1070 1070 if (user->sid == NULL) {
1071 1071 bzero(param, sizeof (struct samr_ListAliasMembers));
1072 1072 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1073 1073 smb_lgrp_free(&grp);
1074 1074 return (NDR_DRC_OK);
1075 1075 }
1076 1076 user++;
1077 1077 }
1078 1078 smb_lgrp_free(&grp);
1079 1079
1080 1080 param->info = info;
1081 1081 param->status = status;
1082 1082 return (NDR_DRC_OK);
1083 1083 }
1084 1084
1085 1085 /*
1086 1086 * samr_s_Connect2
1087 1087 *
1088 1088 * This is a request to connect to the local SAM database.
1089 1089 * We don't support any form of update request and our database doesn't
1090 1090 * contain any private information, so there is little point in doing
1091 1091 * any access access checking here.
1092 1092 *
1093 1093 * Return a handle for use with subsequent SAM requests.
1094 1094 */
1095 1095 static int
1096 1096 samr_s_Connect2(void *arg, ndr_xa_t *mxa)
1097 1097 {
1098 1098 struct samr_Connect2 *param = arg;
1099 1099 ndr_hdid_t *id;
1100 1100
1101 1101 id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1102 1102 if (id) {
1103 1103 bcopy(id, ¶m->handle, sizeof (samr_handle_t));
1104 1104 param->status = 0;
1105 1105 } else {
1106 1106 bzero(¶m->handle, sizeof (samr_handle_t));
1107 1107 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1108 1108 }
1109 1109
1110 1110 return (NDR_DRC_OK);
1111 1111 }
1112 1112
1113 1113 /*
1114 1114 * samr_s_GetUserPwInfo
1115 1115 *
1116 1116 * Request for a user's password policy information.
1117 1117 */
1118 1118 /*ARGSUSED*/
1119 1119 static int
1120 1120 samr_s_GetUserPwInfo(void *arg, ndr_xa_t *mxa)
1121 1121 {
1122 1122 static samr_password_info_t pwinfo;
1123 1123 struct samr_GetUserPwInfo *param = arg;
1124 1124
1125 1125 param->pwinfo = &pwinfo;
1126 1126 param->status = NT_STATUS_SUCCESS;
1127 1127 return (NDR_DRC_OK);
1128 1128 }
1129 1129
1130 1130 /*
1131 1131 * samr_s_CreateUser
1132 1132 */
1133 1133 /*ARGSUSED*/
1134 1134 static int
1135 1135 samr_s_CreateUser(void *arg, ndr_xa_t *mxa)
1136 1136 {
1137 1137 struct samr_CreateUser *param = arg;
1138 1138
1139 1139 bzero(¶m->user_handle, sizeof (samr_handle_t));
1140 1140 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1141 1141 return (NDR_DRC_OK);
1142 1142 }
1143 1143
1144 1144 /*
1145 1145 * samr_s_ChangePasswordUser2
1146 1146 */
1147 1147 /*ARGSUSED*/
1148 1148 static int
1149 1149 samr_s_ChangePasswordUser2(void *arg, ndr_xa_t *mxa)
1150 1150 {
1151 1151 struct samr_ChangePasswordUser2 *param = arg;
1152 1152
1153 1153 bzero(param, sizeof (*param));
1154 1154 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1155 1155 return (NDR_DRC_OK);
1156 1156 }
1157 1157
1158 1158 /*
1159 1159 * samr_s_GetDomainPwInfo
1160 1160 *
1161 1161 * Request for the domain password policy information.
1162 1162 */
1163 1163 /*ARGSUSED*/
1164 1164 static int
1165 1165 samr_s_GetDomainPwInfo(void *arg, ndr_xa_t *mxa)
1166 1166 {
1167 1167 static samr_password_info_t pwinfo;
1168 1168 struct samr_GetDomainPwInfo *param = arg;
1169 1169
1170 1170 param->pwinfo = &pwinfo;
1171 1171 param->status = NT_STATUS_SUCCESS;
1172 1172 return (NDR_DRC_OK);
1173 1173 }
1174 1174
1175 1175 /*
1176 1176 * samr_s_SetUserInfo
1177 1177 */
1178 1178 /*ARGSUSED*/
1179 1179 static int
1180 1180 samr_s_SetUserInfo(void *arg, ndr_xa_t *mxa)
1181 1181 {
1182 1182 struct samr_SetUserInfo *param = arg;
1183 1183
1184 1184 bzero(param, sizeof (struct samr_SetUserInfo));
1185 1185 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1186 1186 return (NDR_DRC_OK);
1187 1187 }
1188 1188
1189 1189 /*
1190 1190 * samr_s_QueryDispInfo
1191 1191 *
1192 1192 * This function currently return local users' information only.
1193 1193 * This RPC is called repeatedly until all the users info are
1194 1194 * retrieved.
1195 1195 *
1196 1196 * The total count and the returned count are returned as total size
1197 1197 * and returned size. The client doesn't seem to care.
1198 1198 */
1199 1199 static int
1200 1200 samr_s_QueryDispInfo(void *arg, ndr_xa_t *mxa)
1201 1201 {
1202 1202 struct samr_QueryDispInfo *param = arg;
1203 1203 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1204 1204 ndr_handle_t *hd;
1205 1205 samr_keydata_t *data;
1206 1206 DWORD status = NT_STATUS_SUCCESS;
1207 1207 struct user_acct_info *user;
1208 1208 smb_pwditer_t pwi;
1209 1209 smb_luser_t *uinfo;
1210 1210 int num_users;
1211 1211 int start_idx;
1212 1212 int max_retcnt, retcnt;
1213 1213 int skip;
1214 1214
1215 1215 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1216 1216 status = NT_STATUS_INVALID_HANDLE;
1217 1217 goto error;
1218 1218 }
1219 1219
1220 1220 if (!SAMR_VALID_DISPLEVEL(param->level)) {
1221 1221 status = NT_STATUS_INVALID_INFO_CLASS;
1222 1222 goto error;
1223 1223 }
1224 1224
1225 1225 if (!SAMR_SUPPORTED_DISPLEVEL(param->level)) {
1226 1226 status = NT_STATUS_NOT_IMPLEMENTED;
1227 1227 goto error;
1228 1228 }
1229 1229
1230 1230 data = (samr_keydata_t *)hd->nh_data;
1231 1231
1232 1232 switch (data->kd_type) {
1233 1233 case SMB_DOMAIN_BUILTIN:
1234 1234 goto no_info;
1235 1235
1236 1236 case SMB_DOMAIN_LOCAL:
1237 1237 num_users = smb_sam_usr_cnt();
1238 1238 start_idx = param->start_idx;
1239 1239 if ((num_users == 0) || (start_idx >= num_users))
1240 1240 goto no_info;
1241 1241
1242 1242 max_retcnt = num_users - start_idx;
1243 1243 if (max_retcnt > param->max_entries)
1244 1244 max_retcnt = param->max_entries;
1245 1245 param->users.acct = NDR_MALLOC(mxa,
1246 1246 max_retcnt * sizeof (struct user_acct_info));
1247 1247 user = param->users.acct;
1248 1248 if (user == NULL) {
1249 1249 status = NT_STATUS_NO_MEMORY;
1250 1250 goto error;
1251 1251 }
1252 1252 bzero(user, max_retcnt * sizeof (struct user_acct_info));
1253 1253
1254 1254 if (smb_pwd_iteropen(&pwi) != SMB_PWE_SUCCESS)
1255 1255 goto no_info;
1256 1256
1257 1257 skip = retcnt = 0;
1258 1258 while ((uinfo = smb_pwd_iterate(&pwi)) != NULL) {
1259 1259 if (skip++ < start_idx)
1260 1260 continue;
1261 1261
1262 1262 if (retcnt++ >= max_retcnt)
1263 1263 break;
1264 1264
1265 1265 assert(uinfo->su_name != NULL);
1266 1266
1267 1267 user->index = start_idx + retcnt;
1268 1268 user->rid = uinfo->su_rid;
1269 1269 user->ctrl = ACF_NORMUSER | ACF_PWDNOEXP;
1270 1270 if (uinfo->su_ctrl & SMB_PWF_DISABLE)
1271 1271 user->ctrl |= ACF_DISABLED;
1272 1272 if (NDR_MSTRING(mxa, uinfo->su_name,
1273 1273 (ndr_mstring_t *)&user->name) == -1) {
1274 1274 smb_pwd_iterclose(&pwi);
1275 1275 status = NT_STATUS_NO_MEMORY;
1276 1276 goto error;
1277 1277 }
1278 1278 (void) NDR_MSTRING(mxa, uinfo->su_fullname,
1279 1279 (ndr_mstring_t *)&user->fullname);
1280 1280 (void) NDR_MSTRING(mxa, uinfo->su_desc,
1281 1281 (ndr_mstring_t *)&user->desc);
1282 1282 user++;
1283 1283 }
1284 1284 smb_pwd_iterclose(&pwi);
1285 1285
1286 1286 if (retcnt >= max_retcnt) {
1287 1287 retcnt = max_retcnt;
1288 1288 param->status = status;
1289 1289 } else {
1290 1290 param->status = NT_STATUS_MORE_ENTRIES;
1291 1291 }
1292 1292
1293 1293 param->users.total_size = num_users;
1294 1294 param->users.returned_size = retcnt;
1295 1295 param->users.switch_value = param->level;
1296 1296 param->users.count = retcnt;
1297 1297
1298 1298 break;
1299 1299
1300 1300 default:
1301 1301 status = NT_STATUS_INVALID_HANDLE;
1302 1302 goto error;
1303 1303 }
1304 1304
1305 1305 return (NDR_DRC_OK);
1306 1306
1307 1307 no_info:
1308 1308 param->users.total_size = 0;
1309 1309 param->users.returned_size = 0;
1310 1310 param->users.switch_value = param->level;
1311 1311 param->users.count = 0;
1312 1312 param->users.acct = NULL;
1313 1313 param->status = status;
1314 1314 return (NDR_DRC_OK);
1315 1315
1316 1316 error:
1317 1317 bzero(param, sizeof (struct samr_QueryDispInfo));
1318 1318 param->status = NT_SC_ERROR(status);
1319 1319 return (NDR_DRC_OK);
1320 1320 }
1321 1321
1322 1322 /*
1323 1323 * samr_s_EnumDomainGroups
1324 1324 *
1325 1325 *
1326 1326 * This function is supposed to return local group information.
1327 1327 * As we don't support local users, this function dosen't send
1328 1328 * back any information.
1329 1329 *
1330 1330 * Added template that returns information for a domain group as None.
1331 1331 * All information is hard-coded from packet captures.
1332 1332 */
1333 1333 static int
1334 1334 samr_s_EnumDomainGroups(void *arg, ndr_xa_t *mxa)
1335 1335 {
1336 1336 struct samr_EnumDomainGroups *param = arg;
1337 1337 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1338 1338 DWORD status = NT_STATUS_SUCCESS;
1339 1339
1340 1340 if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) == NULL)
1341 1341 status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1342 1342
1343 1343 param->total_size = 0;
1344 1344 param->returned_size = 0;
1345 1345 param->switch_value = 3;
1346 1346 param->count = 0;
1347 1347 param->groups = 0;
1348 1348 param->status = status;
1349 1349 return (NDR_DRC_OK);
1350 1350
1351 1351 #ifdef SAMR_SUPPORT_GROUPS
1352 1352 if ((desc->discrim != SAMR_LOCAL_DOMAIN) || (param->start_idx != 0)) {
1353 1353 param->total_size = 0;
1354 1354 param->returned_size = 0;
1355 1355 param->switch_value = 3;
1356 1356 param->count = 0;
1357 1357 param->groups = 0;
1358 1358 } else {
1359 1359 param->total_size = 64;
1360 1360 param->returned_size = 64;
1361 1361 param->switch_value = 3;
1362 1362 param->count = 1;
1363 1363 param->groups = (struct group_disp_info *)NDR_MALLOC(
1364 1364 mxa, sizeof (struct group_disp_info));
1365 1365
1366 1366 param->groups->count = 1;
1367 1367 param->groups->acct[0].index = 1;
1368 1368 param->groups->acct[0].rid = 513;
1369 1369 param->groups->acct[0].ctrl = 0x7;
1370 1370 (void) NDR_MSTRING(mxa, "None",
1371 1371 (ndr_mstring_t *)¶m->groups->acct[0].name);
1372 1372
1373 1373 (void) NDR_MSTRING(mxa, "Ordinary users",
1374 1374 (ndr_mstring_t *)¶m->groups->acct[0].desc);
1375 1375 }
1376 1376
1377 1377 param->status = NT_STATUS_SUCCESS;
1378 1378 return (NDR_DRC_OK);
1379 1379 #endif
1380 1380 }
1381 1381
1382 1382 /*
1383 1383 * samr_s_OpenAlias
1384 1384 *
1385 1385 * Lookup for requested alias, if it exists return a handle
1386 1386 * for that alias. The alias domain sid should match with
1387 1387 * the passed domain handle.
1388 1388 */
1389 1389 static int
1390 1390 samr_s_OpenAlias(void *arg, ndr_xa_t *mxa)
1391 1391 {
1392 1392 struct samr_OpenAlias *param = arg;
1393 1393 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1394 1394 ndr_handle_t *hd;
1395 1395 samr_keydata_t *data;
1396 1396 smb_domain_type_t gd_type;
1397 1397 smb_sid_t *sid;
1398 1398 smb_wka_t *wka;
1399 1399 char sidstr[SMB_SID_STRSZ];
1400 1400 uint32_t rid;
1401 1401 uint32_t status;
1402 1402 int rc;
1403 1403
1404 1404 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1405 1405 status = NT_STATUS_INVALID_HANDLE;
1406 1406 goto open_alias_err;
1407 1407 }
1408 1408
1409 1409 if ((param->access_mask & SAMR_ALIAS_ACCESS_ALL_ACCESS) == 0) {
1410 1410 status = NT_STATUS_ACCESS_DENIED;
1411 1411 goto open_alias_err;
1412 1412 }
1413 1413
1414 1414 data = (samr_keydata_t *)hd->nh_data;
1415 1415 gd_type = (smb_domain_type_t)data->kd_type;
1416 1416 rid = param->rid;
1417 1417
1418 1418 switch (gd_type) {
1419 1419 case SMB_DOMAIN_BUILTIN:
1420 1420 (void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1421 1421 NT_BUILTIN_DOMAIN_SIDSTR, rid);
1422 1422 if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1423 1423 status = NT_STATUS_NO_SUCH_ALIAS;
1424 1424 goto open_alias_err;
1425 1425 }
1426 1426
1427 1427 wka = smb_wka_lookup_sid(sid);
1428 1428 smb_sid_free(sid);
1429 1429
1430 1430 if (wka == NULL) {
1431 1431 status = NT_STATUS_NO_SUCH_ALIAS;
1432 1432 goto open_alias_err;
1433 1433 }
1434 1434 break;
1435 1435
1436 1436 case SMB_DOMAIN_LOCAL:
1437 1437 rc = smb_lgrp_getbyrid(rid, gd_type, NULL);
1438 1438 if (rc != SMB_LGRP_SUCCESS) {
1439 1439 status = NT_STATUS_NO_SUCH_ALIAS;
1440 1440 goto open_alias_err;
1441 1441 }
1442 1442 break;
1443 1443
1444 1444 default:
1445 1445 status = NT_STATUS_NO_SUCH_ALIAS;
1446 1446 goto open_alias_err;
1447 1447 }
1448 1448
1449 1449 id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, data->kd_type, param->rid);
1450 1450 if (id) {
1451 1451 bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t));
1452 1452 param->status = NT_STATUS_SUCCESS;
1453 1453 return (NDR_DRC_OK);
1454 1454 }
1455 1455
1456 1456 status = NT_STATUS_NO_MEMORY;
1457 1457
1458 1458 open_alias_err:
1459 1459 bzero(¶m->alias_handle, sizeof (samr_handle_t));
1460 1460 param->status = NT_SC_ERROR(status);
1461 1461 return (NDR_DRC_OK);
1462 1462 }
1463 1463
1464 1464 /*
1465 1465 * samr_s_CreateDomainAlias
1466 1466 *
1467 1467 * Create a local group in the security accounts manager (SAM) database.
1468 1468 * A local SAM group can only be added if a Solaris group already exists
1469 1469 * with the same name. On success, a valid group handle is returned.
1470 1470 *
1471 1471 * The caller must have administrator rights to execute this function.
1472 1472 */
1473 1473 static int
1474 1474 samr_s_CreateDomainAlias(void *arg, ndr_xa_t *mxa)
1475 1475 {
1476 1476 struct samr_CreateDomainAlias *param = arg;
1477 1477 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1478 1478 uint32_t status = NT_STATUS_SUCCESS;
1479 1479 smb_group_t grp;
1480 1480 uint32_t rc;
1481 1481 char *gname;
1482 1482
1483 1483 if (samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN) != NULL) {
1484 1484 bzero(param, sizeof (struct samr_CreateDomainAlias));
1485 1485 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1486 1486 return (NDR_DRC_OK);
1487 1487 }
1488 1488
1489 1489 gname = (char *)param->alias_name.str;
1490 1490 if (gname == NULL) {
1491 1491 bzero(¶m->alias_handle, sizeof (samr_handle_t));
1492 1492 param->status = NT_SC_ERROR(NT_STATUS_INVALID_PARAMETER);
1493 1493 return (NDR_DRC_OK);
1494 1494 }
1495 1495
1496 1496 if ((!ndr_is_admin(mxa)) ||
1497 1497 ((param->access_mask & SAMR_ALIAS_ACCESS_WRITE_ACCOUNT) == 0)) {
1498 1498 bzero(¶m->alias_handle, sizeof (samr_handle_t));
1499 1499 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1500 1500 return (NDR_DRC_OK);
1501 1501 }
1502 1502
1503 1503 rc = smb_lgrp_add(gname, "");
1504 1504 if (rc != SMB_LGRP_SUCCESS) {
1505 1505 bzero(¶m->alias_handle, sizeof (samr_handle_t));
1506 1506 status = smb_lgrp_err_to_ntstatus(rc);
1507 1507 param->status = NT_SC_ERROR(status);
1508 1508 return (NDR_DRC_OK);
1509 1509 }
1510 1510
1511 1511 rc = smb_lgrp_getbyname((char *)gname, &grp);
1512 1512 if (rc != SMB_LGRP_SUCCESS) {
1513 1513 bzero(¶m->alias_handle, sizeof (samr_handle_t));
1514 1514 status = smb_lgrp_err_to_ntstatus(rc);
1515 1515 param->status = NT_SC_ERROR(status);
1516 1516 return (NDR_DRC_OK);
1517 1517 }
1518 1518
1519 1519 id = samr_hdalloc(mxa, SAMR_KEY_ALIAS, SMB_DOMAIN_LOCAL, grp.sg_rid);
1520 1520 smb_lgrp_free(&grp);
1521 1521 if (id) {
1522 1522 bcopy(id, ¶m->alias_handle, sizeof (samr_handle_t));
1523 1523 param->status = status;
1524 1524 } else {
1525 1525 bzero(¶m->alias_handle, sizeof (samr_handle_t));
1526 1526 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1527 1527 }
1528 1528
1529 1529 return (NDR_DRC_OK);
1530 1530 }
1531 1531
1532 1532 /*
1533 1533 * samr_s_SetAliasInfo
1534 1534 *
1535 1535 * Similar to NetLocalGroupSetInfo.
1536 1536 */
1537 1537 static int
1538 1538 samr_s_SetAliasInfo(void *arg, ndr_xa_t *mxa)
1539 1539 {
1540 1540 struct samr_SetAliasInfo *param = arg;
1541 1541 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1542 1542 DWORD status = NT_STATUS_SUCCESS;
1543 1543
1544 1544 if (samr_hdlookup(mxa, id, SAMR_KEY_ALIAS) == NULL)
1545 1545 status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1546 1546
1547 1547 param->status = status;
1548 1548 return (NDR_DRC_OK);
1549 1549 }
1550 1550
1551 1551 /*
1552 1552 * samr_s_QueryAliasInfo
1553 1553 *
1554 1554 * Retrieves information about the specified local group account
1555 1555 * by given handle.
1556 1556 */
1557 1557 static int
1558 1558 samr_s_QueryAliasInfo(void *arg, ndr_xa_t *mxa)
1559 1559 {
1560 1560 struct samr_QueryAliasInfo *param = arg;
1561 1561 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1562 1562 ndr_handle_t *hd;
1563 1563 samr_keydata_t *data;
1564 1564 smb_group_t grp;
1565 1565 smb_domain_type_t gd_type;
1566 1566 smb_sid_t *sid;
1567 1567 smb_wka_t *wka;
1568 1568 char sidstr[SMB_SID_STRSZ];
1569 1569 char *name;
1570 1570 char *desc;
1571 1571 uint32_t rid;
1572 1572 uint32_t status;
1573 1573 int rc;
1574 1574
1575 1575 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1576 1576 status = NT_STATUS_INVALID_HANDLE;
1577 1577 goto query_alias_err;
1578 1578 }
1579 1579
1580 1580 data = (samr_keydata_t *)hd->nh_data;
1581 1581 gd_type = (smb_domain_type_t)data->kd_type;
1582 1582 rid = data->kd_rid;
1583 1583
1584 1584 switch (gd_type) {
1585 1585 case SMB_DOMAIN_BUILTIN:
1586 1586 (void) snprintf(sidstr, SMB_SID_STRSZ, "%s-%d",
1587 1587 NT_BUILTIN_DOMAIN_SIDSTR, rid);
1588 1588 if ((sid = smb_sid_fromstr(sidstr)) == NULL) {
1589 1589 status = NT_STATUS_NO_SUCH_ALIAS;
1590 1590 goto query_alias_err;
1591 1591 }
1592 1592
1593 1593 wka = smb_wka_lookup_sid(sid);
1594 1594 smb_sid_free(sid);
1595 1595
1596 1596 if (wka == NULL) {
1597 1597 status = NT_STATUS_NO_SUCH_ALIAS;
1598 1598 goto query_alias_err;
1599 1599 }
1600 1600
1601 1601 name = wka->wka_name;
1602 1602 desc = (wka->wka_desc != NULL) ? wka->wka_desc : "";
1603 1603 break;
1604 1604
1605 1605 case SMB_DOMAIN_LOCAL:
1606 1606 rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1607 1607 if (rc != SMB_LGRP_SUCCESS) {
1608 1608 status = NT_STATUS_NO_SUCH_ALIAS;
1609 1609 goto query_alias_err;
1610 1610 }
1611 1611 name = grp.sg_name;
1612 1612 desc = grp.sg_cmnt;
1613 1613 break;
1614 1614
1615 1615 default:
1616 1616 status = NT_STATUS_NO_SUCH_ALIAS;
1617 1617 goto query_alias_err;
1618 1618 }
1619 1619
1620 1620 switch (param->level) {
1621 1621 case SAMR_QUERY_ALIAS_INFO_GENERAL:
1622 1622 param->ru.info1.level = param->level;
1623 1623 (void) NDR_MSTRING(mxa, name,
1624 1624 (ndr_mstring_t *)¶m->ru.info1.name);
1625 1625 (void) NDR_MSTRING(mxa, desc,
1626 1626 (ndr_mstring_t *)¶m->ru.info1.desc);
1627 1627 param->ru.info1.member_count = 1;
1628 1628 break;
1629 1629
1630 1630 case SAMR_QUERY_ALIAS_INFO_NAME:
1631 1631 param->ru.info2.level = param->level;
1632 1632 (void) NDR_MSTRING(mxa, name,
1633 1633 (ndr_mstring_t *)¶m->ru.info2.name);
1634 1634 break;
1635 1635
1636 1636 case SAMR_QUERY_ALIAS_INFO_COMMENT:
1637 1637 param->ru.info3.level = param->level;
1638 1638 (void) NDR_MSTRING(mxa, desc,
1639 1639 (ndr_mstring_t *)¶m->ru.info3.desc);
1640 1640 break;
1641 1641
1642 1642 default:
1643 1643 if (gd_type == SMB_DOMAIN_LOCAL)
1644 1644 smb_lgrp_free(&grp);
1645 1645 status = NT_STATUS_INVALID_INFO_CLASS;
1646 1646 goto query_alias_err;
1647 1647 };
1648 1648
1649 1649 if (gd_type == SMB_DOMAIN_LOCAL)
1650 1650 smb_lgrp_free(&grp);
1651 1651 param->address = (DWORD)(uintptr_t)¶m->ru;
1652 1652 param->status = 0;
1653 1653 return (NDR_DRC_OK);
1654 1654
1655 1655 query_alias_err:
1656 1656 param->status = NT_SC_ERROR(status);
1657 1657 return (NDR_DRC_OK);
1658 1658 }
1659 1659
1660 1660 /*
1661 1661 * samr_s_DeleteDomainAlias
1662 1662 *
1663 1663 * Deletes a local group in the security database, which is the
1664 1664 * security accounts manager (SAM). A valid group handle is returned
1665 1665 * to the caller upon success.
1666 1666 *
1667 1667 * The caller must have administrator rights to execute this function.
1668 1668 */
1669 1669 static int
1670 1670 samr_s_DeleteDomainAlias(void *arg, ndr_xa_t *mxa)
1671 1671 {
1672 1672 struct samr_DeleteDomainAlias *param = arg;
1673 1673 ndr_hdid_t *id = (ndr_hdid_t *)¶m->alias_handle;
1674 1674 ndr_handle_t *hd;
1675 1675 smb_group_t grp;
1676 1676 samr_keydata_t *data;
1677 1677 smb_domain_type_t gd_type;
1678 1678 uint32_t rid;
1679 1679 uint32_t rc;
1680 1680 uint32_t status = NT_STATUS_SUCCESS;
1681 1681
1682 1682 if (!ndr_is_admin(mxa)) {
1683 1683 bzero(param, sizeof (struct samr_DeleteDomainAlias));
1684 1684 param->status = NT_SC_ERROR(NT_STATUS_ACCESS_DENIED);
1685 1685 return (NDR_DRC_OK);
1686 1686 }
1687 1687
1688 1688 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_ALIAS)) == NULL) {
1689 1689 bzero(param, sizeof (struct samr_DeleteDomainAlias));
1690 1690 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1691 1691 return (NDR_DRC_OK);
1692 1692 }
1693 1693
1694 1694 data = (samr_keydata_t *)hd->nh_data;
1695 1695 gd_type = (smb_domain_type_t)data->kd_type;
1696 1696 rid = data->kd_rid;
1697 1697
1698 1698 switch (gd_type) {
1699 1699 case SMB_DOMAIN_BUILTIN:
1700 1700 bzero(param, sizeof (struct samr_DeleteDomainAlias));
1701 1701 status = NT_SC_ERROR(NT_STATUS_NOT_SUPPORTED);
1702 1702 break;
1703 1703
1704 1704 case SMB_DOMAIN_LOCAL:
1705 1705 rc = smb_lgrp_getbyrid(rid, gd_type, &grp);
1706 1706 if (rc != SMB_LGRP_SUCCESS) {
1707 1707 bzero(param, sizeof (struct samr_DeleteDomainAlias));
1708 1708 status = smb_lgrp_err_to_ntstatus(rc);
1709 1709 status = NT_SC_ERROR(status);
1710 1710 break;
1711 1711 }
1712 1712
1713 1713 rc = smb_lgrp_delete(grp.sg_name);
1714 1714 if (rc != SMB_LGRP_SUCCESS) {
1715 1715 bzero(param, sizeof (struct samr_DeleteDomainAlias));
1716 1716 status = smb_lgrp_err_to_ntstatus(rc);
1717 1717 status = NT_SC_ERROR(status);
1718 1718 }
1719 1719 smb_lgrp_free(&grp);
1720 1720 break;
1721 1721
1722 1722 default:
1723 1723 bzero(param, sizeof (struct samr_DeleteDomainAlias));
1724 1724 status = NT_SC_ERROR(NT_STATUS_NO_SUCH_ALIAS);
1725 1725 }
1726 1726
1727 1727 param->status = status;
1728 1728 return (NDR_DRC_OK);
1729 1729 }
1730 1730
1731 1731 /*
1732 1732 * samr_s_EnumDomainAliases
1733 1733 *
1734 1734 * This function sends back a list which contains all local groups' name.
1735 1735 */
1736 1736 static int
1737 1737 samr_s_EnumDomainAliases(void *arg, ndr_xa_t *mxa)
1738 1738 {
1739 1739 struct samr_EnumDomainAliases *param = arg;
1740 1740 ndr_hdid_t *id = (ndr_hdid_t *)¶m->domain_handle;
1741 1741 ndr_handle_t *hd;
1742 1742 samr_keydata_t *data;
1743 1743 smb_group_t grp;
1744 1744 smb_giter_t gi;
1745 1745 int cnt, skip, i;
1746 1746 struct name_rid *info;
1747 1747
1748 1748 if ((hd = samr_hdlookup(mxa, id, SAMR_KEY_DOMAIN)) == NULL) {
1749 1749 bzero(param, sizeof (struct samr_EnumDomainAliases));
1750 1750 param->status = NT_SC_ERROR(NT_STATUS_INVALID_HANDLE);
1751 1751 return (NDR_DRC_OK);
1752 1752 }
1753 1753
1754 1754 data = (samr_keydata_t *)hd->nh_data;
1755 1755
1756 1756 cnt = smb_sam_grp_cnt(data->kd_type);
1757 1757 if (cnt <= param->resume_handle) {
1758 1758 param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1759 1759 sizeof (struct aliases_info));
1760 1760
1761 1761 if (param->aliases == NULL) {
1762 1762 bzero(param, sizeof (struct samr_EnumDomainAliases));
1763 1763 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1764 1764 return (NDR_DRC_OK);
1765 1765 }
1766 1766
1767 1767 bzero(param->aliases, sizeof (struct aliases_info));
1768 1768 param->out_resume = 0;
1769 1769 param->entries = 0;
1770 1770 param->status = NT_STATUS_SUCCESS;
1771 1771 return (NDR_DRC_OK);
1772 1772 }
1773 1773
1774 1774 cnt -= param->resume_handle;
1775 1775 param->aliases = (struct aliases_info *)NDR_MALLOC(mxa,
1776 1776 sizeof (struct aliases_info) + (cnt-1) * sizeof (struct name_rid));
1777 1777
1778 1778 if (param->aliases == NULL) {
1779 1779 bzero(param, sizeof (struct samr_EnumDomainAliases));
1780 1780 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1781 1781 return (NDR_DRC_OK);
1782 1782 }
1783 1783
1784 1784 if (smb_lgrp_iteropen(&gi) != SMB_LGRP_SUCCESS) {
1785 1785 bzero(param, sizeof (struct samr_EnumDomainAliases));
1786 1786 param->status = NT_SC_ERROR(NT_STATUS_INTERNAL_ERROR);
1787 1787 return (NDR_DRC_OK);
1788 1788 }
1789 1789
1790 1790 skip = i = 0;
1791 1791 info = param->aliases->info;
1792 1792 while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) {
1793 1793 if ((skip++ >= param->resume_handle) &&
1794 1794 (grp.sg_domain == data->kd_type) && (i++ < cnt)) {
1795 1795 info->rid = grp.sg_rid;
1796 1796 (void) NDR_MSTRING(mxa, grp.sg_name,
1797 1797 (ndr_mstring_t *)&info->name);
1798 1798
1799 1799 info++;
1800 1800 }
1801 1801 smb_lgrp_free(&grp);
1802 1802 }
1803 1803 smb_lgrp_iterclose(&gi);
1804 1804
1805 1805 param->aliases->count = i;
1806 1806 param->aliases->address = i;
1807 1807
1808 1808 param->out_resume = i;
1809 1809 param->entries = i;
1810 1810 param->status = 0;
1811 1811 return (NDR_DRC_OK);
1812 1812 }
1813 1813
1814 1814 /*
1815 1815 * samr_s_Connect4
1816 1816 */
1817 1817 static int
1818 1818 samr_s_Connect4(void *arg, ndr_xa_t *mxa)
1819 1819 {
1820 1820 struct samr_Connect4 *param = arg;
1821 1821 ndr_hdid_t *id;
1822 1822
1823 1823 id = samr_hdalloc(mxa, SAMR_KEY_CONNECT, SMB_DOMAIN_NULL, 0);
1824 1824 if (id) {
1825 1825 bcopy(id, ¶m->handle, sizeof (samr_handle_t));
1826 1826 param->status = 0;
1827 1827 } else {
1828 1828 bzero(¶m->handle, sizeof (samr_handle_t));
1829 1829 param->status = NT_SC_ERROR(NT_STATUS_NO_MEMORY);
1830 1830 }
1831 1831
1832 1832 return (NDR_DRC_OK);
1833 1833 }
1834 1834
1835 1835 /*
1836 1836 * samr_s_Connect5
1837 1837 *
1838 1838 * This is the connect5 form of the connect request used by Windows XP.
1839 1839 * Returns an RPC fault for now.
1840 1840 */
1841 1841 /*ARGSUSED*/
1842 1842 static int
1843 1843 samr_s_Connect5(void *arg, ndr_xa_t *mxa)
1844 1844 {
1845 1845 struct samr_Connect5 *param = arg;
1846 1846
1847 1847 bzero(param, sizeof (struct samr_Connect5));
1848 1848 return (NDR_DRC_FAULT_REQUEST_OPNUM_INVALID);
1849 1849 }
1850 1850
1851 1851 static ndr_stub_table_t samr_stub_table[] = {
1852 1852 { samr_s_Connect, SAMR_OPNUM_Connect },
1853 1853 { samr_s_CloseHandle, SAMR_OPNUM_CloseHandle },
1854 1854 { samr_s_LookupDomain, SAMR_OPNUM_LookupDomain },
1855 1855 { samr_s_EnumLocalDomains, SAMR_OPNUM_EnumLocalDomains },
1856 1856 { samr_s_OpenDomain, SAMR_OPNUM_OpenDomain },
1857 1857 { samr_s_QueryDomainInfo, SAMR_OPNUM_QueryDomainInfo },
1858 1858 { samr_s_QueryInfoDomain2, SAMR_OPNUM_QueryInfoDomain2 },
1859 1859 { samr_s_LookupNames, SAMR_OPNUM_LookupNames },
1860 1860 { samr_s_OpenUser, SAMR_OPNUM_OpenUser },
1861 1861 { samr_s_DeleteUser, SAMR_OPNUM_DeleteUser },
1862 1862 { samr_s_QueryUserInfo, SAMR_OPNUM_QueryUserInfo },
1863 1863 { samr_s_QueryUserGroups, SAMR_OPNUM_QueryUserGroups },
1864 1864 { samr_s_OpenGroup, SAMR_OPNUM_OpenGroup },
1865 1865 { samr_s_Connect2, SAMR_OPNUM_Connect2 },
1866 1866 { samr_s_GetUserPwInfo, SAMR_OPNUM_GetUserPwInfo },
1867 1867 { samr_s_CreateUser, SAMR_OPNUM_CreateUser },
1868 1868 { samr_s_ChangePasswordUser2, SAMR_OPNUM_ChangePasswordUser2 },
1869 1869 { samr_s_GetDomainPwInfo, SAMR_OPNUM_GetDomainPwInfo },
1870 1870 { samr_s_SetUserInfo, SAMR_OPNUM_SetUserInfo },
1871 1871 { samr_s_Connect4, SAMR_OPNUM_Connect4 },
1872 1872 { samr_s_Connect5, SAMR_OPNUM_Connect5 },
1873 1873 { samr_s_QueryDispInfo, SAMR_OPNUM_QueryDispInfo },
1874 1874 { samr_s_OpenAlias, SAMR_OPNUM_OpenAlias },
1875 1875 { samr_s_CreateDomainAlias, SAMR_OPNUM_CreateDomainAlias },
1876 1876 { samr_s_SetAliasInfo, SAMR_OPNUM_SetAliasInfo },
1877 1877 { samr_s_QueryAliasInfo, SAMR_OPNUM_QueryAliasInfo },
1878 1878 { samr_s_DeleteDomainAlias, SAMR_OPNUM_DeleteDomainAlias },
1879 1879 { samr_s_EnumDomainAliases, SAMR_OPNUM_EnumDomainAliases },
1880 1880 { samr_s_EnumDomainGroups, SAMR_OPNUM_EnumDomainGroups },
1881 1881 { samr_s_AddAliasMember, SAMR_OPNUM_AddAliasMember },
1882 1882 { samr_s_DeleteAliasMember, SAMR_OPNUM_DeleteAliasMember },
1883 1883 { samr_s_ListAliasMembers, SAMR_OPNUM_ListAliasMembers },
1884 1884 {0}
1885 1885 };
1886 1886
1887 1887 /*
1888 1888 * There is a bug in the way that midl and the marshalling code handles
1889 1889 * unions so we need to fix some of the data offsets at runtime. The
1890 1890 * following macros and the fixup functions handle the corrections.
1891 1891 */
1892 1892
1893 1893 DECL_FIXUP_STRUCT(samr_QueryAliasInfo_ru);
1894 1894 DECL_FIXUP_STRUCT(samr_QueryAliasInfoRes);
1895 1895 DECL_FIXUP_STRUCT(samr_QueryAliasInfo);
1896 1896
1897 1897 DECL_FIXUP_STRUCT(QueryUserInfo_result_u);
1898 1898 DECL_FIXUP_STRUCT(QueryUserInfo_result);
1899 1899 DECL_FIXUP_STRUCT(samr_QueryUserInfo);
1900 1900
1901 1901 void
1902 1902 fixup_samr_QueryAliasInfo(struct samr_QueryAliasInfo *val)
1903 1903 {
1904 1904 unsigned short size1 = 0;
1905 1905 unsigned short size2 = 0;
1906 1906 unsigned short size3 = 0;
1907 1907
1908 1908 switch (val->level) {
1909 1909 case SAMR_QUERY_ALIAS_INFO_GENERAL:
1910 1910 size1 = sizeof (struct samr_QueryAliasInfoGeneral);
1911 1911 break;
1912 1912 case SAMR_QUERY_ALIAS_INFO_NAME:
1913 1913 size1 = sizeof (struct samr_QueryAliasInfoName);
1914 1914 break;
1915 1915 case SAMR_QUERY_ALIAS_INFO_COMMENT:
1916 1916 size1 = sizeof (struct samr_QueryAliasInfoComment);
1917 1917 break;
1918 1918
1919 1919 default:
1920 1920 return;
1921 1921 };
1922 1922
1923 1923 size2 = size1 + (2 * sizeof (DWORD));
1924 1924 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1925 1925
1926 1926 FIXUP_PDU_SIZE(samr_QueryAliasInfo_ru, size1);
1927 1927 FIXUP_PDU_SIZE(samr_QueryAliasInfoRes, size2);
1928 1928 FIXUP_PDU_SIZE(samr_QueryAliasInfo, size3);
1929 1929 }
1930 1930
1931 1931 void
1932 1932 fixup_samr_QueryUserInfo(struct samr_QueryUserInfo *val)
1933 1933 {
1934 1934 unsigned short size1 = 0;
1935 1935 unsigned short size2 = 0;
1936 1936 unsigned short size3 = 0;
1937 1937
1938 1938 switch (val->switch_index) {
1939 1939 CASE_INFO_ENT(samr_QueryUserInfo, 1);
1940 1940 CASE_INFO_ENT(samr_QueryUserInfo, 6);
1941 1941 CASE_INFO_ENT(samr_QueryUserInfo, 7);
1942 1942 CASE_INFO_ENT(samr_QueryUserInfo, 8);
1943 1943 CASE_INFO_ENT(samr_QueryUserInfo, 9);
1944 1944 CASE_INFO_ENT(samr_QueryUserInfo, 16);
1945 1945 CASE_INFO_ENT(samr_QueryUserInfo, 21);
1946 1946
1947 1947 default:
1948 1948 return;
1949 1949 };
1950 1950
1951 1951 size2 = size1 + (2 * sizeof (DWORD));
1952 1952 size3 = size2 + sizeof (ndr_request_hdr_t) + sizeof (DWORD);
1953 1953
1954 1954 FIXUP_PDU_SIZE(QueryUserInfo_result_u, size1);
1955 1955 FIXUP_PDU_SIZE(QueryUserInfo_result, size2);
1956 1956 FIXUP_PDU_SIZE(samr_QueryUserInfo, size3);
1957 1957 }
1958 1958
1959 1959 /*
1960 1960 * As long as there is only one entry in the union, there is no need
1961 1961 * to patch anything.
1962 1962 */
1963 1963 /*ARGSUSED*/
1964 1964 void
1965 1965 fixup_samr_QueryGroupInfo(struct samr_QueryGroupInfo *val)
1966 1966 {
1967 1967 }
↓ open down ↓ |
1914 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX