smb_lgrp.c revision 36a00406f380da1f3fd86e1a6af2de4d9f64633c
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
*/
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <syslog.h>
#include <thread.h>
#include <synch.h>
#include <grp.h>
#include <assert.h>
#include <libintl.h>
#include <smb_sqlite.h>
/*
* Local domain SID (aka machine SID) is not stored in the domain table
* therefore the index is 0
*/
#define SMB_LGRP_LOCAL_IDX 0
#define SMB_LGRP_BUILTIN_IDX 1
#define SMB_LGRP_DB_NAME "/var/smb/smbgroup.db"
#define SMB_LGRP_DB_VERMAJOR 1
#define SMB_LGRP_DB_VERMINOR 0
#define SMB_LGRP_DB_ADDMEMBER 1
#define SMB_LGRP_DB_DELMEMBER 2
/*
* members column of the groups table is an array of
* member structure smb_lgmid_t defined below.
*
* privs column of the groups table is an array of bytes
* where each byte is the id of an enable privilege
*/
#define SMB_LGRP_DB_SQL \
"CREATE TABLE db_info (" \
" ver_major INTEGER," \
" ver_minor INTEGER," \
" magic INTEGER" \
");" \
"" \
"CREATE TABLE domains (" \
" dom_idx INTEGER PRIMARY KEY," \
" dom_sid TEXT UNIQUE," \
" dom_cnt INTEGER" \
");" \
"" \
"CREATE UNIQUE INDEX domsid_idx ON domains (dom_sid);" \
"" \
"CREATE TABLE groups (" \
" name TEXT PRIMARY KEY," \
" sid_idx INTEGER," \
" sid_rid INTEGER," \
" sid_type INTEGER," \
" sid_attrs INTEGER," \
" comment TEXT," \
" n_privs INTEGER," \
" privs BLOB," \
" n_members INTEGER," \
" members BLOB" \
");" \
"" \
"CREATE INDEX grprid_idx ON groups (sid_rid);"
/*
* Number of groups table columns
*/
#define SMB_LGRP_GTBL_NCOL 10
#define SMB_LGRP_GTBL_NAME 0
#define SMB_LGRP_GTBL_SIDIDX 1
#define SMB_LGRP_GTBL_SIDRID 2
#define SMB_LGRP_GTBL_SIDTYP 3
#define SMB_LGRP_GTBL_SIDATR 4
#define SMB_LGRP_GTBL_CMNT 5
#define SMB_LGRP_GTBL_NPRIVS 6
#define SMB_LGRP_GTBL_PRIVS 7
#define SMB_LGRP_GTBL_NMEMBS 8
#define SMB_LGRP_GTBL_MEMBS 9
#define SMB_LGRP_INFO_NONE 0x00
#define SMB_LGRP_INFO_NAME 0x01
#define SMB_LGRP_INFO_CMNT 0x02
#define SMB_LGRP_INFO_SID 0x04
#define SMB_LGRP_INFO_PRIV 0x08
#define SMB_LGRP_INFO_MEMB 0x10
#define SMB_LGRP_INFO_ALL 0x1F
#define SMB_LGRP_PGRP_GRPTMP "/etc/gtmp"
#define SMB_LGRP_PGRP_GRPBUFSIZ 5120
#define SMB_LGRP_PGRP_GROUP "/etc/group"
#define SMB_LGRP_PGRP_NOTUNIQUE 0
#define SMB_LGRP_PGRP_RESERVED 1
#define SMB_LGRP_PGRP_UNIQUE 2
#define SMB_LGRP_PGRP_TOOBIG 3
#define SMB_LGRP_PGRP_INVALID 4
/* Member ID */
typedef struct smb_lgmid {
} smb_lgmid_t;
#define SMB_LGRP_MID_HEXSZ 32
/* Member list */
typedef struct smb_lgmlist {
char *m_ids;
/* Privilege ID */
typedef uint8_t smb_lgpid_t;
/* Privilege list */
typedef struct smb_lgplist {
static struct {
int errnum;
char *errmsg;
} errtab[] = {
{ SMB_LGRP_SUCCESS, "success" },
{ SMB_LGRP_INVALID_ARG, "invalid argument" },
{ SMB_LGRP_INVALID_MEMBER, "invalid member type" },
{ SMB_LGRP_INVALID_NAME, "invalid name" },
{ SMB_LGRP_NOT_FOUND, "group not found" },
{ SMB_LGRP_EXISTS, "group exists" },
{ SMB_LGRP_NO_SID, "cannot obtain a SID" },
{ SMB_LGRP_NO_LOCAL_SID, "cannot get the machine SID" },
{ SMB_LGRP_SID_NOTLOCAL, "local account has non-local SID" },
"operation not permitted on well-known account" },
{ SMB_LGRP_NO_MEMORY, "not enough memory" },
{ SMB_LGRP_DB_ERROR, "database operation error" },
{ SMB_LGRP_DBINIT_ERROR, "database initialization error" },
{ SMB_LGRP_INTERNAL_ERROR, "internal error" },
{ SMB_LGRP_MEMBER_IN_GROUP, "member already in group" },
{ SMB_LGRP_MEMBER_NOT_IN_GROUP, "not a member" },
{ SMB_LGRP_NO_SUCH_PRIV, "no such privilege" },
{ SMB_LGRP_NO_SUCH_DOMAIN, "no such domain SID" },
{ SMB_LGRP_PRIV_HELD, "privilege already held" },
{ SMB_LGRP_PRIV_NOT_HELD, "privilege not held" },
{ SMB_LGRP_BAD_DATA, "bad data" },
{ SMB_LGRP_NO_MORE, "no more groups" },
{ SMB_LGRP_DBOPEN_FAILED, "database open failed" },
{ SMB_LGRP_DBEXEC_FAILED, "database operation failed" },
{ SMB_LGRP_DBINIT_FAILED, "database initialization failed" },
{ SMB_LGRP_DOMLKP_FAILED, "domain SID lookup failed" },
{ SMB_LGRP_DOMINS_FAILED, "domain SID insert failed" },
{ SMB_LGRP_INSERT_FAILED, "group insert failed" },
{ SMB_LGRP_DELETE_FAILED, "group delete failed" },
{ SMB_LGRP_UPDATE_FAILED, "group update failed" },
{ SMB_LGRP_LOOKUP_FAILED, "group lookup failed" },
{ SMB_LGRP_OFFLINE, "local group service is offline" },
{ SMB_LGRP_POSIXCREATE_FAILED, "posix group create failed" }
};
/*
* Serialization for the local group API.
*/
typedef struct {
static smb_localgrp_t smb_localgrp;
static boolean_t smb_lgrp_enter(void);
static void smb_lgrp_exit(void);
static int smb_lgrp_db_init(void);
static sqlite *smb_lgrp_db_open(int);
static void smb_lgrp_db_close(sqlite *);
static int smb_lgrp_db_setinfo(sqlite *);
static int smb_lgrp_gtbl_delete(sqlite *, char *);
static int smb_lgrp_gtbl_count(sqlite *, int, int *);
static int smb_lgrp_decode_privset(smb_group_t *, char *, char *);
static void smb_lgrp_set_default_privs(smb_group_t *);
static boolean_t smb_lgrp_normalize_name(char *);
static boolean_t smb_lgrp_exists(char *);
static int smb_lgrp_pgrp_add(char *);
/*
* smb_lgrp_add
*
* Create a local group with the given name and comment.
* This new group doesn't have any members and no enabled
* privileges.
*
* No well-known accounts can be added other than Administators,
* Backup Operators and Power Users. These built-in groups
* won't have any members when created but a set of default
* privileges will be enabled for them.
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
return (SMB_LGRP_INVALID_ARG);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
if (smb_lgrp_pgrp_add(gname) != 0) {
return (SMB_LGRP_POSIXCREATE_FAILED);
}
return (SMB_LGRP_NOT_FOUND);
}
}
/*
* Make sure a local SID can be obtained
*/
!= IDMAP_SUCCESS) {
return (SMB_LGRP_NO_SID);
}
return (SMB_LGRP_SID_NOTLOCAL);
}
} else {
/* cannot add well-known accounts */
return (SMB_LGRP_WKSID);
}
return (SMB_LGRP_NO_MEMORY);
}
}
return (SMB_LGRP_EXISTS);
}
return (rc);
}
/*
* smb_lgrp_rename
*
* Renames the given group
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
return (SMB_LGRP_SUCCESS);
/* Cannot rename well-known groups */
return (SMB_LGRP_WKSID);
/* Cannot rename to a well-known groups */
return (SMB_LGRP_WKSID);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
if (smb_lgrp_pgrp_add(new_gname) != 0) {
return (SMB_LGRP_POSIXCREATE_FAILED);
}
return (SMB_LGRP_NOT_FOUND);
}
}
return (rc);
}
/*
* smb_lgrp_delete
*
* Deletes the specified local group.
*/
int
smb_lgrp_delete(char *gname)
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
/* Cannot remove a built-in group */
return (SMB_LGRP_WKSID);
if (!smb_lgrp_exists(gname))
return (SMB_LGRP_NOT_FOUND);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (rc);
}
/*
* smb_lgrp_setcmnt
*
* Sets the description for the given group
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
return (SMB_LGRP_INVALID_ARG);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (rc);
}
/*
* smb_lgrp_getcmnt
*
* Obtain the description of the specified group
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
return (SMB_LGRP_INVALID_ARG);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
if (rc == SMB_LGRP_SUCCESS) {
smb_lgrp_free(&grp);
}
return (rc);
}
/*
* smb_lgrp_setpriv
*
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
return (SMB_LGRP_NO_SUCH_PRIV);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
if (enable) {
if (rc == SMB_LGRP_PRIV_HELD)
} else {
if (rc == SMB_LGRP_PRIV_NOT_HELD)
}
return (rc);
}
/*
* smb_lgrp_getpriv
*
* Obtain the status of the specified privilge for the group
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
return (SMB_LGRP_NO_SUCH_PRIV);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
if (rc == SMB_LGRP_SUCCESS) {
smb_lgrp_free(&grp);
}
return (rc);
}
/*
* smb_lgrp_add_member
*
* Add the given account to the specified group as its member.
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (!smb_sid_isvalid(msid))
return (SMB_LGRP_INVALID_ARG);
if (!smb_lgrp_chkmember(sid_type))
return (SMB_LGRP_INVALID_MEMBER);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (rc);
}
/*
* smb_lgrp_del_member
*
* Delete the specified member from the given group.
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (!smb_sid_isvalid(msid))
return (SMB_LGRP_INVALID_ARG);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (rc);
}
/*
* smb_lgrp_getbyname
*
* Retrieves the information of the group specified by
* the given name.
*
* Note that this function doesn't allocate the group
* structure itself only the fields, so the given grp
* pointer has to point to a group structure.
* Caller must free the allocated memories for the fields
* by calling smb_lgrp_free().
*/
int
{
int rc;
if (!smb_lgrp_normalize_name(gname))
return (SMB_LGRP_INVALID_NAME);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (rc);
}
/*
* smb_lgrp_getbyrid
*
* Retrieves the information of the group specified by
* the given RID and domain type.
*
* Note that this function doesn't allocate the group
* structure itself only the fields, so the given grp
* pointer has to point to a group structure.
* Caller must free the allocated memories for the fields
* by calling smb_lgrp_free().
*
* If grp is NULL no information would be returned. The
* return value of SMB_LGRP_SUCCESS will indicate that a
* group with the given information exists.
*/
int
{
int infolvl = SMB_LGRP_INFO_ALL;
int rc;
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
}
return (rc);
}
/*
* smb_lgrp_numbydomain
*
* Returns the number of groups in the given domain in the
* arg 'count'
*/
int
{
int dom_idx;
int rc;
switch (dom_type) {
case SMB_DOMAIN_LOCAL:
break;
case SMB_DOMAIN_BUILTIN:
break;
default:
*count = 0;
return (SMB_LGRP_INVALID_ARG);
}
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (rc);
}
/*
* smb_lgrp_free
*
* Frees the allocated memory for the fields of the given
* group structure. Note that this function doesn't free
* the group itself.
*/
void
{
int i;
return;
for (i = 0; i < grp->sg_nmembers; i++)
}
/*
* smb_lgrp_iteropen
*
* Initializes the given group iterator by opening
* the group database and creating a virtual machine
* for iteration.
*/
int
{
char *sql;
int rc = SMB_LGRP_SUCCESS;
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
return (SMB_LGRP_NO_MEMORY);
}
return (SMB_LGRP_DBOPEN_FAILED);
}
}
return (rc);
}
/*
* smb_lgrp_iterclose
*
* Closes the given group iterator.
*/
void
{
int rc;
if (!smb_lgrp_enter())
return;
}
}
/*
* Returns B_TRUE if there has been an error during
* iteration.
*/
{
}
/*
* smb_lgrp_iterate
*
* Iterate through group database
* Group information is returned in provided group structure.
*
* Note that this function doesn't allocate the group
* structure itself only the fields, so the given grp
* pointer has to point to a group structure.
* Caller must free the allocated memories for the fields
* by calling smb_lgrp_free().
*/
int
{
const char **values;
int ncol;
int rc;
int i;
return (SMB_LGRP_INVALID_ARG);
if (!smb_lgrp_enter())
return (SMB_LGRP_OFFLINE);
for (;;) {
if (rc == SQLITE_DONE) {
return (SMB_LGRP_NO_MORE);
}
if (rc != SQLITE_ROW) {
return (SMB_LGRP_DBEXEC_FAILED);
}
if (ncol != SMB_LGRP_GTBL_NCOL) {
return (SMB_LGRP_DB_ERROR);
}
for (i = 0; i < ncol; i++) {
return (SMB_LGRP_DB_ERROR);
}
}
if (rc == SMB_LGRP_SUCCESS)
break;
}
return (rc);
}
/*
* smb_lgrp_is_member
*
* Check to see if the specified account is a member of
* the given group.
*/
{
int i;
return (B_FALSE);
for (i = 0; i < grp->sg_nmembers; i++) {
return (B_TRUE);
}
return (B_FALSE);
}
/*
* smb_lgrp_strerror
*
* Returns a text for the given group error code.
*/
char *
smb_lgrp_strerror(int errnum)
{
int i;
for (i = 0; i < nerr; ++i) {
}
return ("unknown local group error");
}
/*
* smb_lgrp_err_to_ntstatus
*
* This routine maps Local group operation errors to NT Status error codes.
*/
{
int i;
static struct err_map {
} err_map[] = {
};
}
return (NT_STATUS_INTERNAL_ERROR);
}
/*
* smb_lgrp_chkmember
*
* Determines valid account types for being member of
* a local group. We really have no business trying to
* keep track of the "type" of SIDs in a group, so just
* validate that the SID type is a known enum value.
*/
static boolean_t
{
switch (sid_type) {
case SidTypeNull:
case SidTypeUser:
case SidTypeGroup:
case SidTypeAlias:
case SidTypeWellKnownGroup:
case SidTypeDeletedAccount:
case SidTypeInvalid:
case SidTypeUnknown:
return (B_TRUE);
}
return (B_FALSE);
}
/*
* smb_lgrp_start
*
* Initializes the library private global variables.
* Create the database, if it doesn't exist, and add
* the predefined builtin groups.
*/
int
smb_lgrp_start(void)
{
static char *builtin[] = {
"Administrators",
"Backup Operators",
"Power Users"
};
char *localsid;
int i, rc;
return (SMB_LGRP_NO_LOCAL_SID);
}
return (SMB_LGRP_NO_LOCAL_SID);
}
rc = smb_lgrp_db_init();
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
for (i = 0; i < ngrp; i++) {
continue;
if (rc != SMB_LGRP_SUCCESS) {
}
}
}
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_stop
*
* Unintialize the library global private variables.
*/
void
smb_lgrp_stop(void)
{
if (!smb_localgrp.lg_online)
return;
while (smb_localgrp.lg_refcnt > 0)
}
static boolean_t
smb_lgrp_enter(void)
{
if (smb_localgrp.lg_online)
return (status);
}
static void
smb_lgrp_exit(void)
{
if ((--smb_localgrp.lg_refcnt) == 0)
}
/*
* smb_lgrp_db_open
*
* Opens group database with the given mode.
*/
static sqlite *
smb_lgrp_db_open(int mode)
{
}
return (db);
}
/*
* smb_lgrp_db_close
*
* Closes the given database handle
*/
static void
{
if (db) {
}
}
/*
* smb_lgrp_db_init
*
* Creates the group database based on the defined SQL statement.
* It also initializes db_info and domain tables.
*/
static int
smb_lgrp_db_init(void)
{
int rc = SMB_LGRP_SUCCESS;
return (SMB_LGRP_DBOPEN_FAILED);
}
return (SMB_LGRP_DBEXEC_FAILED);
}
case SQLITE_ERROR:
/*
* This is the normal situation: CREATE probably failed because
* tables already exist. It may indicate an error in SQL as well
* but we cannot tell.
*/
&errmsg);
break;
case SQLITE_OK:
&errmsg);
break;
NULL);
if (rc == SMB_LGRP_SUCCESS)
if (rc != SMB_LGRP_SUCCESS) {
(void) sqlite_close(db);
(void) unlink(SMB_LGRP_DB_NAME);
return (rc);
}
break;
default:
"failed to initialize group database (%s)", errmsg);
&errmsg);
break;
}
/* this is bad - database may be left in a locked state */
}
(void) sqlite_close(db);
return (rc);
}
/*
* smb_lgrp_gtbl_lookup
*
* This is a flexible lookup function for the group database.
* The key type can be specified by the 'key' arg and the actual key
* values can be passed after the 'infolvl' arg. 'infolvl' arg specifies
* what information items for the specified group is needed.
*
* Note that the function assumes the given key is unique and only
* specifies one or 0 group. The keys that are supported now are
* the group name and the group SID
*
* Note that this function doesn't allocate the group
* structure itself only the fields, so the given grp
* pointer has to point to a group structure.
* Caller must free the allocated memories for the fields
* by calling smb_lgrp_free().
*/
static int
{
char *sql;
char **result;
return (SMB_LGRP_DBOPEN_FAILED);
switch (key) {
case SMB_LGRP_GTBL_NAME:
break;
case SMB_LGRP_GTBL_SIDRID:
/* need to map the given rid to a gid */
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
} else {
}
"WHERE (sid_idx = %d) AND (sid_rid = %u)",
break;
default:
return (SMB_LGRP_INVALID_ARG);
}
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_LOOKUP_FAILED);
}
if (nrow == 0) {
/* group not found */
return (SMB_LGRP_NOT_FOUND);
}
return (SMB_LGRP_DB_ERROR);
}
return (rc);
}
/*
* smb_lgrp_gtbl_exists
*
* Checks to see if the given group exists or not.
*/
static boolean_t
{
char *sql;
char **result;
int rc;
return (NULL);
gname);
return (B_FALSE);
}
return (nrow != 0);
}
/*
* smb_lgrp_gtbl_count
*
* Counts the number of groups in the domain specified by
* 'dom_idx'
*/
static int
{
char *sql;
char **result;
int rc;
*count = 0;
return (SMB_LGRP_DBOPEN_FAILED);
dom_idx);
return (SMB_LGRP_LOOKUP_FAILED);
}
if (ncol > 1)
return (SMB_LGRP_DB_ERROR);
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_gtbl_insert
*
* Insert a record for the given group in the group database.
*
* NOTE: this function assumes that this group has no members
* at this time.
*/
static int
{
char *sql;
int dom_idx;
int rc;
return (SMB_LGRP_DBOPEN_FAILED);
"(name, sid_idx, sid_rid, sid_type, sid_attrs, comment, "
"n_privs, privs, n_members, members) "
"VALUES('%s', %u, %u, %u, %u, '%q', %u, '%q', %u, '%q')",
return (SMB_LGRP_NO_MEMORY);
} else {
}
return (rc);
}
/*
* smb_lgrp_gtbl_delete
*
* Removes the specified group from the database
*/
static int
{
char *sql;
int rc;
return (SMB_LGRP_DBOPEN_FAILED);
return (SMB_LGRP_NO_MEMORY);
} else {
}
return (rc);
}
/*
* smb_lgrp_gtbl_update
*
* Updates the specified group information, the supported items
* are group name and comment
*/
static int
{
char *sql;
int rc;
return (SMB_LGRP_DBOPEN_FAILED);
/* UPDATE doesn't fail if gname doesn't exist */
return (SMB_LGRP_NOT_FOUND);
switch (col_id) {
case SMB_LGRP_GTBL_NAME:
return (SMB_LGRP_EXISTS);
break;
case SMB_LGRP_GTBL_CMNT:
break;
default:
return (SMB_LGRP_INVALID_ARG);
}
return (SMB_LGRP_NO_MEMORY);
} else {
}
return (rc);
}
/*
* smb_lgrp_gtbl_update_mlist
*
* given group
*/
static int
int flags)
{
char *sql;
char **result;
int rc;
return (SMB_LGRP_DBOPEN_FAILED);
"WHERE name = '%s'", gname);
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_LOOKUP_FAILED);
}
if (nrow == 0) {
/* group not found */
return (SMB_LGRP_NOT_FOUND);
}
return (SMB_LGRP_DB_ERROR);
}
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
switch (flags) {
case SMB_LGRP_DB_ADDMEMBER:
break;
case SMB_LGRP_DB_DELMEMBER:
break;
default:
}
if (rc != SMB_LGRP_SUCCESS)
return (rc);
return (SMB_LGRP_NO_MEMORY);
} else {
}
return (rc);
}
/*
* smb_lgrp_gtbl_update_plist
*
* given group
*/
static int
{
char *sql;
char **result;
int rc;
return (SMB_LGRP_DBOPEN_FAILED);
"WHERE name = '%s'", gname);
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_LOOKUP_FAILED);
}
if (nrow == 0) {
/* group not found */
return (SMB_LGRP_NOT_FOUND);
}
return (SMB_LGRP_DB_ERROR);
}
if (enable)
else
if (rc != SMB_LGRP_SUCCESS)
return (rc);
gname);
return (SMB_LGRP_NO_MEMORY);
} else {
}
return (rc);
}
/*
* smb_lgrp_dtbl_insert
*
* Inserts the specified domain SID in the dmain table.
* Upon successful insert the index will be returned in
* 'dom_idx' arg.
*/
static int
{
char *sql;
int rc;
" VALUES('%s', 1);", dom_sid);
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_DOMINS_FAILED);
}
if (dom_idx)
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_dtbl_getidx
*
* Searches the domain table for the domain SID of the
* given member SID. If it finds the domain SID it'll
* return the index and the RID, otherwise it'll insert
* it in the domain table as a new SID.
*/
static int
{
char sidstr[SMB_SID_STRSZ];
char **result;
char *sql;
int rc;
/* This is a local SID */
return (SMB_LGRP_INTERNAL_ERROR);
return (SMB_LGRP_SUCCESS);
}
return (SMB_LGRP_NO_MEMORY);
sidstr);
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_DOMLKP_FAILED);
}
switch (nrow) {
case 0:
/* new domain SID; insert it into the domains table */
case 1:
return (SMB_LGRP_SUCCESS);
}
return (SMB_LGRP_DB_ERROR);
}
/*
* smb_lgrp_dtbl_getsid
*
* Searchs the domain table for the given domain index.
* Converts the found domain SID to binary format and
* returns it in the 'sid' arg.
*
* Caller must free the returned SID by calling free().
*/
static int
{
char **result;
char *sql;
int rc;
dom_idx);
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_DOMLKP_FAILED);
}
switch (nrow) {
case 0:
break;
case 1:
break;
default:
break;
}
return (rc);
}
/*
* smb_lgrp_db_setinfo
*
* Initializes the db_info table upon database creation.
*/
static int
{
char *sql;
int rc;
" magic) VALUES (%d, %d, %u)", SMB_LGRP_DB_VERMAJOR,
return (SMB_LGRP_NO_MEMORY);
} else {
}
return (rc);
}
/*
* smb_lgrp_mlist_add
*
* Adds the given member (newm) to the input member list (in_members)
* if it's not already there. The result list will be returned in
* out_members. The caller must free the allocated memory for
* out_members by calling free().
*
* in_members and out_members are hex strings.
*/
static int
{
char mid_hex[SMB_LGRP_MID_HEXSZ];
char *in_list;
char *out_list;
int in_size;
int out_size;
int mid_hexsz;
int i;
out_members->m_cnt = 0;
/*
* Check to see if this is already a group member
*/
for (i = 0; i < in_members->m_cnt; i++) {
return (SMB_LGRP_MEMBER_IN_GROUP);
}
return (SMB_LGRP_NO_MEMORY);
if (in_members->m_ids)
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_mlist_del
*
* Removes the given member (msid) from the input member list
* (in_members) if it's already there. The result list will b
* returned in out_members. The caller must free the allocated
* memory for out_members by calling free().
*
* in_members and out_members are hex strings.
*/
static int
{
char mid_hex[SMB_LGRP_MID_HEXSZ];
char *in_list;
char *out_list;
int in_size;
int out_size;
int mid_hexsz;
int out_cnt;
int i;
out_members->m_cnt = 0;
return (SMB_LGRP_MEMBER_NOT_IN_GROUP);
return (SMB_LGRP_NO_MEMORY);
*out_list = '\0';
out_cnt++;
}
}
return (SMB_LGRP_MEMBER_NOT_IN_GROUP);
}
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_plist_add
*
* Adds the given privilege to the input list (in_privs)
* if it's not already there. The result list is returned
* in out_privs. The caller must free the allocated memory
* for out_privs by calling free().
*/
static int
{
int i, size;
return (SMB_LGRP_PRIV_HELD);
}
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_plist_del
*
* Removes the given privilege from the input list (in_privs)
* if it's already there. The result list is returned
* in out_privs. The caller must free the allocated memory
* for out_privs by calling free().
*/
static int
{
int i, size;
return (SMB_LGRP_PRIV_NOT_HELD);
return (SMB_LGRP_NO_MEMORY);
}
return (SMB_LGRP_PRIV_NOT_HELD);
}
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_encode_privset
*
* Encodes given privilege set into a buffer to be stored in the group
* database. Each entry of the encoded buffer contains the privilege ID
* of an enable privilege. The returned buffer is null-terminated.
*/
static void
{
int i;
return;
assert(0);
}
}
}
}
/*
* smb_lgrp_decode_privset
*
* Decodes the privilege information read from group table
* (nprivs, privs) into a binray format specified by the
* privilege field of smb_group_t
*/
static int
{
int i;
return (SMB_LGRP_BAD_DATA);
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_decode_members
*
* Decodes the members information read from group table
* (nmembers, members) into a binary format specified by the
* member fields of smb_group_t
*/
static int
{
int m_num;
int mids_size;
int i, rc;
grp->sg_nmembers = 0;
return (SMB_LGRP_NO_MEMORY);
return (SMB_LGRP_NO_MEMORY);
}
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
}
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_decode
*
* Fills out the fields of the given group (grp) based in the
* string information read from the group table. infolvl determines
* which fields are requested and need to be decoded.
*
* Allocated memories must be freed by calling smb_lgrp_free()
* upon successful return.
*/
static int
{
int rc;
if (infolvl == SMB_LGRP_INFO_NONE)
return (SMB_LGRP_SUCCESS);
if (infolvl & SMB_LGRP_INFO_NAME) {
return (SMB_LGRP_NO_MEMORY);
}
if (infolvl & SMB_LGRP_INFO_CMNT) {
return (SMB_LGRP_NO_MEMORY);
}
}
if (infolvl & SMB_LGRP_INFO_SID) {
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
}
if (infolvl & SMB_LGRP_INFO_PRIV) {
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
}
if (infolvl & SMB_LGRP_INFO_MEMB) {
if (rc != SMB_LGRP_SUCCESS) {
return (rc);
}
}
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_normalize_name
*
* Trim whitespace, validate the group name and convert it to lowercase.
*/
static boolean_t
smb_lgrp_normalize_name(char *name)
{
(void) trim_whitespace(name);
return (B_FALSE);
(void) smb_strlwr(name);
return (B_TRUE);
}
/*
* smb_lgrp_set_default_privs
*
* set default privileges for Administrators and Backup Operators
*/
static void
{
return;
}
return;
}
}
/*
* smb_lgrp_getsid
*
* Returns a SID based on the provided information
* returned SID will be a local SID. If dom_idx is not 0 then
* the domain SID will be fetched from the domain table.
*/
static int
{
int id_type;
int rc;
if (dom_idx == SMB_LGRP_LOCAL_IDX) {
if (stat != IDMAP_SUCCESS) {
"failed to get a SID for %s id=%u (%d)",
return (SMB_LGRP_NO_SID);
}
/*
* Make sure the returned SID is local
*/
"local %s (%u) is mapped to a non-local SID",
*rid);
return (SMB_LGRP_SID_NOTLOCAL);
}
return (SMB_LGRP_SUCCESS);
}
if (rc != SMB_LGRP_SUCCESS) {
return (SMB_LGRP_DB_ERROR);
}
return (SMB_LGRP_NO_MEMORY);
}
return (SMB_LGRP_SUCCESS);
}
/*
* smb_lgrp_getgid
*
* Converts given local RID to a local gid since for user
* defined local groups, gid is stored in the table.
*/
static int
{
int idtype;
int rc;
return (SMB_LGRP_NO_MEMORY);
}
/*
* smb_lgrp_exists
*
* Returns B_TRUE if the local group with the given name exists.
* Otherwise, returns B_FALSE.
*/
static boolean_t
smb_lgrp_exists(char *gname)
{
if (!smb_lgrp_normalize_name(gname))
return (B_FALSE);
return (B_FALSE);
return (rc);
}
/*
* smb_lgrp_pgrp_valid_gname
*
* Validate posix group name string.
*/
static int
smb_lgrp_pgrp_valid_gname(char *group)
{
char c;
int len = 0;
int badchar = 0;
return (SMB_LGRP_PGRP_INVALID);
len++;
return (SMB_LGRP_PGRP_INVALID);
badchar++;
}
return (SMB_LGRP_PGRP_INVALID);
return (SMB_LGRP_PGRP_NOTUNIQUE);
return (SMB_LGRP_PGRP_UNIQUE);
}
/*
* smb_lgrp_pgrp_valid_gid
*
* Check to see that the gid is not a reserved gid
* -- nobody (60001), noaccess (60002) or nogroup (65534)
*/
static int
{
}
/*
* smb_lgrp_pgrp_findnextgid(void)
*
* This method finds the next valid GID.
* It sorts the used GIDs in decreasing order to return MAXUSED + 1.
* It then adds one to obtain the next valid GID.
* On failure, -1 is returned. On success, a valid GID is returned.
*/
static int
{
int gid;
"r")) == NULL)
return (-1);
return (SMB_LGRP_PGRP_DEFRID + 1);
}
gid = -1;
do {
if (!smb_lgrp_pgrp_valid_gid(next))
continue;
if (next <= SMB_LGRP_PGRP_DEFRID) {
break;
}
gid++;
break;
}
gid = -1;
return (gid);
}
/*
* smb_lgrp_pgrp_add
*
* Create a posix group with the given name.
*/
static int
smb_lgrp_pgrp_add(char *group)
{
int newdone = 0;
char buf[SMB_LGRP_PGRP_GRPBUFSIZ];
int rc = 0;
return (-1);
if ((gret = smb_lgrp_pgrp_findnextgid()) < 0)
return (-1);
return (-1);
return (-1);
}
(void) unlink(SMB_LGRP_PGRP_GRPTMP);
return (-1);
}
(void) unlink(SMB_LGRP_PGRP_GRPTMP);
return (-1);
}
/* Check for NameService reference */
newdone = 1;
}
}
if (!newdone)
(void) unlink(SMB_LGRP_PGRP_GRPTMP);
return (-1);
}
return (0);
}