#include <string.h>
#include <syslog.h>
#include <smbsrv/string.h>
#include <smbsrv/libsmb.h>
#include <smbsrv/smb_privilege.h>
static char *smb_priv_getname(uint32_t id);
static smb_privinfo_t priv_table[] = {
{ 0, "", "", 0 },
{ 1, "", "", 0 },
{ 2, SE_CREATE_TOKEN_NAME, "Create a token object", 0 },
{ 3, SE_ASSIGNPRIMARYTOKEN_NAME, "Replace a process level token", 0 },
{ 4, SE_LOCK_MEMORY_NAME, "Lock pages in memory", 0 },
{ 5, SE_INCREASE_QUOTA_NAME, "Increase quotas", 0 },
{ 6, SE_MACHINE_ACCOUNT_NAME, "Add workstations to domain", 0 },
{ 7, SE_TCB_NAME, "Act as part of the operating system", 0 },
{ 8, SE_SECURITY_NAME, "Manage auditing and security log", 0 },
{ 9, SE_TAKE_OWNERSHIP_NAME,
"Take ownership of files or other objects", PF_PRESENTABLE },
{ 10, SE_LOAD_DRIVER_NAME, "Load and unload device drivers", 0 },
{ 11, SE_SYSTEM_PROFILE_NAME, "Profile system performance", 0 },
{ 12, SE_SYSTEMTIME_NAME, "Change the system time", 0 },
{ 13, SE_PROF_SINGLE_PROCESS_NAME, "Profile single process", 0 },
{ 14, SE_INC_BASE_PRIORITY_NAME, "Increase scheduling priority", 0 },
{ 15, SE_CREATE_PAGEFILE_NAME, "Create a pagefile", 0 },
{ 16, SE_CREATE_PERMANENT_NAME, "Create permanent shared objects", 0 },
{ 17, SE_BACKUP_NAME, "Back up files and directories",
PF_PRESENTABLE },
{ 18, SE_RESTORE_NAME, "Restore files and directories",
PF_PRESENTABLE },
{ 19, SE_SHUTDOWN_NAME, "Shut down the system", 0 },
{ 20, SE_DEBUG_NAME, "Debug programs", 0 },
{ 21, SE_AUDIT_NAME, "Generate security audits", 0 },
{ 22, SE_SYSTEM_ENVIRONMENT_NAME,
"Modify firmware environment values", 0 },
{ 23, SE_CHANGE_NOTIFY_NAME, "Bypass traverse checking", 0 },
{ 24, SE_REMOTE_SHUTDOWN_NAME,
"Force shutdown from a remote system", 0 },
{ 25, SE_READ_FILE_NAME,
"Bypass ACL for READ access", PF_PRESENTABLE },
{ 26, SE_WRITE_FILE_NAME,
"Bypass ACL for WRITE and DELETE access", PF_PRESENTABLE },
};
int
smb_priv_presentable_num()
{
int i, num;
num = 0;
for (i = SE_MIN_LUID; i <= SE_MAX_LUID; i++)
if (priv_table[i].flags == PF_PRESENTABLE)
num++;
return (num);
}
int
smb_priv_presentable_ids(uint32_t *ids, int num)
{
int i, j;
if (ids == NULL || num <= 0)
return (0);
for (i = SE_MIN_LUID, j = 0; i <= SE_MAX_LUID; i++)
if (priv_table[i].flags == PF_PRESENTABLE)
ids[j++] = priv_table[i].id;
return (1);
}
smb_privinfo_t *
smb_priv_getbyvalue(uint32_t id)
{
if (id < SE_MIN_LUID || id > SE_MAX_LUID)
return (0);
return (&priv_table[id]);
}
smb_privinfo_t *
smb_priv_getbyname(char *name)
{
smb_privinfo_t *entry;
int i;
if (name == 0)
return (0);
for (i = SE_MIN_LUID; i <= SE_MAX_LUID; ++i) {
entry = &priv_table[i];
if (smb_strcasecmp(name, entry->name, 0) == 0)
return (entry);
}
return (0);
}
int
smb_privset_size()
{
int pcnt = SE_MAX_LUID - SE_MIN_LUID + 1;
return (2 * sizeof (uint32_t) +
pcnt * sizeof (smb_luid_attrs_t));
}
int
smb_privset_validate(smb_privset_t *privset)
{
int count;
uint32_t i;
if (privset == 0) {
return (0);
}
count = SE_MAX_LUID - SE_MIN_LUID + 1;
if (privset->priv_cnt != count) {
return (0);
}
for (i = 0; i < count; i++) {
if (privset->priv[i].luid.hi_part != 0) {
return (0);
}
if (privset->priv[i].luid.lo_part !=
i + SE_MIN_LUID) {
return (0);
}
}
return (1);
}
void
smb_privset_init(smb_privset_t *privset)
{
int count;
uint32_t i;
if (privset == 0)
return;
count = SE_MAX_LUID - SE_MIN_LUID + 1;
privset->priv_cnt = count;
privset->control = 0;
for (i = 0; i < count; i++) {
privset->priv[i].luid.hi_part = 0;
privset->priv[i].luid.lo_part = i + SE_MIN_LUID;
privset->priv[i].attrs = 0;
}
}
smb_privset_t *
smb_privset_new()
{
smb_privset_t *privset;
privset = malloc(smb_privset_size());
if (privset == NULL)
return (NULL);
smb_privset_init(privset);
return (privset);
}
void
smb_privset_copy(smb_privset_t *dst, smb_privset_t *src)
{
if (src == 0 || dst == 0)
return;
(void) memcpy(dst, src, smb_privset_size());
}
void
smb_privset_merge(smb_privset_t *dst, smb_privset_t *src)
{
int i;
if (src == NULL || dst == NULL)
return;
for (i = 0; i < src->priv_cnt; i++) {
if (src->priv[i].attrs == SE_PRIVILEGE_ENABLED)
smb_privset_enable(dst, src->priv[i].luid.lo_part);
}
}
void
smb_privset_free(smb_privset_t *privset)
{
free(privset);
}
void
smb_privset_enable(smb_privset_t *privset, uint32_t id)
{
int i;
if (privset == NULL)
return;
for (i = 0; i < privset->priv_cnt; i++) {
if (privset->priv[i].luid.lo_part == id)
privset->priv[i].attrs = SE_PRIVILEGE_ENABLED;
}
}
void
smb_privset_log(smb_privset_t *privset)
{
smb_luid_t *luid;
int i, ecnt;
if (privset == NULL)
return;
for (i = 0, ecnt = 0; i < privset->priv_cnt; ++i) {
if (privset->priv[i].attrs != 0) {
ecnt++;
}
}
syslog(LOG_DEBUG, " Privilege Count: %d (Enable=%d)",
privset->priv_cnt, ecnt);
for (i = 0; i < privset->priv_cnt; ++i) {
if (privset->priv[i].attrs != 0) {
luid = &privset->priv[i].luid;
syslog(LOG_DEBUG, " %s",
smb_priv_getname(luid->lo_part));
}
}
}
int
smb_privset_query(smb_privset_t *privset, uint32_t id)
{
int i;
if (privset == NULL)
return (0);
for (i = 0; privset->priv_cnt; i++) {
if (privset->priv[i].luid.lo_part == id) {
if (privset->priv[i].attrs == SE_PRIVILEGE_ENABLED)
return (1);
else
return (0);
}
}
return (0);
}
static char *
smb_priv_getname(uint32_t id)
{
if (id < SE_MIN_LUID || id > SE_MAX_LUID)
return ("Unknown Privilege");
return (priv_table[id].name);
}