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