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