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