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