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