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