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