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