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