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