1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 #include <stdlib.h> 29 #include <strings.h> 30 #include <unistd.h> 31 #include <syslog.h> 32 #include <thread.h> 33 #include <synch.h> 34 #include <grp.h> 35 #include <assert.h> 36 #include <libintl.h> 37 #include <smbsrv/libsmb.h> 38 #include <smb_sqlite.h> 39 40 /* 41 * Local domain SID (aka machine SID) is not stored in the domain table 42 * therefore the index is 0 43 */ 44 #define SMB_LGRP_LOCAL_IDX 0 45 #define SMB_LGRP_BUILTIN_IDX 1 46 47 #define SMB_LGRP_DB_NAME "/var/smb/smbgroup.db" 48 #define SMB_LGRP_DB_TIMEOUT 3000 /* in millisecond */ 49 #define SMB_LGRP_DB_VERMAJOR 1 50 #define SMB_LGRP_DB_VERMINOR 0 51 #define SMB_LGRP_DB_MAGIC 0x4C475250 /* LGRP */ 52 53 #define SMB_LGRP_DB_ORD 1 /* open read-only */ 54 #define SMB_LGRP_DB_ORW 2 /* open read/write */ 55 56 #define SMB_LGRP_DB_ADDMEMBER 1 57 #define SMB_LGRP_DB_DELMEMBER 2 58 59 /* 60 * members column of the groups table is an array of 61 * member structure smb_lgmid_t defined below. 62 * 63 * privs column of the groups table is an array of bytes 64 * where each byte is the id of an enable privilege 65 */ 66 #define SMB_LGRP_DB_SQL \ 67 "CREATE TABLE db_info (" \ 68 " ver_major INTEGER," \ 69 " ver_minor INTEGER," \ 70 " magic INTEGER" \ 71 ");" \ 72 "" \ 73 "CREATE TABLE domains (" \ 74 " dom_idx INTEGER PRIMARY KEY," \ 75 " dom_sid TEXT UNIQUE," \ 76 " dom_cnt INTEGER" \ 77 ");" \ 78 "" \ 79 "CREATE UNIQUE INDEX domsid_idx ON domains (dom_sid);" \ 80 "" \ 81 "CREATE TABLE groups (" \ 82 " name TEXT PRIMARY KEY," \ 83 " sid_idx INTEGER," \ 84 " sid_rid INTEGER," \ 85 " sid_type INTEGER," \ 86 " sid_attrs INTEGER," \ 87 " comment TEXT," \ 88 " n_privs INTEGER," \ 89 " privs BLOB," \ 90 " n_members INTEGER," \ 91 " members BLOB" \ 92 ");" \ 93 "" \ 94 "CREATE INDEX grprid_idx ON groups (sid_rid);" 95 96 /* 97 * Number of groups table columns 98 */ 99 #define SMB_LGRP_GTBL_NCOL 10 100 101 #define SMB_LGRP_GTBL_NAME 0 102 #define SMB_LGRP_GTBL_SIDIDX 1 103 #define SMB_LGRP_GTBL_SIDRID 2 104 #define SMB_LGRP_GTBL_SIDTYP 3 105 #define SMB_LGRP_GTBL_SIDATR 4 106 #define SMB_LGRP_GTBL_CMNT 5 107 #define SMB_LGRP_GTBL_NPRIVS 6 108 #define SMB_LGRP_GTBL_PRIVS 7 109 #define SMB_LGRP_GTBL_NMEMBS 8 110 #define SMB_LGRP_GTBL_MEMBS 9 111 112 #define SMB_LGRP_INFO_NONE 0x00 113 #define SMB_LGRP_INFO_NAME 0x01 114 #define SMB_LGRP_INFO_CMNT 0x02 115 #define SMB_LGRP_INFO_SID 0x04 116 #define SMB_LGRP_INFO_PRIV 0x08 117 #define SMB_LGRP_INFO_MEMB 0x10 118 #define SMB_LGRP_INFO_ALL 0x1F 119 120 #define NULL_MSGCHK(msg) ((msg) ? (msg) : "NULL") 121 122 /* Member ID */ 123 typedef struct smb_lgmid { 124 uint32_t m_idx; 125 uint32_t m_rid; 126 uint16_t m_type; 127 } smb_lgmid_t; 128 129 #define SMB_LGRP_MID_HEXSZ 32 130 131 /* Member list */ 132 typedef struct smb_lgmlist { 133 uint32_t m_cnt; 134 char *m_ids; 135 } smb_lgmlist_t; 136 137 /* Privilege ID */ 138 typedef uint8_t smb_lgpid_t; 139 140 /* Privilege list */ 141 typedef struct smb_lgplist { 142 uint32_t p_cnt; 143 smb_lgpid_t *p_ids; 144 } smb_lgplist_t; 145 146 static mutex_t smb_lgrp_lsid_mtx; 147 static nt_sid_t *smb_lgrp_lsid; 148 149 static int smb_lgrp_db_init(void); 150 static sqlite *smb_lgrp_db_open(int); 151 static void smb_lgrp_db_close(sqlite *); 152 static int smb_lgrp_db_setinfo(sqlite *); 153 154 static boolean_t smb_lgrp_gtbl_exists(sqlite *, char *); 155 static int smb_lgrp_gtbl_lookup(sqlite *, int, smb_group_t *, int, ...); 156 static int smb_lgrp_gtbl_insert(sqlite *, smb_group_t *); 157 static int smb_lgrp_gtbl_update(sqlite *, char *, smb_group_t *, int); 158 static int smb_lgrp_gtbl_delete(sqlite *, char *); 159 static int smb_lgrp_gtbl_update_mlist(sqlite *, char *, smb_gsid_t *, int); 160 static int smb_lgrp_gtbl_update_plist(sqlite *, char *, uint8_t, boolean_t); 161 static int smb_lgrp_gtbl_count(sqlite *, int, int *); 162 163 static int smb_lgrp_dtbl_insert(sqlite *, char *, uint32_t *); 164 static int smb_lgrp_dtbl_getidx(sqlite *, nt_sid_t *, uint16_t, 165 uint32_t *, uint32_t *); 166 static int smb_lgrp_dtbl_getsid(sqlite *, uint32_t, nt_sid_t **); 167 168 static int smb_lgrp_mlist_add(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *); 169 static int smb_lgrp_mlist_del(smb_lgmlist_t *, smb_lgmid_t *, smb_lgmlist_t *); 170 171 static int smb_lgrp_plist_add(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *); 172 static int smb_lgrp_plist_del(smb_lgplist_t *, smb_lgpid_t, smb_lgplist_t *); 173 174 static void smb_lgrp_encode_privset(smb_group_t *, smb_lgplist_t *); 175 176 static int smb_lgrp_decode(smb_group_t *, char **, int, sqlite *); 177 static int smb_lgrp_decode_privset(smb_group_t *, char *, char *); 178 static int smb_lgrp_decode_members(smb_group_t *, char *, char *, sqlite *); 179 180 static void smb_lgrp_set_default_privs(smb_group_t *); 181 static boolean_t smb_lgrp_chkname(char *); 182 static boolean_t smb_lgrp_chkmember(uint16_t); 183 static int smb_lgrp_getsid(int, uint32_t *, uint16_t, sqlite *, nt_sid_t **); 184 185 /* 186 * smb_lgrp_add 187 * 188 * Create a local group with the given name and comment. 189 * This new group doesn't have any members and no enabled 190 * privileges. 191 * 192 * No well-known accounts can be added other than Administators, 193 * Backup Operators and Power Users. These built-in groups 194 * won't have any members when created but a set of default 195 * privileges will be enabled for them. 196 */ 197 int 198 smb_lgrp_add(char *gname, char *cmnt) 199 { 200 well_known_account_t *wk_acct; 201 struct group *pxgrp; 202 smb_group_t grp; 203 nt_sid_t *sid = NULL; 204 sqlite *db; 205 int rc; 206 207 (void) trim_whitespace(gname); 208 if (!smb_lgrp_chkname(gname)) 209 return (SMB_LGRP_INVALID_NAME); 210 211 if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX)) 212 return (SMB_LGRP_INVALID_ARG); 213 214 bzero(&grp, sizeof (grp)); 215 grp.sg_name = utf8_strlwr(gname); 216 grp.sg_cmnt = cmnt; 217 218 wk_acct = nt_builtin_lookup(gname); 219 if (wk_acct == NULL) { 220 if ((pxgrp = getgrnam(gname)) == NULL) 221 return (SMB_LGRP_NOT_FOUND); 222 223 /* 224 * Make sure a local SID can be obtained 225 */ 226 if (smb_idmap_getsid(pxgrp->gr_gid, SMB_IDMAP_GROUP, &sid) 227 != IDMAP_SUCCESS) 228 return (SMB_LGRP_NO_SID); 229 230 if (!nt_sid_is_indomain(smb_lgrp_lsid, sid)) { 231 free(sid); 232 return (SMB_LGRP_SID_NOTLOCAL); 233 } 234 235 grp.sg_id.gs_type = SidTypeAlias; 236 grp.sg_domain = SMB_LGRP_LOCAL; 237 grp.sg_rid = pxgrp->gr_gid; 238 } else { 239 if (wk_acct->flags & LGF_HIDDEN) { 240 /* cannot add well-known accounts */ 241 return (SMB_LGRP_WKSID); 242 } 243 244 grp.sg_id.gs_type = wk_acct->sid_name_use; 245 if ((sid = nt_sid_strtosid(wk_acct->sid)) == NULL) 246 return (SMB_LGRP_NO_MEMORY); 247 (void) nt_sid_get_rid(sid, &grp.sg_rid); 248 free(sid); 249 grp.sg_domain = SMB_LGRP_BUILTIN; 250 251 grp.sg_privs = smb_privset_new(); 252 smb_lgrp_set_default_privs(&grp); 253 } 254 255 256 grp.sg_attr = SE_GROUP_MANDATORY | SE_GROUP_ENABLED_BY_DEFAULT | 257 SE_GROUP_ENABLED; 258 259 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 260 rc = smb_lgrp_gtbl_insert(db, &grp); 261 smb_lgrp_db_close(db); 262 263 smb_privset_free(grp.sg_privs); 264 return (rc); 265 } 266 267 /* 268 * smb_lgrp_rename 269 * 270 * Renames the given group 271 */ 272 int 273 smb_lgrp_rename(char *gname, char *new_gname) 274 { 275 smb_group_t grp; 276 sqlite *db; 277 int rc; 278 279 (void) trim_whitespace(gname); 280 if (!smb_lgrp_chkname(gname)) 281 return (SMB_LGRP_INVALID_NAME); 282 283 (void) trim_whitespace(new_gname); 284 if (!smb_lgrp_chkname(gname)) 285 return (SMB_LGRP_INVALID_NAME); 286 287 if (utf8_strcasecmp(gname, new_gname) == 0) 288 return (SMB_LGRP_SUCCESS); 289 290 /* Cannot rename well-known groups */ 291 if (nt_builtin_is_wellknown(gname)) 292 return (SMB_LGRP_WKSID); 293 294 /* Cannot rename to a well-known groups */ 295 if (nt_builtin_is_wellknown(new_gname)) 296 return (SMB_LGRP_WKSID); 297 298 grp.sg_name = new_gname; 299 300 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 301 rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_NAME); 302 smb_lgrp_db_close(db); 303 304 return (rc); 305 } 306 307 /* 308 * smb_lgrp_delete 309 * 310 * Deletes the specified local group. 311 */ 312 int 313 smb_lgrp_delete(char *gname) 314 { 315 sqlite *db; 316 int rc; 317 318 (void) trim_whitespace(gname); 319 if (!smb_lgrp_chkname(gname)) 320 return (SMB_LGRP_INVALID_NAME); 321 322 /* Cannot remove a built-in group */ 323 if (nt_builtin_is_wellknown(gname)) 324 return (SMB_LGRP_WKSID); 325 326 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 327 rc = smb_lgrp_gtbl_delete(db, gname); 328 smb_lgrp_db_close(db); 329 330 return (rc); 331 } 332 333 /* 334 * smb_lgrp_setcmnt 335 * 336 * Sets the description for the given group 337 */ 338 int 339 smb_lgrp_setcmnt(char *gname, char *cmnt) 340 { 341 smb_group_t grp; 342 sqlite *db; 343 int rc; 344 345 (void) trim_whitespace(gname); 346 if (!smb_lgrp_chkname(gname)) 347 return (SMB_LGRP_INVALID_NAME); 348 349 if (cmnt && (strlen(cmnt) > SMB_LGRP_COMMENT_MAX)) 350 return (SMB_LGRP_INVALID_ARG); 351 352 grp.sg_cmnt = cmnt; 353 354 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 355 rc = smb_lgrp_gtbl_update(db, gname, &grp, SMB_LGRP_GTBL_CMNT); 356 smb_lgrp_db_close(db); 357 358 return (rc); 359 } 360 361 /* 362 * smb_lgrp_getcmnt 363 * 364 * Obtain the description of the specified group 365 */ 366 int 367 smb_lgrp_getcmnt(char *gname, char **cmnt) 368 { 369 smb_group_t grp; 370 sqlite *db; 371 int rc; 372 373 (void) trim_whitespace(gname); 374 if (!smb_lgrp_chkname(gname)) 375 return (SMB_LGRP_INVALID_NAME); 376 377 if (cmnt == NULL) 378 return (SMB_LGRP_INVALID_ARG); 379 380 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); 381 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp, 382 SMB_LGRP_INFO_CMNT, gname); 383 smb_lgrp_db_close(db); 384 385 if (rc == SMB_LGRP_SUCCESS) { 386 *cmnt = grp.sg_cmnt; 387 grp.sg_cmnt = NULL; 388 smb_lgrp_free(&grp); 389 } 390 391 return (rc); 392 } 393 394 395 /* 396 * smb_lgrp_setpriv 397 * 398 * Enable/disable the specified privilge for the group 399 */ 400 int 401 smb_lgrp_setpriv(char *gname, uint8_t priv_lid, boolean_t enable) 402 { 403 sqlite *db; 404 int rc; 405 406 (void) trim_whitespace(gname); 407 if (!smb_lgrp_chkname(gname)) 408 return (SMB_LGRP_INVALID_NAME); 409 410 if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID)) 411 return (SMB_LGRP_NO_SUCH_PRIV); 412 413 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 414 rc = smb_lgrp_gtbl_update_plist(db, gname, priv_lid, enable); 415 smb_lgrp_db_close(db); 416 417 if (enable) { 418 if (rc == SMB_LGRP_PRIV_HELD) 419 rc = SMB_LGRP_SUCCESS; 420 } else { 421 if (rc == SMB_LGRP_PRIV_NOT_HELD) 422 rc = SMB_LGRP_SUCCESS; 423 } 424 425 return (rc); 426 } 427 428 /* 429 * smb_lgrp_getpriv 430 * 431 * Obtain the status of the specified privilge for the group 432 */ 433 int 434 smb_lgrp_getpriv(char *gname, uint8_t priv_lid, boolean_t *enable) 435 { 436 sqlite *db; 437 smb_group_t grp; 438 int rc; 439 440 (void) trim_whitespace(gname); 441 if (!smb_lgrp_chkname(gname)) 442 return (SMB_LGRP_INVALID_NAME); 443 444 if ((priv_lid < SE_MIN_LUID) || (priv_lid > SE_MAX_LUID)) 445 return (SMB_LGRP_NO_SUCH_PRIV); 446 447 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); 448 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, &grp, 449 SMB_LGRP_INFO_PRIV, gname); 450 smb_lgrp_db_close(db); 451 452 if (rc == SMB_LGRP_SUCCESS) { 453 *enable = (smb_privset_query(grp.sg_privs, priv_lid) == 1); 454 smb_lgrp_free(&grp); 455 } 456 457 return (rc); 458 } 459 460 /* 461 * smb_lgrp_add_member 462 * 463 * Add the given account to the specified group as its member. 464 */ 465 int 466 smb_lgrp_add_member(char *gname, nt_sid_t *msid, uint16_t sid_type) 467 { 468 sqlite *db; 469 smb_gsid_t mid; 470 int rc; 471 472 (void) trim_whitespace(gname); 473 if (!smb_lgrp_chkname(gname)) 474 return (SMB_LGRP_INVALID_NAME); 475 476 if (!nt_sid_is_valid(msid)) 477 return (SMB_LGRP_INVALID_ARG); 478 479 if (!smb_lgrp_chkmember(sid_type)) 480 return (SMB_LGRP_INVALID_MEMBER); 481 482 mid.gs_sid = msid; 483 mid.gs_type = sid_type; 484 485 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 486 rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_ADDMEMBER); 487 smb_lgrp_db_close(db); 488 489 return (rc); 490 } 491 492 /* 493 * smb_lgrp_del_member 494 * 495 * Delete the specified member from the given group. 496 */ 497 int 498 smb_lgrp_del_member(char *gname, nt_sid_t *msid, uint16_t sid_type) 499 { 500 sqlite *db; 501 smb_gsid_t mid; 502 int rc; 503 504 (void) trim_whitespace(gname); 505 if (!smb_lgrp_chkname(gname)) 506 return (SMB_LGRP_INVALID_NAME); 507 508 if (!nt_sid_is_valid(msid)) 509 return (SMB_LGRP_INVALID_ARG); 510 511 mid.gs_sid = msid; 512 mid.gs_type = sid_type; 513 514 db = smb_lgrp_db_open(SMB_LGRP_DB_ORW); 515 rc = smb_lgrp_gtbl_update_mlist(db, gname, &mid, SMB_LGRP_DB_DELMEMBER); 516 smb_lgrp_db_close(db); 517 518 return (rc); 519 } 520 521 /* 522 * smb_lgrp_getbyname 523 * 524 * Retrieves the information of the group specified by 525 * the given name. 526 * 527 * Note that this function doesn't allocate the group 528 * structure itself only the fields, so the given grp 529 * pointer has to point to a group structure. 530 * Caller must free the allocated memories for the fields 531 * by calling smb_lgrp_free(). 532 */ 533 int 534 smb_lgrp_getbyname(char *gname, smb_group_t *grp) 535 { 536 sqlite *db; 537 int rc; 538 539 (void) trim_whitespace(gname); 540 if (!smb_lgrp_chkname(gname)) 541 return (SMB_LGRP_INVALID_NAME); 542 543 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); 544 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_NAME, grp, 545 SMB_LGRP_INFO_ALL, gname); 546 smb_lgrp_db_close(db); 547 548 return (rc); 549 } 550 551 /* 552 * smb_lgrp_getbyrid 553 * 554 * Retrieves the information of the group specified by 555 * the given RID and domain type. 556 * 557 * Note that this function doesn't allocate the group 558 * structure itself only the fields, so the given grp 559 * pointer has to point to a group structure. 560 * Caller must free the allocated memories for the fields 561 * by calling smb_lgrp_free(). 562 * 563 * If grp is NULL no information would be returned. The 564 * return value of SMB_LGRP_SUCCESS will indicate that a 565 * group with the given information exists. 566 */ 567 int 568 smb_lgrp_getbyrid(uint32_t rid, smb_gdomain_t domtype, smb_group_t *grp) 569 { 570 smb_group_t tmpgrp; 571 sqlite *db; 572 int infolvl = SMB_LGRP_INFO_ALL; 573 int rc; 574 575 if (grp == NULL) { 576 grp = &tmpgrp; 577 infolvl = SMB_LGRP_INFO_NONE; 578 } 579 580 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); 581 rc = smb_lgrp_gtbl_lookup(db, SMB_LGRP_GTBL_SIDRID, grp, infolvl, 582 rid, domtype); 583 smb_lgrp_db_close(db); 584 585 return (rc); 586 } 587 588 /* 589 * smb_lgrp_numbydomain 590 * 591 * Returns the number of groups in the given domain in the 592 * arg 'count' 593 */ 594 int 595 smb_lgrp_numbydomain(smb_gdomain_t dom_type, int *count) 596 { 597 sqlite *db; 598 int dom_idx; 599 int rc; 600 601 switch (dom_type) { 602 case SMB_LGRP_LOCAL: 603 dom_idx = SMB_LGRP_LOCAL_IDX; 604 break; 605 case SMB_LGRP_BUILTIN: 606 dom_idx = SMB_LGRP_BUILTIN_IDX; 607 break; 608 default: 609 *count = 0; 610 return (SMB_LGRP_INVALID_ARG); 611 } 612 613 db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); 614 rc = smb_lgrp_gtbl_count(db, dom_idx, count); 615 smb_lgrp_db_close(db); 616 617 return (rc); 618 } 619 620 /* 621 * smb_lgrp_numbydomain 622 * 623 * Returns the number of groups which have the given SID 624 * as a member. 625 */ 626 int 627 smb_lgrp_numbymember(nt_sid_t *msid, int *count) 628 { 629 smb_giter_t gi; 630 smb_group_t grp; 631 int rc; 632 633 *count = 0; 634 rc = smb_lgrp_iteropen(&gi); 635 if (rc != SMB_LGRP_SUCCESS) 636 return (rc); 637 638 while (smb_lgrp_iterate(&gi, &grp) == SMB_LGRP_SUCCESS) { 639 if (smb_lgrp_is_member(&grp, msid)) 640 (*count)++; 641 smb_lgrp_free(&grp); 642 } 643 smb_lgrp_iterclose(&gi); 644 return (SMB_LGRP_SUCCESS); 645 } 646 647 /* 648 * smb_lgrp_free 649 * 650 * Frees the allocated memory for the fields of the given 651 * group structure. Note that this function doesn't free 652 * the group itself. 653 */ 654 void 655 smb_lgrp_free(smb_group_t *grp) 656 { 657 int i; 658 659 if (grp == NULL) 660 return; 661 662 free(grp->sg_name); 663 free(grp->sg_cmnt); 664 free(grp->sg_id.gs_sid); 665 smb_privset_free(grp->sg_privs); 666 667 for (i = 0; i < grp->sg_nmembers; i++) 668 free(grp->sg_members[i].gs_sid); 669 free(grp->sg_members); 670 } 671 672 /* 673 * smb_lgrp_iteropen 674 * 675 * Initializes the given group iterator by opening 676 * the group database and creating a virtual machine 677 * for iteration. 678 */ 679 int 680 smb_lgrp_iteropen(smb_giter_t *iter) 681 { 682 char *sql; 683 char *errmsg = NULL; 684 int rc = SMB_LGRP_SUCCESS; 685 686 assert(iter); 687 688 bzero(iter, sizeof (smb_giter_t)); 689 690 sql = sqlite_mprintf("SELECT * FROM groups"); 691 if (sql == NULL) 692 return (SMB_LGRP_NO_MEMORY); 693 694 iter->sgi_db = smb_lgrp_db_open(SMB_LGRP_DB_ORD); 695 if (iter->sgi_db == NULL) { 696 sqlite_freemem(sql); 697 return (SMB_LGRP_DBOPEN_FAILED); 698 } 699 700 rc = sqlite_compile(iter->sgi_db, sql, NULL, &iter->sgi_vm, &errmsg); 701 sqlite_freemem(sql); 702 703 if (rc != SQLITE_OK) { 704 syslog(LOG_DEBUG, "failed to create a VM (%s)", 705 NULL_MSGCHK(errmsg)); 706 rc = SMB_LGRP_DB_ERROR; 707 } 708 709 return (rc); 710 } 711 712 /* 713 * smb_lgrp_iterclose 714 * 715 * Closes the given group iterator. 716 */ 717 void 718 smb_lgrp_iterclose(smb_giter_t *iter) 719 { 720 char *errmsg = NULL; 721 int rc; 722 723 assert(iter); 724 725 rc = sqlite_finalize(iter->sgi_vm, &errmsg); 726 if (rc != SQLITE_OK) { 727 syslog(LOG_DEBUG, "failed to destroy a VM (%s)", 728 NULL_MSGCHK(errmsg)); 729 } 730 731 smb_lgrp_db_close(iter->sgi_db); 732 } 733 734 /* 735 * smb_lgrp_iterate 736 * 737 * Iterate through group database 738 * Group information is returned in provided group structure. 739 * 740 * Note that this function doesn't allocate the group 741 * structure itself only the fields, so the given grp 742 * pointer has to point to a group structure. 743 * Caller must free the allocated memories for the fields 744 * by calling smb_lgrp_free(). 745 */ 746 int 747 smb_lgrp_iterate(smb_giter_t *iter, smb_group_t *grp) 748 { 749 const char **values; 750 int ncol; 751 int rc; 752 int i; 753 754 if (iter->sgi_vm == NULL || iter->sgi_db == NULL) 755 return (SMB_LGRP_INVALID_ARG); 756 757 bzero(grp, sizeof (smb_group_t)); 758 rc = sqlite_step(iter->sgi_vm, &ncol, &values, NULL); 759 if (rc == SQLITE_DONE) 760 return (SMB_LGRP_NO_MORE); 761 762 if (rc != SQLITE_ROW) 763 return (SMB_LGRP_DBEXEC_FAILED); 764 765 if (ncol != SMB_LGRP_GTBL_NCOL) 766 return (SMB_LGRP_DB_ERROR); 767 768 for (i = 0; i < ncol; i++) { 769 if (values[i] == NULL) 770 return (SMB_LGRP_DB_ERROR); 771 } 772 773 return (smb_lgrp_decode(grp, (char **)values, SMB_LGRP_INFO_ALL, 774 iter->sgi_db)); 775 } 776 777 /* 778 * smb_lgrp_is_member 779 * 780 * Check to see if the specified account is a member of 781 * the given group. 782 */ 783 boolean_t 784 smb_lgrp_is_member(smb_group_t *grp, nt_sid_t *sid) 785 { 786 int i; 787 788 if (grp == NULL || grp->sg_members == NULL || sid == NULL) 789 return (B_FALSE); 790 791 for (i = 0; i < grp->sg_nmembers; i++) { 792 if (nt_sid_is_equal(grp->sg_members[i].gs_sid, sid)) 793 return (B_TRUE); 794 } 795 796 return (B_FALSE); 797 } 798 799 /* 800 * smb_lgrp_strerror 801 * 802 * Returns a text for the given group error code. 803 */ 804 char * 805 smb_lgrp_strerror(int errno) 806 { 807 switch (errno) { 808 case SMB_LGRP_SUCCESS: 809 return (dgettext(TEXT_DOMAIN, "success")); 810 case SMB_LGRP_INVALID_ARG: 811 return (dgettext(TEXT_DOMAIN, "invalid argument")); 812 case SMB_LGRP_INVALID_MEMBER: 813 return (dgettext(TEXT_DOMAIN, "invalid member type")); 814 case SMB_LGRP_INVALID_NAME: 815 return (dgettext(TEXT_DOMAIN, "invalid name")); 816 case SMB_LGRP_NOT_FOUND: 817 return (dgettext(TEXT_DOMAIN, "group not found")); 818 case SMB_LGRP_EXISTS: 819 return (dgettext(TEXT_DOMAIN, "group exists")); 820 case SMB_LGRP_NO_SID: 821 return (dgettext(TEXT_DOMAIN, "cannot obtain a SID")); 822 case SMB_LGRP_NO_LOCAL_SID: 823 return (dgettext(TEXT_DOMAIN, "cannot get the machine SID")); 824 case SMB_LGRP_SID_NOTLOCAL: 825 return (dgettext(TEXT_DOMAIN, "not a local SID")); 826 case SMB_LGRP_WKSID: 827 return (dgettext(TEXT_DOMAIN, 828 "operation not permitted on well-known accounts")); 829 case SMB_LGRP_NO_MEMORY: 830 return (dgettext(TEXT_DOMAIN, "not enough memory")); 831 case SMB_LGRP_DB_ERROR: 832 return (dgettext(TEXT_DOMAIN, "database operation error")); 833 case SMB_LGRP_DBINIT_ERROR: 834 return (dgettext(TEXT_DOMAIN, "database initialization error")); 835 case SMB_LGRP_INTERNAL_ERROR: 836 return (dgettext(TEXT_DOMAIN, "internal error")); 837 case SMB_LGRP_MEMBER_IN_GROUP: 838 return (dgettext(TEXT_DOMAIN, "member already in the group")); 839 case SMB_LGRP_MEMBER_NOT_IN_GROUP: 840 return (dgettext(TEXT_DOMAIN, "not a member")); 841 case SMB_LGRP_NO_SUCH_PRIV: 842 return (dgettext(TEXT_DOMAIN, "no such privilege")); 843 case SMB_LGRP_NO_SUCH_DOMAIN: 844 return (dgettext(TEXT_DOMAIN, "no such domain SID")); 845 case SMB_LGRP_PRIV_HELD: 846 return (dgettext(TEXT_DOMAIN, "already holds the privilege")); 847 case SMB_LGRP_PRIV_NOT_HELD: 848 return (dgettext(TEXT_DOMAIN, "privilege not held")); 849 case SMB_LGRP_BAD_DATA: 850 return (dgettext(TEXT_DOMAIN, "bad data")); 851 case SMB_LGRP_NO_MORE: 852 return (dgettext(TEXT_DOMAIN, "no more groups")); 853 case SMB_LGRP_DBOPEN_FAILED: 854 return (dgettext(TEXT_DOMAIN, "failed openning database")); 855 case SMB_LGRP_DBEXEC_FAILED: 856 return (dgettext(TEXT_DOMAIN, 857 "failed executing database operation")); 858 case SMB_LGRP_DBINIT_FAILED: 859 return (dgettext(TEXT_DOMAIN, "failed initializing database")); 860 case SMB_LGRP_DOMLKP_FAILED: 861 return (dgettext(TEXT_DOMAIN, "failed getting the domain SID")); 862 case SMB_LGRP_DOMINS_FAILED: 863 return (dgettext(TEXT_DOMAIN, 864 "failed inserting the domain SID")); 865 case SMB_LGRP_INSERT_FAILED: 866 return (dgettext(TEXT_DOMAIN, "failed inserting the group")); 867 case SMB_LGRP_DELETE_FAILED: 868 return (dgettext(TEXT_DOMAIN, "failed deleting the group")); 869 case SMB_LGRP_UPDATE_FAILED: 870 return (dgettext(TEXT_DOMAIN, "failed updating the group")); 871 case SMB_LGRP_LOOKUP_FAILED: 872 return (dgettext(TEXT_DOMAIN, "failed looking up the group")); 873 } 874 875 return (dgettext(TEXT_DOMAIN, "unknown error code")); 876 } 877 878 /* 879 * smb_lgrp_chkmember 880 * 881 * Determines valid account types for being member of 882 * a local group. 883 * 884 * Currently, we just support users as valid members. 885 */ 886 static boolean_t 887 smb_lgrp_chkmember(uint16_t sid_type) 888 { 889 return (sid_type == SidTypeUser); 890 } 891 892 /* 893 * smb_lgrp_start 894 * 895 * Initializes the library private global variables. 896 * If the database doesn't exist, it'll create it and adds the 897 * predefined builtin groups. 898 */ 899 int 900 smb_lgrp_start(void) 901 { 902 char *supported_bg[] = 903 {"Administrators", "Backup Operators", "Power Users"}; 904 well_known_account_t *wka; 905 int rc, i, ngrp; 906 char *lsid_str; 907 908 (void) mutex_init(&smb_lgrp_lsid_mtx, USYNC_THREAD, NULL); 909 (void) mutex_lock(&smb_lgrp_lsid_mtx); 910 lsid_str = smb_config_get_localsid(); 911 if (lsid_str == NULL) { 912 (void) mutex_unlock(&smb_lgrp_lsid_mtx); 913 return (SMB_LGRP_NO_LOCAL_SID); 914 } 915 916 smb_lgrp_lsid = nt_sid_strtosid(lsid_str); 917 free(lsid_str); 918 if (!nt_sid_is_valid(smb_lgrp_lsid)) { 919 free(smb_lgrp_lsid); 920 smb_lgrp_lsid = NULL; 921 (void) mutex_unlock(&smb_lgrp_lsid_mtx); 922 return (SMB_LGRP_NO_LOCAL_SID); 923 } 924 925 rc = smb_lgrp_db_init(); 926 if (rc != SMB_LGRP_SUCCESS) { 927 free(smb_lgrp_lsid); 928 smb_lgrp_lsid = NULL; 929 (void) mutex_unlock(&smb_lgrp_lsid_mtx); 930 return (rc); 931 } 932 (void) mutex_unlock(&smb_lgrp_lsid_mtx); 933 934 ngrp = sizeof (supported_bg) / sizeof (supported_bg[0]); 935 for (i = 0; i < ngrp; i++) { 936 wka = nt_builtin_lookup(supported_bg[i]); 937 if (wka == NULL) 938 continue; 939 rc = smb_lgrp_add(wka->name, wka->desc); 940 if (rc != SMB_LGRP_SUCCESS) 941 syslog(LOG_DEBUG, "failed to add %s", wka->name); 942 } 943 944 return (SMB_LGRP_SUCCESS); 945 } 946 947 /* 948 * smb_lgrp_stop 949 * 950 * Unintialize the library global private variables. 951 */ 952 void 953 smb_lgrp_stop(void) 954 { 955 (void) mutex_lock(&smb_lgrp_lsid_mtx); 956 free(smb_lgrp_lsid); 957 smb_lgrp_lsid = NULL; 958 (void) mutex_unlock(&smb_lgrp_lsid_mtx); 959 (void) mutex_destroy(&smb_lgrp_lsid_mtx); 960 } 961 962 /* 963 * smb_lgrp_db_open 964 * 965 * Opens group database with the given mode. 966 */ 967 static sqlite * 968 smb_lgrp_db_open(int mode) 969 { 970 sqlite *db; 971 char *errmsg = NULL; 972 973 db = sqlite_open(SMB_LGRP_DB_NAME, mode, &errmsg); 974 if (db == NULL) { 975 syslog(LOG_ERR, "failed to open group database (%s)", 976 NULL_MSGCHK(errmsg)); 977 sqlite_freemem(errmsg); 978 } 979 980 return (db); 981 } 982 983 /* 984 * smb_lgrp_db_close 985 * 986 * Closes the given database handle 987 */ 988 static void 989 smb_lgrp_db_close(sqlite *db) 990 { 991 if (db) { 992 sqlite_close(db); 993 } 994 } 995 996 /* 997 * smb_lgrp_db_init 998 * 999 * Creates the group database based on the defined SQL statement. 1000 * It also initializes db_info and domain tables. 1001 */ 1002 static int 1003 smb_lgrp_db_init(void) 1004 { 1005 int dbrc = SQLITE_OK; 1006 int rc = SMB_LGRP_SUCCESS; 1007 sqlite *db = NULL; 1008 char *errmsg = NULL; 1009 1010 db = sqlite_open(SMB_LGRP_DB_NAME, 0600, &errmsg); 1011 if (db == NULL) { 1012 syslog(LOG_ERR, "failed to create group database (%s)", 1013 NULL_MSGCHK(errmsg)); 1014 sqlite_freemem(errmsg); 1015 return (SMB_LGRP_DBOPEN_FAILED); 1016 } 1017 1018 sqlite_busy_timeout(db, SMB_LGRP_DB_TIMEOUT); 1019 dbrc = sqlite_exec(db, "BEGIN TRANSACTION;", NULL, NULL, &errmsg); 1020 if (dbrc != SQLITE_OK) { 1021 syslog(LOG_DEBUG, "failed to begin database transaction (%s)", 1022 NULL_MSGCHK(errmsg)); 1023 sqlite_freemem(errmsg); 1024 sqlite_close(db); 1025 return (SMB_LGRP_DBEXEC_FAILED); 1026 } 1027 1028 switch (sqlite_exec(db, SMB_LGRP_DB_SQL, NULL, NULL, &errmsg)) { 1029 case SQLITE_ERROR: 1030 /* 1031 * This is the normal situation: CREATE probably failed because 1032 * tables already exist. It may indicate an error in SQL as well 1033 * but we cannot tell. 1034 */ 1035 sqlite_freemem(errmsg); 1036 dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, 1037 &errmsg); 1038 rc = SMB_LGRP_SUCCESS; 1039 break; 1040 1041 case SQLITE_OK: 1042 dbrc = sqlite_exec(db, "COMMIT TRANSACTION", NULL, NULL, 1043 &errmsg); 1044 if (dbrc != SQLITE_OK) 1045 break; 1046 rc = smb_lgrp_dtbl_insert(db, NT_BUILTIN_DOMAIN_SIDSTR, 1047 NULL); 1048 if (rc == SMB_LGRP_SUCCESS) 1049 rc = smb_lgrp_db_setinfo(db); 1050 if (rc != SMB_LGRP_SUCCESS) { 1051 (void) sqlite_close(db); 1052 (void) unlink(SMB_LGRP_DB_NAME); 1053 return (rc); 1054 } 1055 break; 1056 1057 default: 1058 syslog(LOG_ERR, 1059 "failed to initialize group database (%s)", errmsg); 1060 sqlite_freemem(errmsg); 1061 dbrc = sqlite_exec(db, "ROLLBACK TRANSACTION", NULL, NULL, 1062 &errmsg); 1063 rc = SMB_LGRP_DBINIT_FAILED; 1064 break; 1065 } 1066 1067 if (dbrc != SQLITE_OK) { 1068 /* this is bad - database may be left in a locked state */ 1069 syslog(LOG_DEBUG, "failed to close a transaction (%s)", 1070 NULL_MSGCHK(errmsg)); 1071 sqlite_freemem(errmsg); 1072 } 1073 1074 (void) sqlite_close(db); 1075 return (rc); 1076 } 1077 1078 /* 1079 * smb_lgrp_gtbl_lookup 1080 * 1081 * This is a flexible lookup function for the group database. 1082 * The key type can be specified by the 'key' arg and the actual key 1083 * values can be passed after the 'infolvl' arg. 'infolvl' arg specifies 1084 * what information items for the specified group is needed. 1085 * 1086 * Note that the function assumes the given key is unique and only 1087 * specifies one or 0 group. The keys that are supported now are 1088 * the group name and the group SID 1089 * 1090 * Note that this function doesn't allocate the group 1091 * structure itself only the fields, so the given grp 1092 * pointer has to point to a group structure. 1093 * Caller must free the allocated memories for the fields 1094 * by calling smb_lgrp_free(). 1095 */ 1096 static int 1097 smb_lgrp_gtbl_lookup(sqlite *db, int key, smb_group_t *grp, int infolvl, ...) 1098 { 1099 char *errmsg = NULL; 1100 char *sql; 1101 char **result; 1102 int nrow, ncol; 1103 int rc, dom_idx; 1104 smb_group_t kgrp; 1105 va_list ap; 1106 1107 if (db == NULL) 1108 return (SMB_LGRP_DBOPEN_FAILED); 1109 1110 bzero(grp, sizeof (smb_group_t)); 1111 va_start(ap, infolvl); 1112 1113 switch (key) { 1114 case SMB_LGRP_GTBL_NAME: 1115 kgrp.sg_name = va_arg(ap, char *); 1116 sql = sqlite_mprintf("SELECT * FROM groups WHERE name = '%s'", 1117 kgrp.sg_name); 1118 break; 1119 1120 case SMB_LGRP_GTBL_SIDRID: 1121 kgrp.sg_rid = va_arg(ap, uint32_t); 1122 kgrp.sg_domain = va_arg(ap, smb_gdomain_t); 1123 dom_idx = (kgrp.sg_domain == SMB_LGRP_LOCAL) 1124 ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX; 1125 sql = sqlite_mprintf("SELECT * FROM groups" 1126 "WHERE (sid_idx = %d) AND (sid_rid = %u)", 1127 dom_idx, kgrp.sg_rid); 1128 break; 1129 1130 default: 1131 va_end(ap); 1132 return (SMB_LGRP_INVALID_ARG); 1133 } 1134 1135 va_end(ap); 1136 if (sql == NULL) 1137 return (SMB_LGRP_NO_MEMORY); 1138 1139 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1140 sqlite_freemem(sql); 1141 1142 if (rc != SQLITE_OK) { 1143 syslog(LOG_DEBUG, "failed to lookup (%s)", NULL_MSGCHK(errmsg)); 1144 sqlite_freemem(errmsg); 1145 return (SMB_LGRP_LOOKUP_FAILED); 1146 } 1147 1148 if (nrow == 0) { 1149 /* group not found */ 1150 sqlite_free_table(result); 1151 return (SMB_LGRP_NOT_FOUND); 1152 } 1153 1154 if (nrow != 1 || ncol != SMB_LGRP_GTBL_NCOL) { 1155 sqlite_free_table(result); 1156 return (SMB_LGRP_DB_ERROR); 1157 } 1158 1159 rc = smb_lgrp_decode(grp, &result[SMB_LGRP_GTBL_NCOL], infolvl, db); 1160 sqlite_free_table(result); 1161 return (rc); 1162 } 1163 1164 /* 1165 * smb_lgrp_gtbl_exists 1166 * 1167 * Checks to see if the given group exists or not. 1168 */ 1169 static boolean_t 1170 smb_lgrp_gtbl_exists(sqlite *db, char *gname) 1171 { 1172 char *errmsg = NULL; 1173 char *sql; 1174 char **result; 1175 int nrow, ncol; 1176 int rc; 1177 1178 if (db == NULL) 1179 return (NULL); 1180 1181 sql = sqlite_mprintf("SELECT name FROM groups WHERE name = '%s'", 1182 gname); 1183 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1184 sqlite_freemem(sql); 1185 1186 if (rc != SQLITE_OK) { 1187 syslog(LOG_DEBUG, "failed to lookup %s (%s)", 1188 gname, NULL_MSGCHK(errmsg)); 1189 sqlite_freemem(errmsg); 1190 return (B_FALSE); 1191 } 1192 1193 sqlite_free_table(result); 1194 return (nrow != 0); 1195 } 1196 1197 /* 1198 * smb_lgrp_gtbl_count 1199 * 1200 * Counts the number of groups in the domain specified by 1201 * 'dom_idx' 1202 */ 1203 static int 1204 smb_lgrp_gtbl_count(sqlite *db, int dom_idx, int *count) 1205 { 1206 char *errmsg = NULL; 1207 char *sql; 1208 char **result; 1209 int nrow, ncol; 1210 int rc; 1211 1212 *count = 0; 1213 if (db == NULL) 1214 return (SMB_LGRP_DBOPEN_FAILED); 1215 1216 sql = sqlite_mprintf("SELECT sid_idx FROM groups WHERE sid_idx = %d", 1217 dom_idx); 1218 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1219 sqlite_freemem(sql); 1220 1221 if (rc != SQLITE_OK) { 1222 syslog(LOG_DEBUG, "failed to count (%s)", NULL_MSGCHK(errmsg)); 1223 sqlite_freemem(errmsg); 1224 return (SMB_LGRP_LOOKUP_FAILED); 1225 } 1226 1227 sqlite_free_table(result); 1228 if (ncol > 1) 1229 return (SMB_LGRP_DB_ERROR); 1230 1231 *count = nrow; 1232 return (SMB_LGRP_SUCCESS); 1233 } 1234 1235 /* 1236 * smb_lgrp_gtbl_insert 1237 * 1238 * Insert a record for the given group in the group database. 1239 * 1240 * NOTE: this function assumes that this group has no members 1241 * at this time. 1242 */ 1243 static int 1244 smb_lgrp_gtbl_insert(sqlite *db, smb_group_t *grp) 1245 { 1246 smb_lgpid_t privs[SE_MAX_LUID + 1]; 1247 smb_lgplist_t plist; 1248 char *errmsg = NULL; 1249 char *sql; 1250 int dom_idx; 1251 int rc; 1252 1253 if (db == NULL) 1254 return (SMB_LGRP_DBOPEN_FAILED); 1255 1256 dom_idx = (grp->sg_domain == SMB_LGRP_LOCAL) 1257 ? SMB_LGRP_LOCAL_IDX : SMB_LGRP_BUILTIN_IDX; 1258 1259 plist.p_cnt = SE_MAX_LUID; 1260 plist.p_ids = privs; 1261 smb_lgrp_encode_privset(grp, &plist); 1262 1263 sql = sqlite_mprintf("INSERT INTO groups" 1264 "(name, sid_idx, sid_rid, sid_type, sid_attrs, comment, " 1265 "n_privs, privs, n_members, members) " 1266 "VALUES('%s', %u, %u, %u, %u, '%q', %u, '%q', %u, '%q')", 1267 grp->sg_name, dom_idx, grp->sg_rid, grp->sg_id.gs_type, 1268 grp->sg_attr, (grp->sg_cmnt) ? grp->sg_cmnt : "", 1269 plist.p_cnt, (char *)plist.p_ids, 0, ""); 1270 1271 if (sql == NULL) 1272 return (SMB_LGRP_NO_MEMORY); 1273 1274 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1275 sqlite_freemem(sql); 1276 1277 if (rc != SQLITE_OK) { 1278 syslog(LOG_DEBUG, "failed to insert %s (%s)", 1279 grp->sg_name, NULL_MSGCHK(errmsg)); 1280 sqlite_freemem(errmsg); 1281 rc = SMB_LGRP_INSERT_FAILED; 1282 } else { 1283 rc = SMB_LGRP_SUCCESS; 1284 } 1285 1286 return (rc); 1287 } 1288 1289 /* 1290 * smb_lgrp_gtbl_delete 1291 * 1292 * Removes the specified group from the database 1293 */ 1294 static int 1295 smb_lgrp_gtbl_delete(sqlite *db, char *gname) 1296 { 1297 char *errmsg = NULL; 1298 char *sql; 1299 int rc; 1300 1301 if (db == NULL) 1302 return (SMB_LGRP_DBOPEN_FAILED); 1303 1304 sql = sqlite_mprintf("DELETE FROM groups WHERE name = '%s'", gname); 1305 if (sql == NULL) 1306 return (SMB_LGRP_NO_MEMORY); 1307 1308 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1309 sqlite_freemem(sql); 1310 1311 if (rc != SQLITE_OK) { 1312 syslog(LOG_DEBUG, "failed to delete %s (%s)", 1313 gname, NULL_MSGCHK(errmsg)); 1314 sqlite_freemem(errmsg); 1315 rc = SMB_LGRP_DELETE_FAILED; 1316 } else { 1317 rc = SMB_LGRP_SUCCESS; 1318 } 1319 1320 return (rc); 1321 } 1322 1323 /* 1324 * smb_lgrp_gtbl_update 1325 * 1326 * Updates the specified group information, the supported items 1327 * are group name and comment 1328 */ 1329 static int 1330 smb_lgrp_gtbl_update(sqlite *db, char *gname, smb_group_t *grp, int col_id) 1331 { 1332 char *errmsg = NULL; 1333 char *sql; 1334 int rc; 1335 1336 if (db == NULL) 1337 return (SMB_LGRP_DBOPEN_FAILED); 1338 1339 /* UPDATE doesn't fail if gname doesn't exist */ 1340 if (!smb_lgrp_gtbl_exists(db, gname)) 1341 return (SMB_LGRP_NOT_FOUND); 1342 1343 switch (col_id) { 1344 case SMB_LGRP_GTBL_NAME: 1345 if (smb_lgrp_gtbl_exists(db, grp->sg_name)) 1346 return (SMB_LGRP_EXISTS); 1347 sql = sqlite_mprintf("UPDATE groups SET name = '%s' " 1348 "WHERE name = '%s'", grp->sg_name, gname); 1349 break; 1350 1351 case SMB_LGRP_GTBL_CMNT: 1352 sql = sqlite_mprintf("UPDATE groups SET comment = '%q' " 1353 "WHERE name = '%s'", grp->sg_cmnt, gname); 1354 break; 1355 1356 default: 1357 return (SMB_LGRP_INVALID_ARG); 1358 } 1359 1360 if (sql == NULL) 1361 return (SMB_LGRP_NO_MEMORY); 1362 1363 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1364 sqlite_freemem(sql); 1365 1366 if (rc != SQLITE_OK) { 1367 syslog(LOG_DEBUG, "failed to update %s (%s)", 1368 gname, NULL_MSGCHK(errmsg)); 1369 sqlite_freemem(errmsg); 1370 rc = SMB_LGRP_UPDATE_FAILED; 1371 } else { 1372 rc = SMB_LGRP_SUCCESS; 1373 } 1374 1375 return (rc); 1376 } 1377 1378 /* 1379 * smb_lgrp_gtbl_update_mlist 1380 * 1381 * Adds/removes the specified member from the member list of the 1382 * given group 1383 */ 1384 static int 1385 smb_lgrp_gtbl_update_mlist(sqlite *db, char *gname, smb_gsid_t *member, 1386 int flags) 1387 { 1388 smb_lgmlist_t new_members; 1389 smb_lgmlist_t members; 1390 smb_lgmid_t mid; 1391 char *errmsg = NULL; 1392 char *sql; 1393 char **result; 1394 int nrow, ncol; 1395 int rc; 1396 1397 if (db == NULL) 1398 return (SMB_LGRP_DBOPEN_FAILED); 1399 1400 sql = sqlite_mprintf("SELECT n_members, members FROM groups " 1401 "WHERE name = '%s'", gname); 1402 1403 if (sql == NULL) 1404 return (SMB_LGRP_NO_MEMORY); 1405 1406 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1407 sqlite_freemem(sql); 1408 1409 if (rc != SQLITE_OK) { 1410 syslog(LOG_DEBUG, "failed to lookup %s (%s)", 1411 gname, NULL_MSGCHK(errmsg)); 1412 sqlite_freemem(errmsg); 1413 return (SMB_LGRP_LOOKUP_FAILED); 1414 } 1415 1416 if (nrow == 0) { 1417 /* group not found */ 1418 sqlite_free_table(result); 1419 return (SMB_LGRP_NOT_FOUND); 1420 } 1421 1422 if (nrow != 1 || ncol != 2) { 1423 sqlite_free_table(result); 1424 return (SMB_LGRP_DB_ERROR); 1425 } 1426 1427 bzero(&mid, sizeof (mid)); 1428 mid.m_type = member->gs_type; 1429 rc = smb_lgrp_dtbl_getidx(db, member->gs_sid, mid.m_type, 1430 &mid.m_idx, &mid.m_rid); 1431 if (rc != SMB_LGRP_SUCCESS) { 1432 sqlite_free_table(result); 1433 return (rc); 1434 } 1435 1436 members.m_cnt = atoi(result[2]); 1437 members.m_ids = result[3]; 1438 1439 switch (flags) { 1440 case SMB_LGRP_DB_ADDMEMBER: 1441 rc = smb_lgrp_mlist_add(&members, &mid, &new_members); 1442 break; 1443 case SMB_LGRP_DB_DELMEMBER: 1444 rc = smb_lgrp_mlist_del(&members, &mid, &new_members); 1445 break; 1446 default: 1447 rc = SMB_LGRP_INVALID_ARG; 1448 } 1449 1450 sqlite_free_table(result); 1451 if (rc != SMB_LGRP_SUCCESS) 1452 return (rc); 1453 1454 sql = sqlite_mprintf("UPDATE groups SET n_members = %u, members = '%s'" 1455 " WHERE name = '%s'", new_members.m_cnt, new_members.m_ids, gname); 1456 1457 free(new_members.m_ids); 1458 1459 if (sql == NULL) 1460 return (SMB_LGRP_NO_MEMORY); 1461 1462 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1463 sqlite_freemem(sql); 1464 1465 if (rc != SQLITE_OK) { 1466 syslog(LOG_DEBUG, "failed to update %s (%s)", gname, 1467 NULL_MSGCHK(errmsg)); 1468 sqlite_freemem(errmsg); 1469 rc = SMB_LGRP_UPDATE_FAILED; 1470 } else { 1471 rc = SMB_LGRP_SUCCESS; 1472 } 1473 1474 return (rc); 1475 } 1476 1477 /* 1478 * smb_lgrp_gtbl_update_plist 1479 * 1480 * Adds/removes the specified privilege from the privilege list of the 1481 * given group 1482 */ 1483 static int 1484 smb_lgrp_gtbl_update_plist(sqlite *db, char *gname, uint8_t priv_id, 1485 boolean_t enable) 1486 { 1487 char *sql; 1488 char *errmsg = NULL; 1489 char **result; 1490 int nrow, ncol; 1491 int rc; 1492 smb_lgplist_t privs; 1493 smb_lgplist_t new_privs; 1494 1495 if (db == NULL) 1496 return (SMB_LGRP_DBOPEN_FAILED); 1497 1498 sql = sqlite_mprintf("SELECT n_privs, privs FROM groups " 1499 "WHERE name = '%s'", gname); 1500 1501 if (sql == NULL) 1502 return (SMB_LGRP_NO_MEMORY); 1503 1504 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1505 sqlite_freemem(sql); 1506 1507 if (rc != SQLITE_OK) { 1508 syslog(LOG_DEBUG, "failed to lookup %s (%s)", 1509 gname, NULL_MSGCHK(errmsg)); 1510 sqlite_freemem(errmsg); 1511 return (SMB_LGRP_LOOKUP_FAILED); 1512 } 1513 1514 if (nrow == 0) { 1515 /* group not found */ 1516 sqlite_free_table(result); 1517 return (SMB_LGRP_NOT_FOUND); 1518 } 1519 1520 if (nrow != 1 || ncol != 2) { 1521 sqlite_free_table(result); 1522 return (SMB_LGRP_DB_ERROR); 1523 } 1524 1525 privs.p_cnt = atoi(result[2]); 1526 privs.p_ids = (smb_lgpid_t *)result[3]; 1527 1528 if (enable) 1529 rc = smb_lgrp_plist_add(&privs, priv_id, &new_privs); 1530 else 1531 rc = smb_lgrp_plist_del(&privs, priv_id, &new_privs); 1532 1533 sqlite_free_table(result); 1534 if (rc != SMB_LGRP_SUCCESS) 1535 return (rc); 1536 1537 sql = sqlite_mprintf("UPDATE groups SET n_privs = %u, privs = '%q'" 1538 " WHERE name = '%s'", new_privs.p_cnt, (char *)new_privs.p_ids, 1539 gname); 1540 1541 free(new_privs.p_ids); 1542 1543 if (sql == NULL) 1544 return (SMB_LGRP_NO_MEMORY); 1545 1546 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1547 sqlite_freemem(sql); 1548 1549 if (rc != SQLITE_OK) { 1550 syslog(LOG_DEBUG, "failed to update %s (%s)", 1551 gname, NULL_MSGCHK(errmsg)); 1552 sqlite_freemem(errmsg); 1553 rc = SMB_LGRP_UPDATE_FAILED; 1554 } else { 1555 rc = SMB_LGRP_SUCCESS; 1556 } 1557 1558 return (rc); 1559 } 1560 1561 /* 1562 * smb_lgrp_dtbl_insert 1563 * 1564 * Inserts the specified domain SID in the dmain table. 1565 * Upon successful insert the index will be returned in 1566 * 'dom_idx' arg. 1567 */ 1568 static int 1569 smb_lgrp_dtbl_insert(sqlite *db, char *dom_sid, uint32_t *dom_idx) 1570 { 1571 char *errmsg = NULL; 1572 char *sql; 1573 int rc; 1574 1575 sql = sqlite_mprintf("INSERT INTO domains (dom_sid, dom_cnt)" 1576 " VALUES('%s', 1);", dom_sid); 1577 if (sql == NULL) 1578 return (SMB_LGRP_NO_MEMORY); 1579 1580 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1581 sqlite_freemem(sql); 1582 1583 if (rc != SQLITE_OK) { 1584 syslog(LOG_DEBUG, "failed to insert domain SID (%s)", 1585 NULL_MSGCHK(errmsg)); 1586 sqlite_freemem(errmsg); 1587 return (SMB_LGRP_DOMINS_FAILED); 1588 } 1589 1590 if (dom_idx) 1591 *dom_idx = sqlite_last_insert_rowid(db); 1592 return (SMB_LGRP_SUCCESS); 1593 } 1594 1595 /* 1596 * smb_lgrp_dtbl_getidx 1597 * 1598 * Searches the domain table for the domain SID of the 1599 * given member SID. If it finds the domain SID it'll 1600 * return the index and the RID, otherwise it'll insert 1601 * it in the domain table as a new SID. 1602 */ 1603 static int 1604 smb_lgrp_dtbl_getidx(sqlite *db, nt_sid_t *sid, uint16_t sid_type, 1605 uint32_t *dom_idx, uint32_t *rid) 1606 { 1607 char sidstr[NT_SID_FMTBUF_SIZE]; 1608 nt_sid_t *dom_sid; 1609 char **result; 1610 int nrow, ncol; 1611 char *errmsg = NULL; 1612 char *sql; 1613 int rc; 1614 1615 if (nt_sid_is_indomain(smb_lgrp_lsid, sid)) { 1616 /* This is a local SID */ 1617 int id_type = (sid_type == SidTypeUser) 1618 ? SMB_IDMAP_USER : SMB_IDMAP_GROUP; 1619 *dom_idx = SMB_LGRP_LOCAL_IDX; 1620 if (smb_idmap_getid(sid, rid, &id_type) != IDMAP_SUCCESS) 1621 return (SMB_LGRP_INTERNAL_ERROR); 1622 1623 return (SMB_LGRP_SUCCESS); 1624 } 1625 1626 dom_sid = nt_sid_dup(sid); 1627 if (dom_sid == NULL) 1628 return (SMB_LGRP_NO_MEMORY); 1629 1630 (void) nt_sid_split(dom_sid, rid); 1631 nt_sid_format2(dom_sid, sidstr); 1632 free(dom_sid); 1633 1634 sql = sqlite_mprintf("SELECT dom_idx FROM domains WHERE dom_sid = '%s'", 1635 sidstr); 1636 if (sql == NULL) 1637 return (SMB_LGRP_NO_MEMORY); 1638 1639 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1640 sqlite_freemem(sql); 1641 1642 if (rc != SQLITE_OK) { 1643 syslog(LOG_DEBUG, "failed to lookup domain SID (%s)", 1644 NULL_MSGCHK(errmsg)); 1645 sqlite_freemem(errmsg); 1646 return (SMB_LGRP_DOMLKP_FAILED); 1647 } 1648 1649 switch (nrow) { 1650 case 0: 1651 /* new domain SID; insert it into the domains table */ 1652 sqlite_free_table(result); 1653 return (smb_lgrp_dtbl_insert(db, sidstr, dom_idx)); 1654 1655 case 1: 1656 *dom_idx = atoi(result[1]); 1657 sqlite_free_table(result); 1658 return (SMB_LGRP_SUCCESS); 1659 } 1660 1661 sqlite_free_table(result); 1662 return (SMB_LGRP_DB_ERROR); 1663 } 1664 1665 /* 1666 * smb_lgrp_dtbl_getsid 1667 * 1668 * Searchs the domain table for the given domain index. 1669 * Converts the found domain SID to binary format and 1670 * returns it in the 'sid' arg. 1671 * 1672 * Caller must free the returned SID by calling free(). 1673 */ 1674 static int 1675 smb_lgrp_dtbl_getsid(sqlite *db, uint32_t dom_idx, nt_sid_t **sid) 1676 { 1677 char **result; 1678 int nrow, ncol; 1679 char *errmsg = NULL; 1680 char *sql; 1681 int rc; 1682 1683 sql = sqlite_mprintf("SELECT dom_sid FROM domains WHERE dom_idx = %u", 1684 dom_idx); 1685 if (sql == NULL) 1686 return (SMB_LGRP_NO_MEMORY); 1687 1688 rc = sqlite_get_table(db, sql, &result, &nrow, &ncol, &errmsg); 1689 sqlite_freemem(sql); 1690 1691 if (rc != SQLITE_OK) { 1692 syslog(LOG_DEBUG, "failed to lookup domain index (%s)", 1693 NULL_MSGCHK(errmsg)); 1694 sqlite_freemem(errmsg); 1695 return (SMB_LGRP_DOMLKP_FAILED); 1696 } 1697 1698 switch (nrow) { 1699 case 0: 1700 rc = SMB_LGRP_NO_SUCH_DOMAIN; 1701 break; 1702 1703 case 1: 1704 *sid = nt_sid_strtosid(result[1]); 1705 rc = (*sid == NULL) 1706 ? SMB_LGRP_INTERNAL_ERROR : SMB_LGRP_SUCCESS; 1707 break; 1708 1709 default: 1710 rc = SMB_LGRP_DB_ERROR; 1711 break; 1712 } 1713 1714 sqlite_free_table(result); 1715 return (rc); 1716 } 1717 1718 /* 1719 * smb_lgrp_db_setinfo 1720 * 1721 * Initializes the db_info table upon database creation. 1722 */ 1723 static int 1724 smb_lgrp_db_setinfo(sqlite *db) 1725 { 1726 char *errmsg = NULL; 1727 char *sql; 1728 int rc; 1729 1730 sql = sqlite_mprintf("INSERT INTO db_info (ver_major, ver_minor," 1731 " magic) VALUES (%d, %d, %u)", SMB_LGRP_DB_VERMAJOR, 1732 SMB_LGRP_DB_VERMINOR, SMB_LGRP_DB_MAGIC); 1733 1734 if (sql == NULL) 1735 return (SMB_LGRP_NO_MEMORY); 1736 1737 rc = sqlite_exec(db, sql, NULL, NULL, &errmsg); 1738 sqlite_freemem(sql); 1739 if (rc != SQLITE_OK) { 1740 syslog(LOG_DEBUG, "failed to insert database information (%s)", 1741 NULL_MSGCHK(errmsg)); 1742 sqlite_freemem(errmsg); 1743 rc = SMB_LGRP_DBINIT_ERROR; 1744 } else { 1745 rc = SMB_LGRP_SUCCESS; 1746 } 1747 1748 return (rc); 1749 } 1750 1751 /* 1752 * smb_lgrp_mlist_add 1753 * 1754 * Adds the given member (newm) to the input member list (in_members) 1755 * if it's not already there. The result list will be returned in 1756 * out_members. The caller must free the allocated memory for 1757 * out_members by calling free(). 1758 * 1759 * in_members and out_members are hex strings. 1760 */ 1761 static int 1762 smb_lgrp_mlist_add(smb_lgmlist_t *in_members, smb_lgmid_t *newm, 1763 smb_lgmlist_t *out_members) 1764 { 1765 char mid_hex[SMB_LGRP_MID_HEXSZ]; 1766 char *in_list; 1767 char *out_list; 1768 int in_size; 1769 int out_size; 1770 int mid_hexsz; 1771 int i; 1772 1773 out_members->m_cnt = 0; 1774 out_members->m_ids = NULL; 1775 1776 bzero(mid_hex, sizeof (mid_hex)); 1777 mid_hexsz = bintohex((const char *)newm, sizeof (smb_lgmid_t), 1778 mid_hex, sizeof (mid_hex)); 1779 1780 /* 1781 * Check to see if this is already a group member 1782 */ 1783 in_list = in_members->m_ids; 1784 for (i = 0; i < in_members->m_cnt; i++) { 1785 if (strncmp(in_list, mid_hex, mid_hexsz) == 0) 1786 return (SMB_LGRP_MEMBER_IN_GROUP); 1787 in_list += mid_hexsz; 1788 } 1789 1790 in_size = (in_members->m_ids) ? strlen(in_members->m_ids) : 0; 1791 out_size = in_size + sizeof (mid_hex) + 1; 1792 out_list = malloc(out_size); 1793 if (out_list == NULL) 1794 return (SMB_LGRP_NO_MEMORY); 1795 1796 bzero(out_list, out_size); 1797 if (in_members->m_ids) 1798 (void) strlcpy(out_list, in_members->m_ids, out_size); 1799 (void) strcat(out_list, mid_hex); 1800 1801 out_members->m_cnt = in_members->m_cnt + 1; 1802 out_members->m_ids = out_list; 1803 1804 return (SMB_LGRP_SUCCESS); 1805 } 1806 1807 /* 1808 * smb_lgrp_mlist_del 1809 * 1810 * Removes the given member (msid) from the input member list 1811 * (in_members) if it's already there. The result list will b 1812 * returned in out_members. The caller must free the allocated 1813 * memory for out_members by calling free(). 1814 * 1815 * in_members and out_members are hex strings. 1816 */ 1817 static int 1818 smb_lgrp_mlist_del(smb_lgmlist_t *in_members, smb_lgmid_t *mid, 1819 smb_lgmlist_t *out_members) 1820 { 1821 char mid_hex[SMB_LGRP_MID_HEXSZ]; 1822 char *in_list; 1823 char *out_list; 1824 int in_size; 1825 int out_size; 1826 int mid_hexsz; 1827 int out_cnt; 1828 int i; 1829 1830 out_members->m_cnt = 0; 1831 out_members->m_ids = NULL; 1832 1833 if ((in_members == NULL) || (in_members->m_cnt == 0)) 1834 return (SMB_LGRP_MEMBER_NOT_IN_GROUP); 1835 1836 in_size = strlen(in_members->m_ids); 1837 out_size = in_size + sizeof (mid_hex) + 1; 1838 out_list = malloc(out_size); 1839 if (out_list == NULL) 1840 return (SMB_LGRP_NO_MEMORY); 1841 1842 *out_list = '\0'; 1843 1844 bzero(mid_hex, sizeof (mid_hex)); 1845 mid_hexsz = bintohex((const char *)mid, sizeof (smb_lgmid_t), 1846 mid_hex, sizeof (mid_hex)); 1847 1848 in_list = in_members->m_ids; 1849 for (i = 0, out_cnt = 0; i < in_members->m_cnt; i++) { 1850 if (strncmp(in_list, mid_hex, mid_hexsz)) { 1851 (void) strncat(out_list, in_list, mid_hexsz); 1852 out_cnt++; 1853 } 1854 in_list += mid_hexsz; 1855 } 1856 1857 if (out_cnt == in_members->m_cnt) { 1858 free(out_list); 1859 return (SMB_LGRP_MEMBER_NOT_IN_GROUP); 1860 } 1861 1862 out_members->m_cnt = out_cnt; 1863 out_members->m_ids = out_list; 1864 return (SMB_LGRP_SUCCESS); 1865 } 1866 1867 /* 1868 * smb_lgrp_plist_add 1869 * 1870 * Adds the given privilege to the input list (in_privs) 1871 * if it's not already there. The result list is returned 1872 * in out_privs. The caller must free the allocated memory 1873 * for out_privs by calling free(). 1874 */ 1875 static int 1876 smb_lgrp_plist_add(smb_lgplist_t *in_privs, smb_lgpid_t priv_id, 1877 smb_lgplist_t *out_privs) 1878 { 1879 int i, size; 1880 smb_lgpid_t *pbuf; 1881 1882 out_privs->p_cnt = 0; 1883 out_privs->p_ids = NULL; 1884 1885 for (i = 0; i < in_privs->p_cnt; i++) { 1886 if (in_privs->p_ids[i] == priv_id) 1887 return (SMB_LGRP_PRIV_HELD); 1888 } 1889 1890 size = (in_privs->p_cnt + 1) * sizeof (smb_lgpid_t) + 1; 1891 pbuf = malloc(size); 1892 if (pbuf == NULL) 1893 return (SMB_LGRP_NO_MEMORY); 1894 1895 bzero(pbuf, size); 1896 bcopy(in_privs->p_ids, pbuf, in_privs->p_cnt * sizeof (smb_lgpid_t)); 1897 pbuf[in_privs->p_cnt] = priv_id; 1898 1899 out_privs->p_cnt = in_privs->p_cnt + 1; 1900 out_privs->p_ids = pbuf; 1901 1902 return (SMB_LGRP_SUCCESS); 1903 } 1904 1905 /* 1906 * smb_lgrp_plist_del 1907 * 1908 * Removes the given privilege from the input list (in_privs) 1909 * if it's already there. The result list is returned 1910 * in out_privs. The caller must free the allocated memory 1911 * for out_privs by calling free(). 1912 */ 1913 static int 1914 smb_lgrp_plist_del(smb_lgplist_t *in_privs, smb_lgpid_t priv_id, 1915 smb_lgplist_t *out_privs) 1916 { 1917 int i, size; 1918 1919 out_privs->p_cnt = 0; 1920 out_privs->p_ids = NULL; 1921 1922 if ((in_privs == NULL) || (in_privs->p_cnt == 0)) 1923 return (SMB_LGRP_PRIV_NOT_HELD); 1924 1925 size = (in_privs->p_cnt - 1) * sizeof (smb_lgpid_t) + 1; 1926 out_privs->p_ids = malloc(size); 1927 if (out_privs->p_ids == NULL) 1928 return (SMB_LGRP_NO_MEMORY); 1929 1930 bzero(out_privs->p_ids, size); 1931 1932 for (i = 0; i < in_privs->p_cnt; i++) { 1933 if (in_privs->p_ids[i] != priv_id) 1934 out_privs->p_ids[out_privs->p_cnt++] = 1935 in_privs->p_ids[i]; 1936 } 1937 1938 if (out_privs->p_cnt == in_privs->p_cnt) { 1939 free(out_privs->p_ids); 1940 out_privs->p_cnt = 0; 1941 out_privs->p_ids = NULL; 1942 return (SMB_LGRP_PRIV_NOT_HELD); 1943 } 1944 1945 return (SMB_LGRP_SUCCESS); 1946 } 1947 1948 /* 1949 * smb_lgrp_encode_privset 1950 * 1951 * Encodes given privilege set into a buffer to be stored in the group 1952 * database. Each entry of the encoded buffer contains the privilege ID 1953 * of an enable privilege. The returned buffer is null-terminated. 1954 */ 1955 static void 1956 smb_lgrp_encode_privset(smb_group_t *grp, smb_lgplist_t *plist) 1957 { 1958 smb_privset_t *privs; 1959 uint32_t pcnt = plist->p_cnt; 1960 int i; 1961 1962 bzero(plist->p_ids, sizeof (smb_lgpid_t) * plist->p_cnt); 1963 plist->p_cnt = 0; 1964 1965 privs = grp->sg_privs; 1966 if ((privs == NULL) || (privs->priv_cnt == 0)) 1967 return; 1968 1969 if (pcnt < privs->priv_cnt) { 1970 assert(0); 1971 } 1972 1973 for (i = 0; i < privs->priv_cnt; i++) { 1974 if (privs->priv[i].attrs == SE_PRIVILEGE_ENABLED) { 1975 plist->p_ids[plist->p_cnt++] = 1976 (uint8_t)privs->priv[i].luid.lo_part; 1977 } 1978 } 1979 } 1980 1981 /* 1982 * smb_lgrp_decode_privset 1983 * 1984 * Decodes the privilege information read from group table 1985 * (nprivs, privs) into a binray format specified by the 1986 * privilege field of smb_group_t 1987 */ 1988 static int 1989 smb_lgrp_decode_privset(smb_group_t *grp, char *nprivs, char *privs) 1990 { 1991 smb_lgplist_t plist; 1992 int i; 1993 1994 plist.p_cnt = atoi(nprivs); 1995 if (strlen(privs) != plist.p_cnt) 1996 return (SMB_LGRP_BAD_DATA); 1997 1998 plist.p_ids = (smb_lgpid_t *)privs; 1999 grp->sg_privs = smb_privset_new(); 2000 if (grp->sg_privs == NULL) 2001 return (SMB_LGRP_NO_MEMORY); 2002 2003 for (i = 0; i < plist.p_cnt; i++) 2004 smb_privset_enable(grp->sg_privs, plist.p_ids[i]); 2005 2006 return (SMB_LGRP_SUCCESS); 2007 } 2008 2009 /* 2010 * smb_lgrp_decode_members 2011 * 2012 * Decodes the members information read from group table 2013 * (nmembers, members) into a binray format specified by the 2014 * member fields of smb_group_t 2015 */ 2016 static int 2017 smb_lgrp_decode_members(smb_group_t *grp, char *nmembers, char *members, 2018 sqlite *db) 2019 { 2020 smb_lgmid_t *m_ids; 2021 smb_lgmid_t *mid; 2022 smb_gsid_t *member; 2023 int mids_size; 2024 int i, rc; 2025 2026 grp->sg_nmembers = atoi(nmembers); 2027 mids_size = grp->sg_nmembers * sizeof (smb_lgmid_t); 2028 m_ids = malloc(mids_size); 2029 if (m_ids == NULL) 2030 return (SMB_LGRP_NO_MEMORY); 2031 2032 grp->sg_members = malloc(grp->sg_nmembers * sizeof (smb_gsid_t)); 2033 if (grp->sg_members == NULL) { 2034 free(m_ids); 2035 return (SMB_LGRP_NO_MEMORY); 2036 } 2037 2038 (void) hextobin(members, strlen(members), (char *)m_ids, mids_size); 2039 2040 mid = m_ids; 2041 member = grp->sg_members; 2042 for (i = 0; i < grp->sg_nmembers; i++, mid++, member++) { 2043 rc = smb_lgrp_getsid(mid->m_idx, &mid->m_rid, mid->m_type, db, 2044 &member->gs_sid); 2045 if (rc != SMB_LGRP_SUCCESS) { 2046 free(m_ids); 2047 return (SMB_LGRP_DB_ERROR); 2048 } 2049 2050 member->gs_type = mid->m_type; 2051 } 2052 2053 free(m_ids); 2054 return (SMB_LGRP_SUCCESS); 2055 } 2056 2057 /* 2058 * smb_lgrp_decode 2059 * 2060 * Fills out the fields of the given group (grp) based in the 2061 * string information read from the group table. infolvl determines 2062 * which fields are requested and need to be decoded. 2063 * 2064 * Allocated memories must be freed by calling smb_lgrp_free() 2065 * upon successful return. 2066 */ 2067 static int 2068 smb_lgrp_decode(smb_group_t *grp, char **values, int infolvl, sqlite *db) 2069 { 2070 uint32_t sid_idx; 2071 int rc; 2072 2073 if (infolvl == SMB_LGRP_INFO_NONE) 2074 return (SMB_LGRP_SUCCESS); 2075 2076 if (infolvl & SMB_LGRP_INFO_NAME) { 2077 grp->sg_name = strdup(values[SMB_LGRP_GTBL_NAME]); 2078 if (grp->sg_name == NULL) 2079 return (SMB_LGRP_NO_MEMORY); 2080 } 2081 2082 if (infolvl & SMB_LGRP_INFO_CMNT) { 2083 grp->sg_cmnt = strdup(values[SMB_LGRP_GTBL_CMNT]); 2084 if (grp->sg_cmnt == NULL) { 2085 smb_lgrp_free(grp); 2086 return (SMB_LGRP_NO_MEMORY); 2087 } 2088 } 2089 2090 2091 if (infolvl & SMB_LGRP_INFO_SID) { 2092 sid_idx = atoi(values[SMB_LGRP_GTBL_SIDIDX]); 2093 grp->sg_rid = atoi(values[SMB_LGRP_GTBL_SIDRID]); 2094 grp->sg_attr = atoi(values[SMB_LGRP_GTBL_SIDATR]); 2095 grp->sg_id.gs_type = atoi(values[SMB_LGRP_GTBL_SIDTYP]); 2096 rc = smb_lgrp_getsid(sid_idx, &grp->sg_rid, grp->sg_id.gs_type, 2097 db, &grp->sg_id.gs_sid); 2098 if (rc != SMB_LGRP_SUCCESS) { 2099 smb_lgrp_free(grp); 2100 return (SMB_LGRP_NO_MEMORY); 2101 } 2102 grp->sg_domain = (sid_idx == SMB_LGRP_LOCAL_IDX) 2103 ? SMB_LGRP_LOCAL : SMB_LGRP_BUILTIN; 2104 } 2105 2106 if (infolvl & SMB_LGRP_INFO_PRIV) { 2107 rc = smb_lgrp_decode_privset(grp, values[SMB_LGRP_GTBL_NPRIVS], 2108 values[SMB_LGRP_GTBL_PRIVS]); 2109 2110 if (rc != SMB_LGRP_SUCCESS) { 2111 smb_lgrp_free(grp); 2112 return (rc); 2113 } 2114 } 2115 2116 if (infolvl & SMB_LGRP_INFO_MEMB) { 2117 rc = smb_lgrp_decode_members(grp, values[SMB_LGRP_GTBL_NMEMBS], 2118 values[SMB_LGRP_GTBL_MEMBS], db); 2119 if (rc != SMB_LGRP_SUCCESS) { 2120 smb_lgrp_free(grp); 2121 return (rc); 2122 } 2123 } 2124 2125 return (SMB_LGRP_SUCCESS); 2126 } 2127 2128 /* 2129 * smb_lgrp_chkname 2130 * 2131 * User account names are limited to 20 characters and group names are 2132 * limited to 256 characters. In addition, account names cannot be terminated 2133 * by a period and they cannot include commas or any of the following printable 2134 * characters: ", /, \, [, ], :, |, <, >, +, =, ;, ?, *. 2135 * Names also cannot include characters in the range 1-31, which are 2136 * nonprintable. 2137 * 2138 * Source: MSDN, description of NetLocalGroupAdd function. 2139 */ 2140 static boolean_t 2141 smb_lgrp_chkname(char *name) 2142 { 2143 static char *invalid_chars = 2144 "\001\002\003\004\005\006\007\010\011\012\013\014\015\016\017" 2145 "\020\021\022\023\024\025\026\027\030\031" 2146 "\"/\\[]:|<>+=;,*?"; 2147 int len, i; 2148 2149 if (name == NULL || *name == '\0') 2150 return (B_FALSE); 2151 2152 len = strlen(name); 2153 if (len > SMB_LGRP_NAME_MAX) 2154 return (B_FALSE); 2155 2156 if (name[len - 1] == '.') 2157 return (B_FALSE); 2158 2159 for (i = 0; i < len; i++) 2160 if (strchr(invalid_chars, name[i])) 2161 return (B_FALSE); 2162 2163 (void) utf8_strlwr(name); 2164 return (B_TRUE); 2165 } 2166 2167 /* 2168 * smb_lgrp_set_default_privs 2169 * 2170 * set default privileges for Administrators and Backup Operators 2171 */ 2172 static void 2173 smb_lgrp_set_default_privs(smb_group_t *grp) 2174 { 2175 if (utf8_strcasecmp(grp->sg_name, "Administrators") == 0) { 2176 smb_privset_enable(grp->sg_privs, SE_TAKE_OWNERSHIP_LUID); 2177 return; 2178 } 2179 2180 if (utf8_strcasecmp(grp->sg_name, "Backup Operators") == 0) { 2181 smb_privset_enable(grp->sg_privs, SE_BACKUP_LUID); 2182 smb_privset_enable(grp->sg_privs, SE_RESTORE_LUID); 2183 return; 2184 } 2185 } 2186 2187 /* 2188 * smb_lgrp_getsid 2189 * 2190 * Returns a SID based on the provided information 2191 * If dom_idx is 0, it means 'rid' contains a UID/GID and the 2192 * returned SID will be a local SID. If dom_idx is not 0 then 2193 * the domain SID will be fetched from the domain table. 2194 */ 2195 static int 2196 smb_lgrp_getsid(int dom_idx, uint32_t *rid, uint16_t sid_type, 2197 sqlite *db, nt_sid_t **sid) 2198 { 2199 nt_sid_t *dom_sid = NULL; 2200 nt_sid_t *res_sid = NULL; 2201 int id_type; 2202 int rc; 2203 2204 *sid = NULL; 2205 if (dom_idx == SMB_LGRP_LOCAL_IDX) { 2206 id_type = (sid_type == SidTypeUser) 2207 ? SMB_IDMAP_USER : SMB_IDMAP_GROUP; 2208 if (smb_idmap_getsid(*rid, id_type, &res_sid) != IDMAP_SUCCESS) 2209 return (SMB_LGRP_NO_SID); 2210 2211 /* 2212 * Make sure the returned SID is local 2213 */ 2214 if (!nt_sid_is_indomain(smb_lgrp_lsid, res_sid)) { 2215 free(res_sid); 2216 return (SMB_LGRP_SID_NOTLOCAL); 2217 } 2218 2219 (void) nt_sid_get_rid(res_sid, rid); 2220 *sid = res_sid; 2221 return (SMB_LGRP_SUCCESS); 2222 } 2223 2224 rc = smb_lgrp_dtbl_getsid(db, dom_idx, &dom_sid); 2225 if (rc != SMB_LGRP_SUCCESS) 2226 return (SMB_LGRP_DB_ERROR); 2227 2228 res_sid = nt_sid_splice(dom_sid, *rid); 2229 free(dom_sid); 2230 if (res_sid == NULL) 2231 return (SMB_LGRP_NO_MEMORY); 2232 2233 *sid = res_sid; 2234 return (SMB_LGRP_SUCCESS); 2235 } 2236