1/* 2 * Unix SMB/CIFS implementation. 3 * RPC Pipe client / server routines 4 * Copyright (C) Andrew Tridgell 1992-2000, 5 * Copyright (C) Jean Fran�ois Micouleau 1998-2001. 6 * Copyright (C) Volker Lendecke 2006. 7 * Copyright (C) Gerald Carter 2006. 8 * 9 * This program is free software; you can redistribute it and/or modify 10 * it under the terms of the GNU General Public License as published by 11 * the Free Software Foundation; either version 2 of the License, or 12 * (at your option) any later version. 13 * 14 * This program is distributed in the hope that it will be useful, 15 * but WITHOUT ANY WARRANTY; without even the implied warranty of 16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 17 * GNU General Public License for more details. 18 * 19 * You should have received a copy of the GNU General Public License 20 * along with this program; if not, write to the Free Software 21 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 22 */ 23 24#include "includes.h" 25#include "groupdb/mapping.h" 26 27/**************************************************************************** 28initialise first time the mapping list 29****************************************************************************/ 30NTSTATUS add_initial_entry(gid_t gid, const char *sid, enum lsa_SidType sid_name_use, const char *nt_name, const char *comment) 31{ 32 GROUP_MAP map; 33 34 if(!init_group_mapping()) { 35 DEBUG(0,("failed to initialize group mapping\n")); 36 return NT_STATUS_UNSUCCESSFUL; 37 } 38 39 map.gid=gid; 40 if (!string_to_sid(&map.sid, sid)) { 41 DEBUG(0, ("string_to_sid failed: %s", sid)); 42 return NT_STATUS_UNSUCCESSFUL; 43 } 44 45 map.sid_name_use=sid_name_use; 46 fstrcpy(map.nt_name, nt_name); 47 fstrcpy(map.comment, comment); 48 49 return pdb_add_group_mapping_entry(&map); 50} 51 52/**************************************************************************** 53 Map a unix group to a newly created mapping 54****************************************************************************/ 55NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap) 56{ 57 NTSTATUS status; 58 GROUP_MAP map; 59 const char *grpname, *dom, *name; 60 uint32 rid; 61 62 if (pdb_getgrgid(&map, grp->gr_gid)) { 63 return NT_STATUS_GROUP_EXISTS; 64 } 65 66 map.gid = grp->gr_gid; 67 grpname = grp->gr_name; 68 69 if (lookup_name(tmp_talloc_ctx(), grpname, LOOKUP_NAME_ISOLATED, 70 &dom, &name, NULL, NULL)) { 71 72 const char *tmp = talloc_asprintf( 73 tmp_talloc_ctx(), "Unix Group %s", grp->gr_name); 74 75 DEBUG(5, ("%s exists as %s\\%s, retrying as \"%s\"\n", 76 grpname, dom, name, tmp)); 77 grpname = tmp; 78 } 79 80 if (lookup_name(tmp_talloc_ctx(), grpname, LOOKUP_NAME_ISOLATED, 81 NULL, NULL, NULL, NULL)) { 82 DEBUG(3, ("\"%s\" exists, can't map it\n", grp->gr_name)); 83 return NT_STATUS_GROUP_EXISTS; 84 } 85 86 fstrcpy(map.nt_name, grpname); 87 88 if (pdb_rid_algorithm()) { 89 rid = algorithmic_pdb_gid_to_group_rid( grp->gr_gid ); 90 } else { 91 if (!pdb_new_rid(&rid)) { 92 DEBUG(3, ("Could not get a new RID for %s\n", 93 grp->gr_name)); 94 return NT_STATUS_ACCESS_DENIED; 95 } 96 } 97 98 sid_compose(&map.sid, get_global_sam_sid(), rid); 99 map.sid_name_use = SID_NAME_DOM_GRP; 100 fstrcpy(map.comment, talloc_asprintf(tmp_talloc_ctx(), "Unix Group %s", 101 grp->gr_name)); 102 103 status = pdb_add_group_mapping_entry(&map); 104 if (NT_STATUS_IS_OK(status)) { 105 *pmap = map; 106 } 107 return status; 108} 109 110 111 112 113 114 115 116static NTSTATUS alias_memberships(const DOM_SID *members, size_t num_members, 117 DOM_SID **sids, size_t *num) 118{ 119 size_t i; 120 121 *num = 0; 122 *sids = NULL; 123 124 for (i=0; i<num_members; i++) { 125 NTSTATUS status = one_alias_membership(&members[i], sids, num); 126 if (!NT_STATUS_IS_OK(status)) 127 return status; 128 } 129 return NT_STATUS_OK; 130} 131 132struct aliasmem_closure { 133 const DOM_SID *alias; 134 DOM_SID **sids; 135 size_t *num; 136}; 137 138 139 140/* 141 * 142 * High level functions 143 * better to use them than the lower ones. 144 * 145 * we are checking if the group is in the mapping file 146 * and if the group is an existing unix group 147 * 148 */ 149 150/* get a domain group from it's SID */ 151 152BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map) 153{ 154 struct group *grp; 155 BOOL ret; 156 157 if(!init_group_mapping()) { 158 DEBUG(0,("failed to initialize group mapping\n")); 159 return(False); 160 } 161 162 DEBUG(10, ("get_domain_group_from_sid\n")); 163 164 /* if the group is NOT in the database, it CAN NOT be a domain group */ 165 166 become_root(); 167 ret = pdb_getgrsid(map, sid); 168 unbecome_root(); 169 170 /* special case check for rid 513 */ 171 172 if ( !ret ) { 173 uint32 rid; 174 175 sid_peek_rid( &sid, &rid ); 176 177 if ( rid == DOMAIN_GROUP_RID_USERS ) { 178 fstrcpy( map->nt_name, "None" ); 179 fstrcpy( map->comment, "Ordinary Users" ); 180 sid_copy( &map->sid, &sid ); 181 map->sid_name_use = SID_NAME_DOM_GRP; 182 183 return True; 184 } 185 186 return False; 187 } 188 189 DEBUG(10, ("get_domain_group_from_sid: SID found in the TDB\n")); 190 191 /* if it's not a domain group, continue */ 192 if (map->sid_name_use!=SID_NAME_DOM_GRP) { 193 return False; 194 } 195 196 DEBUG(10, ("get_domain_group_from_sid: SID is a domain group\n")); 197 198 if (map->gid==-1) { 199 return False; 200 } 201 202 DEBUG(10, ("get_domain_group_from_sid: SID is mapped to gid:%lu\n",(unsigned long)map->gid)); 203 204 grp = getgrgid(map->gid); 205 if ( !grp ) { 206 DEBUG(10, ("get_domain_group_from_sid: gid DOESN'T exist in UNIX security\n")); 207 return False; 208 } 209 210 DEBUG(10, ("get_domain_group_from_sid: gid exists in UNIX security\n")); 211 212 return True; 213} 214 215/**************************************************************************** 216 Create a UNIX group on demand. 217****************************************************************************/ 218 219int smb_create_group(const char *unix_group, gid_t *new_gid) 220{ 221 pstring add_script; 222 int ret = -1; 223 int fd = 0; 224 225 *new_gid = 0; 226 227 /* defer to scripts */ 228 229 if ( *lp_addgroup_script() ) { 230 pstrcpy(add_script, lp_addgroup_script()); 231 pstring_sub(add_script, "%g", unix_group); 232 ret = smbrun(add_script, &fd); 233 DEBUG(ret ? 0 : 3,("smb_create_group: Running the command `%s' gave %d\n",add_script,ret)); 234 if (ret == 0) { 235 smb_nscd_flush_group_cache(); 236 } 237 if (ret != 0) 238 return ret; 239 240 if (fd != 0) { 241 fstring output; 242 243 *new_gid = 0; 244 if (read(fd, output, sizeof(output)) > 0) { 245 *new_gid = (gid_t)strtoul(output, NULL, 10); 246 } 247 248 close(fd); 249 } 250 251 } 252 253 if (*new_gid == 0) { 254 struct group *grp = getgrnam(unix_group); 255 256 if (grp != NULL) 257 *new_gid = grp->gr_gid; 258 } 259 260 return ret; 261} 262 263/**************************************************************************** 264 Delete a UNIX group on demand. 265****************************************************************************/ 266 267int smb_delete_group(const char *unix_group) 268{ 269 pstring del_script; 270 int ret; 271 272 /* defer to scripts */ 273 274 if ( *lp_delgroup_script() ) { 275 pstrcpy(del_script, lp_delgroup_script()); 276 pstring_sub(del_script, "%g", unix_group); 277 ret = smbrun(del_script,NULL); 278 DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret)); 279 if (ret == 0) { 280 smb_nscd_flush_group_cache(); 281 } 282 return ret; 283 } 284 285 return -1; 286} 287 288/**************************************************************************** 289 Set a user's primary UNIX group. 290****************************************************************************/ 291int smb_set_primary_group(const char *unix_group, const char* unix_user) 292{ 293 pstring add_script; 294 int ret; 295 296 /* defer to scripts */ 297 298 if ( *lp_setprimarygroup_script() ) { 299 pstrcpy(add_script, lp_setprimarygroup_script()); 300 all_string_sub(add_script, "%g", unix_group, sizeof(add_script)); 301 all_string_sub(add_script, "%u", unix_user, sizeof(add_script)); 302 ret = smbrun(add_script,NULL); 303 flush_pwnam_cache(); 304 DEBUG(ret ? 0 : 3,("smb_set_primary_group: " 305 "Running the command `%s' gave %d\n",add_script,ret)); 306 if (ret == 0) { 307 smb_nscd_flush_group_cache(); 308 } 309 return ret; 310 } 311 312 return -1; 313} 314 315/**************************************************************************** 316 Add a user to a UNIX group. 317****************************************************************************/ 318 319int smb_add_user_group(const char *unix_group, const char *unix_user) 320{ 321 pstring add_script; 322 int ret; 323 324 /* defer to scripts */ 325 326 if ( *lp_addusertogroup_script() ) { 327 pstrcpy(add_script, lp_addusertogroup_script()); 328 pstring_sub(add_script, "%g", unix_group); 329 pstring_sub(add_script, "%u", unix_user); 330 ret = smbrun(add_script,NULL); 331 DEBUG(ret ? 0 : 3,("smb_add_user_group: Running the command `%s' gave %d\n",add_script,ret)); 332 if (ret == 0) { 333 smb_nscd_flush_group_cache(); 334 } 335 return ret; 336 } 337 338 return -1; 339} 340 341/**************************************************************************** 342 Delete a user from a UNIX group 343****************************************************************************/ 344 345int smb_delete_user_group(const char *unix_group, const char *unix_user) 346{ 347 pstring del_script; 348 int ret; 349 350 /* defer to scripts */ 351 352 if ( *lp_deluserfromgroup_script() ) { 353 pstrcpy(del_script, lp_deluserfromgroup_script()); 354 pstring_sub(del_script, "%g", unix_group); 355 pstring_sub(del_script, "%u", unix_user); 356 ret = smbrun(del_script,NULL); 357 DEBUG(ret ? 0 : 3,("smb_delete_user_group: Running the command `%s' gave %d\n",del_script,ret)); 358 if (ret == 0) { 359 smb_nscd_flush_group_cache(); 360 } 361 return ret; 362 } 363 364 return -1; 365} 366 367 368NTSTATUS pdb_default_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, 369 DOM_SID sid) 370{ 371 return get_group_map_from_sid(sid, map) ? 372 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 373} 374 375NTSTATUS pdb_default_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, 376 gid_t gid) 377{ 378 return get_group_map_from_gid(gid, map) ? 379 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 380} 381 382NTSTATUS pdb_default_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, 383 const char *name) 384{ 385 return get_group_map_from_ntname(name, map) ? 386 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 387} 388 389NTSTATUS pdb_default_add_group_mapping_entry(struct pdb_methods *methods, 390 GROUP_MAP *map) 391{ 392 return add_mapping_entry(map, TDB_INSERT) ? 393 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 394} 395 396NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods, 397 GROUP_MAP *map) 398{ 399 return add_mapping_entry(map, TDB_REPLACE) ? 400 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 401} 402 403NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods, 404 DOM_SID sid) 405{ 406 return group_map_remove(&sid) ? 407 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 408} 409 410NTSTATUS pdb_default_enum_group_mapping(struct pdb_methods *methods, 411 const DOM_SID *sid, enum lsa_SidType sid_name_use, 412 GROUP_MAP **pp_rmap, size_t *p_num_entries, 413 BOOL unix_only) 414{ 415 return enum_group_mapping(sid, sid_name_use, pp_rmap, p_num_entries, unix_only) ? 416 NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; 417} 418 419NTSTATUS pdb_default_find_alias(struct pdb_methods *methods, 420 const char *name, DOM_SID *sid) 421{ 422 GROUP_MAP map; 423 424 if (!pdb_getgrnam(&map, name)) 425 return NT_STATUS_NO_SUCH_ALIAS; 426 427 if ((map.sid_name_use != SID_NAME_WKN_GRP) && 428 (map.sid_name_use != SID_NAME_ALIAS)) 429 return NT_STATUS_OBJECT_TYPE_MISMATCH; 430 431 sid_copy(sid, &map.sid); 432 return NT_STATUS_OK; 433} 434 435NTSTATUS pdb_default_create_alias(struct pdb_methods *methods, 436 const char *name, uint32 *rid) 437{ 438 DOM_SID sid; 439 enum lsa_SidType type; 440 uint32 new_rid; 441 gid_t gid; 442 BOOL exists; 443 GROUP_MAP map; 444 TALLOC_CTX *mem_ctx; 445 NTSTATUS status; 446 447 DEBUG(10, ("Trying to create alias %s\n", name)); 448 449 mem_ctx = talloc_new(NULL); 450 if (mem_ctx == NULL) { 451 return NT_STATUS_NO_MEMORY; 452 } 453 454 exists = lookup_name(mem_ctx, name, LOOKUP_NAME_ISOLATED, 455 NULL, NULL, &sid, &type); 456 TALLOC_FREE(mem_ctx); 457 458 if (exists) { 459 return NT_STATUS_ALIAS_EXISTS; 460 } 461 462 if (!winbind_allocate_gid(&gid)) { 463 DEBUG(3, ("Could not get a gid out of winbind\n")); 464 return NT_STATUS_ACCESS_DENIED; 465 } 466 467 if (!pdb_new_rid(&new_rid)) { 468 DEBUG(0, ("Could not allocate a RID -- wasted a gid :-(\n")); 469 return NT_STATUS_ACCESS_DENIED; 470 } 471 472 DEBUG(10, ("Creating alias %s with gid %d and rid %d\n", 473 name, gid, new_rid)); 474 475 sid_copy(&sid, get_global_sam_sid()); 476 sid_append_rid(&sid, new_rid); 477 478 map.gid = gid; 479 sid_copy(&map.sid, &sid); 480 map.sid_name_use = SID_NAME_ALIAS; 481 fstrcpy(map.nt_name, name); 482 fstrcpy(map.comment, ""); 483 484 status = pdb_add_group_mapping_entry(&map); 485 486 if (!NT_STATUS_IS_OK(status)) { 487 DEBUG(0, ("Could not add group mapping entry for alias %s " 488 "(%s)\n", name, nt_errstr(status))); 489 return status; 490 } 491 492 *rid = new_rid; 493 494 return NT_STATUS_OK; 495} 496 497NTSTATUS pdb_default_delete_alias(struct pdb_methods *methods, 498 const DOM_SID *sid) 499{ 500 return pdb_delete_group_mapping_entry(*sid); 501} 502 503NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods, 504 const DOM_SID *sid, 505 struct acct_info *info) 506{ 507 GROUP_MAP map; 508 509 if (!pdb_getgrsid(&map, *sid)) 510 return NT_STATUS_NO_SUCH_ALIAS; 511 512 if ((map.sid_name_use != SID_NAME_ALIAS) && 513 (map.sid_name_use != SID_NAME_WKN_GRP)) { 514 DEBUG(2, ("%s is a %s, expected an alias\n", 515 sid_string_static(sid), 516 sid_type_lookup(map.sid_name_use))); 517 return NT_STATUS_NO_SUCH_ALIAS; 518 } 519 520 fstrcpy(info->acct_name, map.nt_name); 521 fstrcpy(info->acct_desc, map.comment); 522 sid_peek_rid(&map.sid, &info->rid); 523 return NT_STATUS_OK; 524} 525 526NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods, 527 const DOM_SID *sid, 528 struct acct_info *info) 529{ 530 GROUP_MAP map; 531 532 if (!pdb_getgrsid(&map, *sid)) 533 return NT_STATUS_NO_SUCH_ALIAS; 534 535 fstrcpy(map.nt_name, info->acct_name); 536 fstrcpy(map.comment, info->acct_desc); 537 538 return pdb_update_group_mapping_entry(&map); 539} 540 541NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods, 542 const DOM_SID *alias, const DOM_SID *member) 543{ 544 return add_aliasmem(alias, member); 545} 546 547NTSTATUS pdb_default_del_aliasmem(struct pdb_methods *methods, 548 const DOM_SID *alias, const DOM_SID *member) 549{ 550 return del_aliasmem(alias, member); 551} 552 553NTSTATUS pdb_default_enum_aliasmem(struct pdb_methods *methods, 554 const DOM_SID *alias, DOM_SID **pp_members, 555 size_t *p_num_members) 556{ 557 return enum_aliasmem(alias, pp_members, p_num_members); 558} 559 560NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods, 561 TALLOC_CTX *mem_ctx, 562 const DOM_SID *domain_sid, 563 const DOM_SID *members, 564 size_t num_members, 565 uint32 **pp_alias_rids, 566 size_t *p_num_alias_rids) 567{ 568 DOM_SID *alias_sids; 569 size_t i, num_alias_sids; 570 NTSTATUS result; 571 572 alias_sids = NULL; 573 num_alias_sids = 0; 574 575 result = alias_memberships(members, num_members, 576 &alias_sids, &num_alias_sids); 577 578 if (!NT_STATUS_IS_OK(result)) 579 return result; 580 581 *p_num_alias_rids = 0; 582 583 if (num_alias_sids == 0) { 584 TALLOC_FREE(alias_sids); 585 return NT_STATUS_OK; 586 } 587 588 *pp_alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids); 589 if (*pp_alias_rids == NULL) 590 return NT_STATUS_NO_MEMORY; 591 592 for (i=0; i<num_alias_sids; i++) { 593 if (!sid_peek_check_rid(domain_sid, &alias_sids[i], 594 &(*pp_alias_rids)[*p_num_alias_rids])) 595 continue; 596 *p_num_alias_rids += 1; 597 } 598 599 TALLOC_FREE(alias_sids); 600 601 return NT_STATUS_OK; 602} 603 604/********************************************************************** 605 no ops for passdb backends that don't implement group mapping 606 *********************************************************************/ 607 608NTSTATUS pdb_nop_getgrsid(struct pdb_methods *methods, GROUP_MAP *map, 609 DOM_SID sid) 610{ 611 return NT_STATUS_UNSUCCESSFUL; 612} 613 614NTSTATUS pdb_nop_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, 615 gid_t gid) 616{ 617 return NT_STATUS_UNSUCCESSFUL; 618} 619 620NTSTATUS pdb_nop_getgrnam(struct pdb_methods *methods, GROUP_MAP *map, 621 const char *name) 622{ 623 return NT_STATUS_UNSUCCESSFUL; 624} 625 626NTSTATUS pdb_nop_add_group_mapping_entry(struct pdb_methods *methods, 627 GROUP_MAP *map) 628{ 629 return NT_STATUS_UNSUCCESSFUL; 630} 631 632NTSTATUS pdb_nop_update_group_mapping_entry(struct pdb_methods *methods, 633 GROUP_MAP *map) 634{ 635 return NT_STATUS_UNSUCCESSFUL; 636} 637 638NTSTATUS pdb_nop_delete_group_mapping_entry(struct pdb_methods *methods, 639 DOM_SID sid) 640{ 641 return NT_STATUS_UNSUCCESSFUL; 642} 643 644NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods, 645 enum lsa_SidType sid_name_use, 646 GROUP_MAP **rmap, size_t *num_entries, 647 BOOL unix_only) 648{ 649 return NT_STATUS_UNSUCCESSFUL; 650} 651 652/**************************************************************************** 653 These need to be redirected through pdb_interface.c 654****************************************************************************/ 655BOOL pdb_get_dom_grp_info(const DOM_SID *sid, struct acct_info *info) 656{ 657 GROUP_MAP map; 658 BOOL res; 659 660 become_root(); 661 res = get_domain_group_from_sid(*sid, &map); 662 unbecome_root(); 663 664 if (!res) 665 return False; 666 667 fstrcpy(info->acct_name, map.nt_name); 668 fstrcpy(info->acct_desc, map.comment); 669 sid_peek_rid(sid, &info->rid); 670 return True; 671} 672 673BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info) 674{ 675 GROUP_MAP map; 676 677 if (!get_domain_group_from_sid(*sid, &map)) 678 return False; 679 680 fstrcpy(map.nt_name, info->acct_name); 681 fstrcpy(map.comment, info->acct_desc); 682 683 return NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map)); 684} 685 686/******************************************************************** 687 Really just intended to be called by smbd 688********************************************************************/ 689 690NTSTATUS pdb_create_builtin_alias(uint32 rid) 691{ 692 DOM_SID sid; 693 enum lsa_SidType type; 694 gid_t gid; 695 GROUP_MAP map; 696 TALLOC_CTX *mem_ctx; 697 NTSTATUS status; 698 const char *name = NULL; 699 fstring groupname; 700 701 DEBUG(10, ("Trying to create builtin alias %d\n", rid)); 702 703 if ( !sid_compose( &sid, &global_sid_Builtin, rid ) ) { 704 return NT_STATUS_NO_SUCH_ALIAS; 705 } 706 707 if ( (mem_ctx = talloc_new(NULL)) == NULL ) { 708 return NT_STATUS_NO_MEMORY; 709 } 710 711 if ( !lookup_sid(mem_ctx, &sid, NULL, &name, &type) ) { 712 TALLOC_FREE( mem_ctx ); 713 return NT_STATUS_NO_SUCH_ALIAS; 714 } 715 716 /* validate RID so copy the name and move on */ 717 718 fstrcpy( groupname, name ); 719 TALLOC_FREE( mem_ctx ); 720 721 if (!winbind_allocate_gid(&gid)) { 722 DEBUG(3, ("pdb_create_builtin_alias: Could not get a gid out of winbind\n")); 723 return NT_STATUS_ACCESS_DENIED; 724 } 725 726 DEBUG(10,("Creating alias %s with gid %d\n", name, gid)); 727 728 map.gid = gid; 729 sid_copy(&map.sid, &sid); 730 map.sid_name_use = SID_NAME_ALIAS; 731 fstrcpy(map.nt_name, name); 732 fstrcpy(map.comment, ""); 733 734 status = pdb_add_group_mapping_entry(&map); 735 736 if (!NT_STATUS_IS_OK(status)) { 737 DEBUG(0, ("pdb_create_builtin_alias: Could not add group mapping entry for alias %d " 738 "(%s)\n", rid, nt_errstr(status))); 739 } 740 741 return status; 742} 743 744 745