Print this page
1575 untangle libmlrpc ... pre2:
Get rid of ndr_rpc_server_{info,os}
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.c
+++ new/usr/src/lib/smbsrv/libmlsvc/common/lsar_clnt.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 * Local Security Authority RPC (LSAR) client-side interface.
29 29 */
30 30
31 31 #include <sys/errno.h>
32 32 #include <stdio.h>
33 33 #include <stdlib.h>
34 34 #include <strings.h>
35 35
36 36 #include <smbsrv/libsmb.h>
37 37 #include <smbsrv/libmlsvc.h>
38 38 #include <smbsrv/smbinfo.h>
39 39 #include <smbsrv/ntaccess.h>
40 40 #include <smbsrv/ntlocale.h>
41 41 #include <smbsrv/string.h>
42 42 #include <lsalib.h>
43 43
44 44 /*
45 45 * The maximum number of bytes we are prepared to deal with in a
46 46 * response.
47 47 */
48 48 #define MLSVC_MAX_RESPONSE_LEN 1024
49 49
50 50 /*
51 51 * This structure is used when looking up names. We only lookup one
52 52 * name at a time but the structure will allow for more.
53 53 */
54 54 typedef struct lsa_names {
55 55 uint32_t n_entry;
56 56 mslsa_string_t name[8];
57 57 } lsa_names_t;
58 58
59 59 typedef DWORD (*lsar_nameop_t)(mlsvc_handle_t *, lsa_names_t *,
60 60 smb_account_t *);
61 61
62 62 static uint32_t lsar_lookup_names1(mlsvc_handle_t *, lsa_names_t *,
63 63 smb_account_t *);
64 64 static uint32_t lsar_lookup_names2(mlsvc_handle_t *, lsa_names_t *,
65 65 smb_account_t *);
66 66 static uint32_t lsar_lookup_names3(mlsvc_handle_t *, lsa_names_t *,
67 67 smb_account_t *);
68 68 static uint32_t lsar_lookup_sids1(mlsvc_handle_t *, lsa_sid_t *,
69 69 smb_account_t *);
70 70 static uint32_t lsar_lookup_sids2(mlsvc_handle_t *, lsa_sid_t *,
71 71 smb_account_t *account);
72 72
73 73 static char *lsar_get_username(const char *);
74 74 static void smb_account_trace(const smb_account_t *);
75 75
76 76 static void lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *,
77 77 smb_trusted_domains_t *);
78 78 static void lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *,
79 79 smb_trusted_domains_t *);
80 80
81 81 /*
82 82 * lsar_open
83 83 *
84 84 * This is a wrapper round lsar_open_policy2 to ensure that we connect
85 85 * using the appropriate domain information.
86 86 *
87 87 * If username argument is NULL, an anonymous connection will be established.
88 88 * Otherwise, an authenticated connection will be established.
89 89 *
90 90 * Returns 0 or NT status (Raw, not LSA-ized)
91 91 */
92 92 DWORD
93 93 lsar_open(char *server, char *domain, char *username,
94 94 mlsvc_handle_t *domain_handle)
95 95 {
96 96 DWORD status;
97 97
98 98 if (server == NULL || domain == NULL)
99 99 return (NT_STATUS_INTERNAL_ERROR);
100 100
101 101 if (username == NULL)
102 102 username = MLSVC_ANON_USER;
103 103
104 104 status = lsar_open_policy2(server, domain, username, domain_handle);
105 105
106 106 return (status);
107 107 }
108 108
109 109 /*
110 110 * lsar_open_policy2
111 111 *
112 112 * Obtain an LSA policy handle. A policy handle is required to access
113 113 * LSA resources on a remote server. The server name supplied here does
114 114 * not need the double backslash prefix; it is added here. Call this
115 115 * function via lsar_open to ensure that the appropriate connection is
116 116 * in place.
117 117 *
118 118 * Returns 0 or NT status (Raw, not LSA-ized)
119 119 */
120 120 DWORD
121 121 lsar_open_policy2(char *server, char *domain, char *user,
122 122 mlsvc_handle_t *lsa_handle)
123 123 {
124 124 struct mslsa_OpenPolicy2 arg;
125 125 DWORD status;
126 126 int opnum;
127 127 int len;
128 128
129 129 status = ndr_rpc_bind(lsa_handle, server, domain, user, "LSARPC");
130 130 if (status != 0)
131 131 return (status);
132 132
133 133 opnum = LSARPC_OPNUM_OpenPolicy2;
134 134 bzero(&arg, sizeof (struct mslsa_OpenPolicy2));
135 135
136 136 len = strlen(server) + 4;
137 137 arg.servername = ndr_rpc_malloc(lsa_handle, len);
138 138 if (arg.servername == NULL) {
139 139 status = NT_STATUS_NO_MEMORY;
140 140 goto out;
141 141 }
142 142
143 143 (void) snprintf((char *)arg.servername, len, "\\\\%s", server);
144 144 arg.attributes.length = sizeof (struct mslsa_object_attributes);
145 145 arg.desiredAccess = MAXIMUM_ALLOWED;
146 146
147 147 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
148 148 status = RPC_NT_CALL_FAILED;
149 149 goto out;
150 150 }
151 151 status = arg.status;
152 152 if (status == NT_STATUS_SUCCESS) {
153 153 (void) memcpy(&lsa_handle->handle, &arg.domain_handle,
154 154 sizeof (ndr_hdid_t));
155 155
156 156 if (ndr_is_null_handle(lsa_handle))
157 157 status = NT_STATUS_INVALID_PARAMETER;
158 158 }
159 159
160 160 ndr_rpc_release(lsa_handle);
161 161
162 162 out:
163 163 if (status != NT_STATUS_SUCCESS)
164 164 ndr_rpc_unbind(lsa_handle);
165 165 return (status);
166 166 }
167 167
168 168 /*
169 169 * lsar_open_account
170 170 *
171 171 * Obtain an LSA account handle. The lsa_handle must be a valid handle
172 172 * obtained via lsar_open_policy2. The main thing to remember here is
173 173 * to set up the context in the lsa_account_handle. I'm not sure what
174 174 * the requirements are for desired access. Some values require admin
175 175 * access.
176 176 *
177 177 * Returns 0 on success. Otherwise non-zero to indicate a failure.
178 178 */
179 179 int
180 180 lsar_open_account(mlsvc_handle_t *lsa_handle, struct mslsa_sid *sid,
181 181 mlsvc_handle_t *lsa_account_handle)
182 182 {
183 183 struct mslsa_OpenAccount arg;
184 184 int opnum;
185 185 int rc;
186 186
187 187 if (ndr_is_null_handle(lsa_handle) || sid == NULL)
188 188 return (-1);
189 189
190 190 opnum = LSARPC_OPNUM_OpenAccount;
191 191 bzero(&arg, sizeof (struct mslsa_OpenAccount));
192 192
193 193 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
194 194 arg.sid = sid;
195 195 arg.access_mask = STANDARD_RIGHTS_REQUIRED
196 196 #if 0
197 197 | POLICY_VIEW_AUDIT_INFORMATION
198 198 | POLICY_GET_PRIVATE_INFORMATION
199 199 | POLICY_TRUST_ADMIN
200 200 #endif
201 201 | POLICY_VIEW_LOCAL_INFORMATION;
202 202
203 203 if ((rc = ndr_rpc_call(lsa_handle, opnum, &arg)) != 0)
204 204 return (-1);
205 205
206 206 if (arg.status != 0) {
207 207 rc = -1;
208 208 } else {
209 209 ndr_inherit_handle(lsa_account_handle, lsa_handle);
210 210
211 211 (void) memcpy(&lsa_account_handle->handle,
212 212 &arg.account_handle, sizeof (ndr_hdid_t));
213 213
214 214 if (ndr_is_null_handle(lsa_account_handle))
215 215 rc = -1;
216 216 }
217 217
218 218 ndr_rpc_release(lsa_handle);
219 219 return (rc);
220 220 }
221 221
222 222 /*
223 223 * lsar_close
224 224 *
225 225 * Close the LSA connection associated with the handle. The lsa_handle
226 226 * must be a valid handle obtained via a call to lsar_open_policy2 or
227 227 * lsar_open_account. On success the handle will be zeroed out to
228 228 * ensure that it is not used again. If this is the top level handle
229 229 * (i.e. the one obtained via lsar_open_policy2) the pipe is closed.
230 230 *
231 231 * Returns 0 on success. Otherwise non-zero to indicate a failure.
232 232 */
233 233 int
234 234 lsar_close(mlsvc_handle_t *lsa_handle)
235 235 {
236 236 struct mslsa_CloseHandle arg;
237 237 int opnum;
238 238
239 239 if (ndr_is_null_handle(lsa_handle))
240 240 return (-1);
241 241
242 242 opnum = LSARPC_OPNUM_CloseHandle;
243 243 bzero(&arg, sizeof (struct mslsa_CloseHandle));
244 244 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
245 245
246 246 (void) ndr_rpc_call(lsa_handle, opnum, &arg);
247 247 ndr_rpc_release(lsa_handle);
248 248
249 249 if (ndr_is_bind_handle(lsa_handle))
250 250 ndr_rpc_unbind(lsa_handle);
251 251
252 252 bzero(lsa_handle, sizeof (mlsvc_handle_t));
253 253 return (0);
254 254 }
255 255
256 256 /*
257 257 * lsar_query_security_desc
258 258 *
259 259 * Don't use this call yet. It is just a place holder for now.
260 260 */
261 261 int
262 262 lsar_query_security_desc(mlsvc_handle_t *lsa_handle)
263 263 {
264 264 struct mslsa_QuerySecurityObject arg;
265 265 int rc;
266 266 int opnum;
267 267
268 268 opnum = LSARPC_OPNUM_QuerySecurityObject;
269 269
270 270 bzero(&arg, sizeof (struct mslsa_QuerySecurityObject));
271 271 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
272 272
273 273 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
274 274 ndr_rpc_release(lsa_handle);
275 275 return (rc);
276 276 }
277 277
278 278 /*
279 279 * lsar_query_info_policy
280 280 *
281 281 * The general purpose of this function is to allow various pieces of
282 282 * information to be queried on the domain controller. The only
283 283 * information queries supported are MSLSA_POLICY_PRIMARY_DOMAIN_INFO
284 284 * and MSLSA_POLICY_ACCOUNT_DOMAIN_INFO.
285 285 *
286 286 * On success, the return code will be 0 and the user_info structure
287 287 * will be set up. The sid_name_use field will be set to SidTypeDomain
288 288 * indicating that the domain name and domain sid fields are vaild. If
289 289 * the infoClass returned from the server is not one of the supported
290 290 * values, the sid_name_use willbe set to SidTypeUnknown. If the RPC
291 291 * fails, a negative error code will be returned, in which case the
292 292 * user_info will not have been updated.
293 293 */
294 294 DWORD
295 295 lsar_query_info_policy(mlsvc_handle_t *lsa_handle, WORD infoClass,
296 296 smb_domain_t *info)
297 297 {
298 298 struct mslsa_QueryInfoPolicy arg;
299 299 struct mslsa_PrimaryDomainInfo *pd_info;
300 300 struct mslsa_AccountDomainInfo *ad_info;
301 301 struct mslsa_DnsDomainInfo *dns_info;
302 302 char guid_str[UUID_PRINTABLE_STRING_LENGTH];
303 303 char sidstr[SMB_SID_STRSZ];
304 304 int opnum;
305 305 DWORD status;
306 306
307 307 if (lsa_handle == NULL || info == NULL)
308 308 return (NT_STATUS_INVALID_PARAMETER);
309 309
310 310 opnum = LSARPC_OPNUM_QueryInfoPolicy;
311 311
312 312 bzero(info, sizeof (smb_domain_t));
313 313 bzero(&arg, sizeof (struct mslsa_QueryInfoPolicy));
314 314 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
315 315
316 316 arg.info_class = infoClass;
317 317
318 318 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
319 319 status = NT_STATUS_INVALID_PARAMETER;
320 320 } else if (arg.status != 0) {
321 321 ndr_rpc_status(lsa_handle, opnum, arg.status);
322 322 status = NT_SC_VALUE(arg.status);
323 323 } else {
324 324
325 325 switch (infoClass) {
326 326 case MSLSA_POLICY_PRIMARY_DOMAIN_INFO:
327 327 pd_info = &arg.ru.pd_info;
328 328
329 329 smb_sid_tostr((smb_sid_t *)pd_info->sid, sidstr);
330 330 info->di_type = SMB_DOMAIN_PRIMARY;
331 331 smb_domain_set_basic_info(sidstr,
332 332 (char *)pd_info->name.str, "", info);
333 333
334 334 status = NT_STATUS_SUCCESS;
335 335 break;
336 336
337 337 case MSLSA_POLICY_ACCOUNT_DOMAIN_INFO:
338 338 ad_info = &arg.ru.ad_info;
339 339
340 340 smb_sid_tostr((smb_sid_t *)ad_info->sid, sidstr);
341 341 info->di_type = SMB_DOMAIN_ACCOUNT;
342 342 smb_domain_set_basic_info(sidstr,
343 343 (char *)ad_info->name.str, "", info);
344 344
345 345 status = NT_STATUS_SUCCESS;
346 346 break;
347 347
348 348 case MSLSA_POLICY_DNS_DOMAIN_INFO:
349 349 dns_info = &arg.ru.dns_info;
350 350 ndr_uuid_unparse((ndr_uuid_t *)&dns_info->guid,
351 351 guid_str);
352 352 smb_sid_tostr((smb_sid_t *)dns_info->sid, sidstr);
353 353
354 354 info->di_type = SMB_DOMAIN_PRIMARY;
355 355 smb_domain_set_dns_info(sidstr,
356 356 (char *)dns_info->nb_domain.str,
357 357 (char *)dns_info->dns_domain.str,
358 358 (char *)dns_info->forest.str,
359 359 guid_str, info);
360 360 status = NT_STATUS_SUCCESS;
361 361 break;
362 362
363 363 default:
364 364 status = NT_STATUS_INVALID_INFO_CLASS;
365 365 break;
366 366 }
367 367 }
368 368
369 369 ndr_rpc_release(lsa_handle);
370 370 return (status);
371 371 }
372 372
373 373 /*
374 374 * Lookup a name and obtain the sid/rid.
375 375 * This is a wrapper for the various lookup sid RPCs.
↓ open down ↓ |
375 lines elided |
↑ open up ↑ |
376 376 */
377 377 uint32_t
378 378 lsar_lookup_names(mlsvc_handle_t *lsa_handle, char *name, smb_account_t *info)
379 379 {
380 380 static lsar_nameop_t ops[] = {
381 381 lsar_lookup_names3,
382 382 lsar_lookup_names2,
383 383 lsar_lookup_names1
384 384 };
385 385
386 - const srvsvc_server_info_t *svinfo;
387 386 lsa_names_t names;
388 387 char *p;
389 388 uint32_t length;
390 389 uint32_t status = NT_STATUS_INVALID_PARAMETER;
391 390 int n_op = (sizeof (ops) / sizeof (ops[0]));
392 391 int i;
393 392
394 393 if (lsa_handle == NULL || name == NULL || info == NULL)
395 394 return (NT_STATUS_INVALID_PARAMETER);
396 395
397 396 bzero(info, sizeof (smb_account_t));
398 397
399 - svinfo = ndr_rpc_server_info(lsa_handle);
400 - if (svinfo->sv_os == NATIVE_OS_WIN2000 &&
401 - svinfo->sv_version_major == 5 && svinfo->sv_version_minor == 0) {
402 - /*
403 - * Windows 2000 doesn't like an LSA lookup for
404 - * DOMAIN\Administrator.
405 - */
406 - if ((p = strchr(name, '\\')) != 0) {
407 - ++p;
398 + /*
399 + * Windows 2000 (or later) doesn't like an LSA lookup for
400 + * DOMAIN\Administrator.
401 + */
402 + if ((p = strchr(name, '\\')) != 0) {
403 + ++p;
408 404
409 - if (strcasecmp(p, "administrator") == 0)
410 - name = p;
411 - }
412 -
405 + if (strcasecmp(p, "administrator") == 0)
406 + name = p;
413 407 }
414 408
415 409 length = smb_wcequiv_strlen(name);
416 410 names.name[0].length = length;
417 411 names.name[0].allosize = length;
418 412 names.name[0].str = (unsigned char *)name;
419 413 names.n_entry = 1;
420 414
421 - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000) {
422 - for (i = 0; i < n_op; ++i) {
423 - ndr_rpc_set_nonull(lsa_handle);
424 - status = (*ops[i])(lsa_handle, &names, info);
425 -
426 - if (status != NT_STATUS_INVALID_PARAMETER)
427 - break;
428 - }
429 - } else {
415 + for (i = 0; i < n_op; ++i) {
430 416 ndr_rpc_set_nonull(lsa_handle);
431 - status = lsar_lookup_names1(lsa_handle, &names, info);
417 + status = (*ops[i])(lsa_handle, &names, info);
418 +
419 + if (status != NT_STATUS_INVALID_PARAMETER)
420 + break;
432 421 }
433 422
434 423 if (status == NT_STATUS_SUCCESS) {
435 424 info->a_name = lsar_get_username(name);
436 425
437 426 if (!smb_account_validate(info)) {
438 427 smb_account_free(info);
439 428 status = NT_STATUS_NO_MEMORY;
440 429 } else {
441 430 smb_account_trace(info);
442 431 }
443 432 }
444 433
445 434 return (status);
446 435 }
447 436
448 437 /*
449 438 * The name may be in one of the following forms:
450 439 *
451 440 * domain\username
452 441 * domain/username
453 442 * username
454 443 * username@domain
455 444 *
456 445 * Return a strdup'd copy of the username. The caller is responsible
457 446 * for freeing the allocated memory.
458 447 */
459 448 static char *
460 449 lsar_get_username(const char *name)
461 450 {
462 451 char tmp[MAXNAMELEN];
463 452 char *dp = NULL;
464 453 char *np = NULL;
465 454
466 455 (void) strlcpy(tmp, name, MAXNAMELEN);
467 456 smb_name_parse(tmp, &np, &dp);
468 457
469 458 if (dp != NULL && np != NULL)
470 459 return (strdup(np));
471 460 else
472 461 return (strdup(name));
473 462 }
474 463
475 464 /*
476 465 * lsar_lookup_names1
477 466 *
478 467 * Lookup a name and obtain the domain and user rid.
479 468 *
480 469 * Note: NT returns an error if the mapped_count is non-zero when the RPC
481 470 * is called.
482 471 *
483 472 * If the lookup fails, the status will typically be NT_STATUS_NONE_MAPPED.
484 473 */
485 474 static uint32_t
486 475 lsar_lookup_names1(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
487 476 smb_account_t *info)
488 477 {
489 478 struct mslsa_LookupNames arg;
490 479 struct mslsa_rid_entry *rid_entry;
491 480 struct mslsa_domain_entry *domain_entry;
492 481 uint32_t status = NT_STATUS_SUCCESS;
493 482 char *domname;
494 483 int opnum = LSARPC_OPNUM_LookupNames;
495 484
496 485 bzero(&arg, sizeof (struct mslsa_LookupNames));
497 486 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
498 487 arg.lookup_level = LSA_LOOKUP_WKSTA;
499 488 arg.name_table = (struct mslsa_lup_name_table *)names;
500 489
501 490 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
502 491 ndr_rpc_release(lsa_handle);
503 492 return (NT_STATUS_INVALID_PARAMETER);
504 493 }
505 494
506 495 if (arg.status != NT_STATUS_SUCCESS) {
507 496 ndr_rpc_status(lsa_handle, opnum, arg.status);
508 497 ndr_rpc_release(lsa_handle);
509 498 return (NT_SC_VALUE(arg.status));
510 499 }
511 500
512 501 if (arg.mapped_count == 0) {
513 502 ndr_rpc_release(lsa_handle);
514 503 return (NT_STATUS_NONE_MAPPED);
515 504 }
516 505
517 506 rid_entry = &arg.translated_sids.rids[0];
518 507 if (rid_entry->domain_index != 0) {
519 508 ndr_rpc_release(lsa_handle);
520 509 return (NT_STATUS_NONE_MAPPED);
521 510 }
522 511
523 512 domain_entry = &arg.domain_table->entries[0];
524 513
525 514 info->a_type = rid_entry->sid_name_use;
526 515 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
527 516 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
528 517 info->a_domain = strdup(domname);
529 518 info->a_rid = rid_entry->rid;
530 519 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
531 520
532 521 ndr_rpc_release(lsa_handle);
533 522 return (status);
534 523 }
535 524
536 525 /*
537 526 * lsar_lookup_names2
538 527 */
539 528 static uint32_t
540 529 lsar_lookup_names2(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
541 530 smb_account_t *info)
542 531 {
543 532 struct lsar_LookupNames2 arg;
544 533 struct lsar_rid_entry2 *rid_entry;
545 534 struct mslsa_domain_entry *domain_entry;
546 535 uint32_t status = NT_STATUS_SUCCESS;
547 536 char *domname;
548 537 int opnum = LSARPC_OPNUM_LookupNames2;
549 538
550 539 bzero(&arg, sizeof (struct lsar_LookupNames2));
551 540 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
552 541 arg.lookup_level = LSA_LOOKUP_WKSTA;
553 542 arg.client_revision = LSA_CLIENT_REVISION_AD;
554 543 arg.name_table = (struct mslsa_lup_name_table *)names;
555 544
556 545 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
557 546 ndr_rpc_release(lsa_handle);
558 547 return (NT_STATUS_INVALID_PARAMETER);
559 548 }
560 549
561 550 if (arg.status != NT_STATUS_SUCCESS) {
562 551 ndr_rpc_status(lsa_handle, opnum, arg.status);
563 552 ndr_rpc_release(lsa_handle);
564 553 return (NT_SC_VALUE(arg.status));
565 554 }
566 555
567 556 if (arg.mapped_count == 0) {
568 557 ndr_rpc_release(lsa_handle);
569 558 return (NT_STATUS_NONE_MAPPED);
570 559 }
571 560
572 561 rid_entry = &arg.translated_sids.rids[0];
573 562 if (rid_entry->domain_index != 0) {
574 563 ndr_rpc_release(lsa_handle);
575 564 return (NT_STATUS_NONE_MAPPED);
576 565 }
577 566
578 567 domain_entry = &arg.domain_table->entries[0];
579 568
580 569 info->a_type = rid_entry->sid_name_use;
581 570 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
582 571 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
583 572 info->a_domain = strdup(domname);
584 573 info->a_rid = rid_entry->rid;
585 574 info->a_sid = smb_sid_splice(info->a_domsid, info->a_rid);
586 575
587 576 ndr_rpc_release(lsa_handle);
588 577 return (status);
589 578 }
590 579
591 580 /*
592 581 * lsar_lookup_names3
593 582 */
594 583 static uint32_t
595 584 lsar_lookup_names3(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
596 585 smb_account_t *info)
597 586 {
598 587 struct lsar_LookupNames3 arg;
599 588 lsar_translated_sid_ex2_t *sid_entry;
600 589 struct mslsa_domain_entry *domain_entry;
601 590 uint32_t status = NT_STATUS_SUCCESS;
602 591 char *domname;
603 592 int opnum = LSARPC_OPNUM_LookupNames3;
604 593
605 594 bzero(&arg, sizeof (struct lsar_LookupNames3));
606 595 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
607 596 arg.lookup_level = LSA_LOOKUP_WKSTA;
608 597 arg.client_revision = LSA_CLIENT_REVISION_AD;
609 598 arg.name_table = (struct mslsa_lup_name_table *)names;
610 599
611 600 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
612 601 ndr_rpc_release(lsa_handle);
613 602 return (NT_STATUS_INVALID_PARAMETER);
614 603 }
615 604
616 605 if (arg.status != NT_STATUS_SUCCESS) {
617 606 ndr_rpc_status(lsa_handle, opnum, arg.status);
618 607 ndr_rpc_release(lsa_handle);
619 608 return (NT_SC_VALUE(arg.status));
620 609 }
621 610
622 611 if (arg.mapped_count == 0) {
623 612 ndr_rpc_release(lsa_handle);
624 613 return (NT_STATUS_NONE_MAPPED);
625 614 }
626 615
627 616 sid_entry = &arg.translated_sids.sids[0];
628 617 if (sid_entry->domain_index != 0) {
629 618 ndr_rpc_release(lsa_handle);
630 619 return (NT_STATUS_NONE_MAPPED);
631 620 }
632 621
633 622 domain_entry = &arg.domain_table->entries[0];
634 623
635 624 info->a_type = sid_entry->sid_name_use;
636 625 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
637 626 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
638 627 info->a_domain = strdup(domname);
639 628 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
640 629 (void) smb_sid_getrid(info->a_sid, &info->a_rid);
641 630
642 631 ndr_rpc_release(lsa_handle);
643 632 return (status);
644 633 }
645 634
646 635 /*
647 636 * lsar_lookup_names4
648 637 *
649 638 * This function is only valid if the remote RPC server is a domain
650 639 * controller and requires the security extensions defined in MS-RPCE.
651 640 *
652 641 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
653 642 * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
654 643 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
655 644 */
656 645 static uint32_t /*LINTED E_STATIC_UNUSED*/
657 646 lsar_lookup_names4(mlsvc_handle_t *lsa_handle, lsa_names_t *names,
658 647 smb_account_t *info)
659 648 {
660 649 struct lsar_LookupNames4 arg;
661 650 lsar_translated_sid_ex2_t *sid_entry;
662 651 struct mslsa_domain_entry *domain_entry;
663 652 uint32_t status = NT_STATUS_SUCCESS;
664 653 char *domname;
665 654 int opnum = LSARPC_OPNUM_LookupNames4;
666 655
667 656 bzero(&arg, sizeof (struct lsar_LookupNames4));
668 657 arg.lookup_level = LSA_LOOKUP_WKSTA;
669 658 arg.client_revision = LSA_CLIENT_REVISION_AD;
670 659 arg.name_table = (struct mslsa_lup_name_table *)names;
671 660
672 661 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
673 662 ndr_rpc_release(lsa_handle);
674 663 return (NT_STATUS_INVALID_PARAMETER);
675 664 }
676 665
677 666 if (arg.status != NT_STATUS_SUCCESS) {
678 667 ndr_rpc_status(lsa_handle, opnum, arg.status);
679 668 ndr_rpc_release(lsa_handle);
680 669 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
681 670 arg.status == NT_STATUS_INVALID_SERVER_STATE)
682 671 return (NT_STATUS_INVALID_PARAMETER);
683 672 return (NT_SC_VALUE(arg.status));
684 673 }
685 674
686 675 if (arg.mapped_count == 0) {
687 676 ndr_rpc_release(lsa_handle);
688 677 return (NT_STATUS_NONE_MAPPED);
689 678 }
690 679
691 680 sid_entry = &arg.translated_sids.sids[0];
692 681 if (sid_entry->domain_index != 0) {
693 682 ndr_rpc_release(lsa_handle);
694 683 return (NT_STATUS_NONE_MAPPED);
695 684 }
696 685
697 686 domain_entry = &arg.domain_table->entries[0];
698 687
699 688 info->a_type = sid_entry->sid_name_use;
700 689 info->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
701 690 if ((domname = (char *)domain_entry->domain_name.str) != NULL)
702 691 info->a_domain = strdup(domname);
703 692 info->a_sid = smb_sid_dup((smb_sid_t *)sid_entry->sid);
704 693 (void) smb_sid_getrid(info->a_sid, &info->a_rid);
705 694
706 695 ndr_rpc_release(lsa_handle);
707 696 return (status);
708 697 }
709 698
710 699 /*
711 700 * Lookup a sid and obtain the domain sid and account name.
712 701 * This is a wrapper for the various lookup sid RPCs.
713 702 */
714 703 uint32_t
715 704 lsar_lookup_sids(mlsvc_handle_t *lsa_handle, smb_sid_t *sid,
716 705 smb_account_t *account)
717 706 {
718 707 char sidbuf[SMB_SID_STRSZ];
↓ open down ↓ |
277 lines elided |
↑ open up ↑ |
719 708 uint32_t status;
720 709
721 710 if (lsa_handle == NULL || sid == NULL || account == NULL)
722 711 return (NT_STATUS_INVALID_PARAMETER);
723 712
724 713 bzero(account, sizeof (smb_account_t));
725 714 bzero(sidbuf, SMB_SID_STRSZ);
726 715 smb_sid_tostr(sid, sidbuf);
727 716 smb_tracef("%s", sidbuf);
728 717
729 - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
730 - status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid,
731 - account);
732 - else
718 + status = lsar_lookup_sids2(lsa_handle, (lsa_sid_t *)sid, account);
719 + if (status == RPC_NT_PROCNUM_OUT_OF_RANGE)
733 720 status = lsar_lookup_sids1(lsa_handle, (lsa_sid_t *)sid,
734 721 account);
735 722
736 723 if (status == NT_STATUS_SUCCESS) {
737 724 if (!smb_account_validate(account)) {
738 725 smb_account_free(account);
739 726 status = NT_STATUS_NO_MEMORY;
740 727 } else {
741 728 smb_account_trace(account);
742 729 }
743 730 }
744 731
745 732 return (status);
746 733 }
747 734
748 735 /*
749 736 * lsar_lookup_sids1
750 737 */
751 738 static uint32_t
752 739 lsar_lookup_sids1(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
753 740 smb_account_t *account)
754 741 {
755 742 struct mslsa_LookupSids arg;
756 743 struct mslsa_lup_sid_entry sid_entry;
757 744 struct mslsa_name_entry *name_entry;
758 745 struct mslsa_domain_entry *domain_entry;
759 746 uint32_t status = NT_STATUS_SUCCESS;
760 747 char *name;
761 748 int opnum = LSARPC_OPNUM_LookupSids;
762 749
763 750 bzero(&arg, sizeof (struct mslsa_LookupSids));
764 751 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
765 752 arg.lookup_level = LSA_LOOKUP_WKSTA;
766 753
767 754 sid_entry.psid = sid;
768 755 arg.lup_sid_table.n_entry = 1;
769 756 arg.lup_sid_table.entries = &sid_entry;
770 757
771 758 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
772 759 ndr_rpc_release(lsa_handle);
773 760 return (NT_STATUS_INVALID_PARAMETER);
774 761 }
775 762
776 763 if (arg.status != NT_STATUS_SUCCESS) {
777 764 ndr_rpc_status(lsa_handle, opnum, arg.status);
778 765 ndr_rpc_release(lsa_handle);
779 766 return (NT_SC_VALUE(arg.status));
780 767 }
781 768
782 769 if (arg.mapped_count == 0) {
783 770 ndr_rpc_release(lsa_handle);
784 771 return (NT_STATUS_NONE_MAPPED);
785 772 }
786 773
787 774 name_entry = &arg.name_table.entries[0];
788 775 if (name_entry->domain_ix != 0) {
789 776 ndr_rpc_release(lsa_handle);
790 777 return (NT_STATUS_NONE_MAPPED);
791 778 }
792 779
793 780 name = (char *)name_entry->name.str;
794 781 account->a_name = (name) ? strdup(name) : strdup("");
795 782 account->a_type = name_entry->sid_name_use;
796 783 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
797 784 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
798 785
799 786 domain_entry = &arg.domain_table->entries[0];
800 787 if ((name = (char *)domain_entry->domain_name.str) != NULL)
801 788 account->a_domain = strdup(name);
802 789 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
803 790
804 791 ndr_rpc_release(lsa_handle);
805 792 return (status);
806 793 }
807 794
808 795 /*
809 796 * lsar_lookup_sids2
810 797 */
811 798 static uint32_t
812 799 lsar_lookup_sids2(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
813 800 smb_account_t *account)
814 801 {
815 802 struct lsar_lookup_sids2 arg;
816 803 struct lsar_name_entry2 *name_entry;
817 804 struct mslsa_lup_sid_entry sid_entry;
818 805 struct mslsa_domain_entry *domain_entry;
819 806 uint32_t status = NT_STATUS_SUCCESS;
820 807 char *name;
821 808 int opnum = LSARPC_OPNUM_LookupSids2;
822 809
823 810 bzero(&arg, sizeof (struct lsar_lookup_sids2));
824 811 (void) memcpy(&arg.policy_handle, lsa_handle, sizeof (mslsa_handle_t));
825 812
826 813 sid_entry.psid = sid;
827 814 arg.lup_sid_table.n_entry = 1;
828 815 arg.lup_sid_table.entries = &sid_entry;
829 816 arg.lookup_level = LSA_LOOKUP_WKSTA;
830 817 arg.client_revision = LSA_CLIENT_REVISION_AD;
831 818
832 819 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
833 820 ndr_rpc_release(lsa_handle);
834 821 return (NT_STATUS_INVALID_PARAMETER);
835 822 }
836 823
837 824 if (arg.status != NT_STATUS_SUCCESS) {
838 825 ndr_rpc_status(lsa_handle, opnum, arg.status);
839 826 ndr_rpc_release(lsa_handle);
840 827 return (NT_SC_VALUE(arg.status));
841 828 }
842 829
843 830 if (arg.mapped_count == 0) {
844 831 ndr_rpc_release(lsa_handle);
845 832 return (NT_STATUS_NONE_MAPPED);
846 833 }
847 834
848 835 name_entry = &arg.name_table.entries[0];
849 836 if (name_entry->domain_ix != 0) {
850 837 ndr_rpc_release(lsa_handle);
851 838 return (NT_STATUS_NONE_MAPPED);
852 839 }
853 840
854 841 name = (char *)name_entry->name.str;
855 842 account->a_name = (name) ? strdup(name) : strdup("");
856 843 account->a_type = name_entry->sid_name_use;
857 844 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
858 845 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
859 846
860 847 domain_entry = &arg.domain_table->entries[0];
861 848 if ((name = (char *)domain_entry->domain_name.str) != NULL)
862 849 account->a_domain = strdup(name);
863 850 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
864 851
865 852 ndr_rpc_release(lsa_handle);
866 853 return (status);
867 854 }
868 855
869 856 /*
870 857 * lsar_lookup_sids3
871 858 *
872 859 * This function is only valid if the remote RPC server is a domain
873 860 * controller and requires the security extensions defined in MS-RPCE.
874 861 *
875 862 * Domain controllers will return RPC_NT_PROTSEQ_NOT_SUPPORTED here
876 863 * because we don't support the RPC_C_AUTHN_NETLOGON security provider.
877 864 * Non-domain controllers will return NT_STATUS_INVALID_SERVER_STATE.
878 865 */
879 866 static uint32_t /*LINTED E_STATIC_UNUSED*/
880 867 lsar_lookup_sids3(mlsvc_handle_t *lsa_handle, lsa_sid_t *sid,
881 868 smb_account_t *account)
882 869 {
883 870 struct lsar_lookup_sids3 arg;
884 871 lsar_translated_name_ex_t *name_entry;
885 872 struct mslsa_lup_sid_entry sid_entry;
886 873 struct mslsa_domain_entry *domain_entry;
887 874 uint32_t status = NT_STATUS_SUCCESS;
888 875 char *name;
889 876 int opnum = LSARPC_OPNUM_LookupSids3;
890 877
891 878 bzero(&arg, sizeof (struct lsar_lookup_sids3));
892 879
893 880 sid_entry.psid = sid;
894 881 arg.lup_sid_table.n_entry = 1;
895 882 arg.lup_sid_table.entries = &sid_entry;
896 883 arg.lookup_level = LSA_LOOKUP_WKSTA;
897 884 arg.client_revision = LSA_CLIENT_REVISION_AD;
898 885
899 886 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
900 887 ndr_rpc_release(lsa_handle);
901 888 return (NT_STATUS_INVALID_PARAMETER);
902 889 }
903 890
904 891 if (arg.status != NT_STATUS_SUCCESS) {
905 892 ndr_rpc_status(lsa_handle, opnum, arg.status);
906 893 ndr_rpc_release(lsa_handle);
907 894 if (arg.status == RPC_NT_PROTSEQ_NOT_SUPPORTED ||
908 895 arg.status == NT_STATUS_INVALID_SERVER_STATE)
909 896 return (NT_STATUS_INVALID_PARAMETER);
910 897 return (NT_SC_VALUE(arg.status));
911 898 }
912 899
913 900 if (arg.mapped_count == 0) {
914 901 ndr_rpc_release(lsa_handle);
915 902 return (NT_STATUS_NONE_MAPPED);
916 903 }
917 904
918 905 name_entry = &arg.name_table.entries[0];
919 906 if (name_entry->domain_ix != 0) {
920 907 ndr_rpc_release(lsa_handle);
921 908 return (NT_STATUS_NONE_MAPPED);
922 909 }
923 910
924 911 name = (char *)name_entry->name.str;
925 912 account->a_name = (name) ? strdup(name) : strdup("");
926 913 account->a_type = name_entry->sid_name_use;
927 914 account->a_sid = smb_sid_dup((smb_sid_t *)sid);
928 915 (void) smb_sid_getrid(account->a_sid, &account->a_rid);
929 916
930 917 domain_entry = &arg.domain_table->entries[0];
931 918 if ((name = (char *)domain_entry->domain_name.str) != NULL)
932 919 account->a_domain = strdup(name);
933 920 account->a_domsid = smb_sid_dup((smb_sid_t *)domain_entry->domain_sid);
934 921
935 922 ndr_rpc_release(lsa_handle);
936 923 return (status);
937 924 }
938 925
939 926 /*
940 927 * lsar_enum_accounts
941 928 *
942 929 * Enumerate the list of accounts (i.e. SIDs). Use the handle returned
943 930 * from lsa_open_policy2. The enum_context is used to support multiple
944 931 * calls to this enumeration function. It should be set to 0 on the
945 932 * first call. It will be updated by the domain controller and should
946 933 * simply be passed unchanged to subsequent calls until there are no
947 934 * more accounts. A warning status of 0x1A indicates that no more data
948 935 * is available. The list of accounts will be returned in accounts.
949 936 * This list is dynamically allocated using malloc, it should be freed
950 937 * by the caller when it is no longer required.
951 938 */
952 939 DWORD
953 940 lsar_enum_accounts(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
954 941 struct mslsa_EnumAccountBuf *accounts)
955 942 {
956 943 struct mslsa_EnumerateAccounts arg;
957 944 struct mslsa_AccountInfo *info;
958 945 int opnum;
959 946 int rc;
960 947 DWORD status;
961 948 DWORD n_entries;
962 949 DWORD i;
963 950 int nbytes;
964 951
965 952 if (lsa_handle == NULL || enum_context == NULL || accounts == NULL)
966 953 return (NT_STATUS_INTERNAL_ERROR);
967 954
968 955 accounts->entries_read = 0;
969 956 accounts->info = 0;
970 957
971 958 opnum = LSARPC_OPNUM_EnumerateAccounts;
972 959
973 960 bzero(&arg, sizeof (struct mslsa_EnumerateAccounts));
974 961 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
975 962 arg.enum_context = *enum_context;
976 963 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
977 964
978 965 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
979 966 if (rc == 0) {
980 967 status = arg.status;
981 968 if (arg.status != 0) {
982 969 if (arg.status == NT_STATUS_NO_MORE_ENTRIES) {
983 970 *enum_context = arg.enum_context;
984 971 } else {
985 972 ndr_rpc_status(lsa_handle, opnum, arg.status);
986 973 }
987 974 } else if (arg.enum_buf->entries_read != 0) {
988 975 n_entries = arg.enum_buf->entries_read;
989 976 nbytes = n_entries * sizeof (struct mslsa_AccountInfo);
990 977
991 978 if ((info = malloc(nbytes)) == NULL) {
992 979 ndr_rpc_release(lsa_handle);
993 980 return (NT_STATUS_NO_MEMORY);
994 981 }
995 982
996 983 for (i = 0; i < n_entries; ++i)
997 984 info[i].sid = (lsa_sid_t *)smb_sid_dup(
998 985 (smb_sid_t *)arg.enum_buf->info[i].sid);
999 986
1000 987 accounts->entries_read = n_entries;
1001 988 accounts->info = info;
1002 989 *enum_context = arg.enum_context;
1003 990 }
1004 991 } else {
1005 992 status = NT_STATUS_INVALID_PARAMETER;
1006 993 }
1007 994
1008 995 ndr_rpc_release(lsa_handle);
1009 996 return (status);
1010 997 }
1011 998
1012 999 /*
1013 1000 * lsar_enum_trusted_domains
1014 1001 *
1015 1002 * Enumerate the list of trusted domains. Use the handle returned from
1016 1003 * lsa_open_policy2. The enum_context is used to support multiple calls
1017 1004 * to this enumeration function. It should be set to 0 on the first
1018 1005 * call. It will be updated by the domain controller and should simply
1019 1006 * be passed unchanged to subsequent calls until there are no more
1020 1007 * domains.
1021 1008 *
1022 1009 * The trusted domains aren't actually returned here. They are added
1023 1010 * to the NT domain database. After all of the trusted domains have
1024 1011 * been discovered, the database can be interrogated to find all of
1025 1012 * the trusted domains.
1026 1013 */
1027 1014 DWORD
1028 1015 lsar_enum_trusted_domains(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1029 1016 smb_trusted_domains_t *list)
1030 1017 {
1031 1018 struct mslsa_EnumTrustedDomain arg;
1032 1019 int opnum;
1033 1020 DWORD status;
1034 1021
1035 1022 if (list == NULL)
1036 1023 return (NT_STATUS_INVALID_PARAMETER);
1037 1024
1038 1025 opnum = LSARPC_OPNUM_EnumTrustedDomain;
1039 1026
1040 1027 bzero(list, sizeof (smb_trusted_domains_t));
1041 1028 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomain));
1042 1029 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1043 1030 arg.enum_context = *enum_context;
1044 1031 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1045 1032
1046 1033 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1047 1034 status = NT_STATUS_INVALID_PARAMETER;
1048 1035 } else if (arg.status != 0) {
1049 1036 *enum_context = arg.enum_context;
1050 1037 status = NT_SC_VALUE(arg.status);
1051 1038
1052 1039 /*
1053 1040 * STATUS_NO_MORE_ENTRIES provides call
1054 1041 * status but does not indicate an error.
1055 1042 */
1056 1043 if (status != NT_STATUS_NO_MORE_ENTRIES)
1057 1044 ndr_rpc_status(lsa_handle, opnum, arg.status);
1058 1045 } else if (arg.enum_buf->entries_read == 0) {
1059 1046 *enum_context = arg.enum_context;
1060 1047 status = 0;
1061 1048 } else {
1062 1049 lsar_set_trusted_domains(arg.enum_buf, list);
1063 1050 *enum_context = arg.enum_context;
1064 1051 status = 0;
1065 1052 }
1066 1053
1067 1054 ndr_rpc_release(lsa_handle);
1068 1055 return (status);
1069 1056 }
1070 1057
1071 1058 DWORD
1072 1059 lsar_enum_trusted_domains_ex(mlsvc_handle_t *lsa_handle, DWORD *enum_context,
1073 1060 smb_trusted_domains_t *list)
1074 1061 {
1075 1062 struct mslsa_EnumTrustedDomainEx arg;
1076 1063 int opnum;
1077 1064 DWORD status;
1078 1065
1079 1066 if (list == NULL)
1080 1067 return (NT_STATUS_INVALID_PARAMETER);
1081 1068
1082 1069 opnum = LSARPC_OPNUM_EnumTrustedDomainsEx;
1083 1070
1084 1071 bzero(list, sizeof (smb_trusted_domains_t));
1085 1072 bzero(&arg, sizeof (struct mslsa_EnumTrustedDomainEx));
1086 1073 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1087 1074 arg.enum_context = *enum_context;
1088 1075 arg.max_length = MLSVC_MAX_RESPONSE_LEN;
1089 1076
1090 1077 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0) {
1091 1078 status = NT_STATUS_INVALID_PARAMETER;
1092 1079 } else if (arg.status != 0) {
1093 1080 *enum_context = arg.enum_context;
1094 1081 status = NT_SC_VALUE(arg.status);
1095 1082
1096 1083 /*
1097 1084 * STATUS_NO_MORE_ENTRIES provides call
1098 1085 * status but does not indicate an error.
1099 1086 */
1100 1087 if (status != NT_STATUS_NO_MORE_ENTRIES)
1101 1088 ndr_rpc_status(lsa_handle, opnum, arg.status);
1102 1089 } else if (arg.enum_buf->entries_read == 0) {
1103 1090 *enum_context = arg.enum_context;
1104 1091 status = 0;
1105 1092 } else {
1106 1093 lsar_set_trusted_domains_ex(arg.enum_buf, list);
1107 1094 *enum_context = arg.enum_context;
1108 1095 status = 0;
1109 1096 }
1110 1097
1111 1098 ndr_rpc_release(lsa_handle);
1112 1099 return (status);
1113 1100 }
1114 1101
1115 1102 /*
1116 1103 * lsar_enum_privs_account
1117 1104 *
1118 1105 * Privileges enum? Need an account handle.
1119 1106 */
1120 1107 /*ARGSUSED*/
1121 1108 int
1122 1109 lsar_enum_privs_account(mlsvc_handle_t *account_handle, smb_account_t *account)
1123 1110 {
1124 1111 struct mslsa_EnumPrivsAccount arg;
1125 1112 int opnum;
1126 1113 int rc;
1127 1114
1128 1115 opnum = LSARPC_OPNUM_EnumPrivsAccount;
1129 1116
1130 1117 bzero(&arg, sizeof (struct mslsa_EnumPrivsAccount));
1131 1118 (void) memcpy(&arg.account_handle, &account_handle->handle,
1132 1119 sizeof (mslsa_handle_t));
1133 1120
1134 1121 rc = ndr_rpc_call(account_handle, opnum, &arg);
1135 1122 if ((rc == 0) && (arg.status != 0)) {
1136 1123 ndr_rpc_status(account_handle, opnum, arg.status);
1137 1124 rc = -1;
1138 1125 }
1139 1126 ndr_rpc_release(account_handle);
1140 1127 return (rc);
1141 1128 }
1142 1129
1143 1130 /*
1144 1131 * lsar_lookup_priv_value
1145 1132 *
1146 1133 * Map a privilege name to a local unique id (LUID). Privilege names
1147 1134 * are consistent across the network. LUIDs are machine specific.
1148 1135 * This function provides the means to map a privilege name to the
1149 1136 * LUID used by a remote server to represent it. The handle here is
1150 1137 * a policy handle.
1151 1138 */
1152 1139 int
1153 1140 lsar_lookup_priv_value(mlsvc_handle_t *lsa_handle, char *name,
1154 1141 struct ms_luid *luid)
1155 1142 {
1156 1143 struct mslsa_LookupPrivValue arg;
1157 1144 int opnum;
1158 1145 int rc;
1159 1146 size_t length;
↓ open down ↓ |
417 lines elided |
↑ open up ↑ |
1160 1147
1161 1148 if (lsa_handle == NULL || name == NULL || luid == NULL)
1162 1149 return (-1);
1163 1150
1164 1151 opnum = LSARPC_OPNUM_LookupPrivValue;
1165 1152
1166 1153 bzero(&arg, sizeof (struct mslsa_LookupPrivValue));
1167 1154 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1168 1155
1169 1156 length = smb_wcequiv_strlen(name);
1170 - if (ndr_rpc_server_os(lsa_handle) == NATIVE_OS_WIN2000)
1171 - length += sizeof (smb_wchar_t);
1157 + length += sizeof (smb_wchar_t);
1172 1158
1173 1159 arg.name.length = length;
1174 1160 arg.name.allosize = length;
1175 1161 arg.name.str = (unsigned char *)name;
1176 1162
1177 1163 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1178 1164 if (rc == 0) {
1179 1165 if (arg.status != 0)
1180 1166 rc = -1;
1181 1167 else
1182 1168 (void) memcpy(luid, &arg.luid, sizeof (struct ms_luid));
1183 1169 }
1184 1170
1185 1171 ndr_rpc_release(lsa_handle);
1186 1172 return (rc);
1187 1173 }
1188 1174
1189 1175 /*
1190 1176 * lsar_lookup_priv_name
1191 1177 *
1192 1178 * Map a local unique id (LUID) to a privilege name. Privilege names
1193 1179 * are consistent across the network. LUIDs are machine specific.
1194 1180 * This function the means to map the LUID used by a remote server to
1195 1181 * the appropriate privilege name. The handle here is a policy handle.
1196 1182 */
1197 1183 int
1198 1184 lsar_lookup_priv_name(mlsvc_handle_t *lsa_handle, struct ms_luid *luid,
1199 1185 char *name, int namelen)
1200 1186 {
1201 1187 struct mslsa_LookupPrivName arg;
1202 1188 int opnum;
1203 1189 int rc;
1204 1190
1205 1191 if (lsa_handle == NULL || luid == NULL || name == NULL)
1206 1192 return (-1);
1207 1193
1208 1194 opnum = LSARPC_OPNUM_LookupPrivName;
1209 1195
1210 1196 bzero(&arg, sizeof (struct mslsa_LookupPrivName));
1211 1197 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1212 1198 (void) memcpy(&arg.luid, luid, sizeof (struct ms_luid));
1213 1199
1214 1200 rc = ndr_rpc_call(lsa_handle, opnum, &arg);
1215 1201 if (rc == 0) {
1216 1202 if (arg.status != 0)
1217 1203 rc = -1;
1218 1204 else
1219 1205 (void) strlcpy(name, (char const *)arg.name->str,
1220 1206 namelen);
1221 1207 }
1222 1208
1223 1209 ndr_rpc_release(lsa_handle);
1224 1210 return (rc);
1225 1211 }
1226 1212
1227 1213 /*
1228 1214 * lsar_lookup_priv_display_name
1229 1215 *
1230 1216 * Map a privilege name to a privilege display name. The input handle
1231 1217 * should be an LSA policy handle and the name would normally be one
1232 1218 * of the privileges defined in smb_privilege.h
1233 1219 *
1234 1220 * There's something peculiar about the return status from NT servers,
1235 1221 * it's not always present. So for now, I'm ignoring the status in the
1236 1222 * RPC response.
1237 1223 *
1238 1224 * Returns NT status codes.
1239 1225 */
1240 1226 DWORD
1241 1227 lsar_lookup_priv_display_name(mlsvc_handle_t *lsa_handle, char *name,
1242 1228 char *display_name, int display_len)
1243 1229 {
1244 1230 struct mslsa_LookupPrivDisplayName arg;
1245 1231 int opnum;
1246 1232 size_t length;
1247 1233 DWORD status;
1248 1234
1249 1235 if (lsa_handle == NULL || name == NULL || display_name == NULL)
1250 1236 return (NT_STATUS_INVALID_PARAMETER);
1251 1237
1252 1238 opnum = LSARPC_OPNUM_LookupPrivDisplayName;
1253 1239
1254 1240 bzero(&arg, sizeof (struct mslsa_LookupPrivDisplayName));
1255 1241 (void) memcpy(&arg.handle, lsa_handle, sizeof (mslsa_handle_t));
1256 1242
1257 1243 length = smb_wcequiv_strlen(name);
1258 1244 arg.name.length = length;
1259 1245 arg.name.allosize = length;
1260 1246 arg.name.str = (unsigned char *)name;
1261 1247
1262 1248 arg.client_language = MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US);
1263 1249 arg.default_language = MAKELANGID(LANG_ENGLISH, SUBLANG_NEUTRAL);
1264 1250
1265 1251 if (ndr_rpc_call(lsa_handle, opnum, &arg) != 0)
1266 1252 status = NT_STATUS_INVALID_PARAMETER;
1267 1253 #if 0
1268 1254 else if (arg.status != 0)
1269 1255 status = NT_SC_VALUE(arg.status);
1270 1256 #endif
1271 1257 else {
1272 1258 (void) strlcpy(display_name,
1273 1259 (char const *)arg.display_name->str, display_len);
1274 1260 status = NT_STATUS_SUCCESS;
1275 1261 }
1276 1262
1277 1263 ndr_rpc_release(lsa_handle);
1278 1264 return (status);
1279 1265 }
1280 1266
1281 1267 static void
1282 1268 lsar_set_trusted_domains_ex(struct mslsa_EnumTrustedDomainBufEx *enum_buf,
1283 1269 smb_trusted_domains_t *list)
1284 1270 {
1285 1271 char sidstr[SMB_SID_STRSZ];
1286 1272 int i;
1287 1273
1288 1274 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1289 1275 return;
1290 1276
1291 1277 list->td_num = 0;
1292 1278 list->td_domains = calloc(enum_buf->entries_read,
1293 1279 sizeof (smb_domain_t));
1294 1280
1295 1281 if (list->td_domains == NULL)
1296 1282 return;
1297 1283
1298 1284 list->td_num = enum_buf->entries_read;
1299 1285 for (i = 0; i < list->td_num; i++) {
1300 1286 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1301 1287 smb_domain_set_trust_info(
1302 1288 sidstr,
1303 1289 (char *)enum_buf->info[i].nb_name.str,
1304 1290 (char *)enum_buf->info[i].dns_name.str,
1305 1291 enum_buf->info[i].trust_direction,
1306 1292 enum_buf->info[i].trust_type,
1307 1293 enum_buf->info[i].trust_attrs,
1308 1294 &list->td_domains[i]);
1309 1295 }
1310 1296 }
1311 1297
1312 1298 static void
1313 1299 lsar_set_trusted_domains(struct mslsa_EnumTrustedDomainBuf *enum_buf,
1314 1300 smb_trusted_domains_t *list)
1315 1301 {
1316 1302 char sidstr[SMB_SID_STRSZ];
1317 1303 int i;
1318 1304
1319 1305 if (list == NULL || enum_buf == NULL || enum_buf->entries_read == 0)
1320 1306 return;
1321 1307
1322 1308 list->td_num = 0;
1323 1309 list->td_domains = calloc(enum_buf->entries_read,
1324 1310 sizeof (smb_domain_t));
1325 1311
1326 1312 if (list->td_domains == NULL)
1327 1313 return;
1328 1314
1329 1315 list->td_num = enum_buf->entries_read;
1330 1316 for (i = 0; i < list->td_num; i++) {
1331 1317 smb_sid_tostr((smb_sid_t *)enum_buf->info[i].sid, sidstr);
1332 1318 smb_domain_set_trust_info(
1333 1319 sidstr, (char *)enum_buf->info[i].name.str,
1334 1320 "", 0, 0, 0, &list->td_domains[i]);
1335 1321 }
1336 1322 }
1337 1323
1338 1324 static void
1339 1325 smb_account_trace(const smb_account_t *info)
1340 1326 {
1341 1327 char sidbuf[SMB_SID_STRSZ];
1342 1328
1343 1329 bzero(sidbuf, SMB_SID_STRSZ);
1344 1330 smb_sid_tostr(info->a_sid, sidbuf);
1345 1331
1346 1332 smb_tracef("%s %s %s %lu %s", info->a_domain, info->a_name,
1347 1333 sidbuf, info->a_rid, smb_sid_type2str(info->a_type));
1348 1334 }
↓ open down ↓ |
167 lines elided |
↑ open up ↑ |
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX