/*
Unix SMB/CIFS implementation.
SMB NT Security Descriptor / Unix permission conversion.
Copyright (C) Jeremy Allison 1994-2009.
Copyright (C) Andreas Gruenbacher 2002.
Copyright (C) Simo Sorce <idra@samba.org> 2009.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "smbd/smbd.h"
#include "system/filesys.h"
#include "../libcli/security/security.h"
#include "trans2.h"
#include "passdb/lookup_sid.h"
#include "auth.h"
#include "../librpc/gen_ndr/idmap.h"
#include "../librpc/gen_ndr/ndr_smb_acl.h"
#include "lib/param/loadparm.h"
extern const struct generic_mapping file_generic_mapping;
#undef DBGC_CLASS
#define DBGC_CLASS DBGC_ACLS
/****************************************************************************
Data structures representing the internal ACE format.
****************************************************************************/
enum ace_owner {UID_ACE, GID_ACE, WORLD_ACE};
enum ace_attribute {ALLOW_ACE, DENY_ACE}; /* Used for incoming NT ACLS. */
typedef struct canon_ace {
struct canon_ace *next, *prev;
SMB_ACL_TAG_T type;
mode_t perms; /* Only use S_I(R|W|X)USR mode bits here. */
struct dom_sid trustee;
enum ace_owner owner_type;
enum ace_attribute attr;
struct unixid unix_ug;
uint8_t ace_flags; /* From windows ACE entry. */
} canon_ace;
#define ALL_ACE_PERMS (S_IRUSR|S_IWUSR|S_IXUSR)
/*
* EA format of user.SAMBA_PAI (Samba_Posix_Acl_Interitance)
* attribute on disk - version 1.
* All values are little endian.
*
* | 1 | 1 | 2 | 2 | ....
* +------+------+-------------+---------------------+-------------+--------------------+
* | vers | flag | num_entries | num_default_entries | ..entries.. | default_entries... |
* +------+------+-------------+---------------------+-------------+--------------------+
*
* Entry format is :
*
* | 1 | 4 |
* +------+-------------------+
* | value| uid/gid or world |
* | type | value |
* +------+-------------------+
*
* Version 2 format. Stores extra Windows metadata about an ACL.
*
* | 1 | 2 | 2 | 2 | ....
* +------+----------+-------------+---------------------+-------------+--------------------+
* | vers | ace | num_entries | num_default_entries | ..entries.. | default_entries... |
* | 2 | type | | | | |
* +------+----------+-------------+---------------------+-------------+--------------------+
*
* Entry format is :
*
* | 1 | 1 | 4 |
* +------+------+-------------------+
* | ace | value| uid/gid or world |
* | flag | type | value |
* +------+-------------------+------+
*
*/
#define PAI_VERSION_OFFSET 0
#define PAI_V1_FLAG_OFFSET 1
#define PAI_V1_NUM_ENTRIES_OFFSET 2
#define PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET 4
#define PAI_V1_ENTRIES_BASE 6
#define PAI_V1_ACL_FLAG_PROTECTED 0x1
#define PAI_V1_ENTRY_LENGTH 5
#define PAI_V1_VERSION 1
#define PAI_V2_TYPE_OFFSET 1
#define PAI_V2_NUM_ENTRIES_OFFSET 3
#define PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET 5
#define PAI_V2_ENTRIES_BASE 7
#define PAI_V2_ENTRY_LENGTH 6
#define PAI_V2_VERSION 2
/*
* In memory format of user.SAMBA_PAI attribute.
*/
struct pai_entry {
struct pai_entry *next, *prev;
uint8_t ace_flags;
enum ace_owner owner_type;
struct unixid unix_ug;
};
struct pai_val {
uint16_t sd_type;
unsigned int num_entries;
struct pai_entry *entry_list;
unsigned int num_def_entries;
struct pai_entry *def_entry_list;
};
/************************************************************************
Return a uint32 of the pai_entry principal.
************************************************************************/
static uint32_t get_pai_entry_val(struct pai_entry *paie)
{
switch (paie->owner_type) {
case UID_ACE:
DEBUG(10,("get_pai_entry_val: uid = %u\n", (unsigned int)paie->unix_ug.id ));
return (uint32_t)paie->unix_ug.id;
case GID_ACE:
DEBUG(10,("get_pai_entry_val: gid = %u\n", (unsigned int)paie->unix_ug.id ));
return (uint32_t)paie->unix_ug.id;
case WORLD_ACE:
default:
DEBUG(10,("get_pai_entry_val: world ace\n"));
return (uint32_t)-1;
}
}
/************************************************************************
Return a uint32 of the entry principal.
************************************************************************/
static uint32_t get_entry_val(canon_ace *ace_entry)
{
switch (ace_entry->owner_type) {
case UID_ACE:
DEBUG(10,("get_entry_val: uid = %u\n", (unsigned int)ace_entry->unix_ug.id ));
return (uint32_t)ace_entry->unix_ug.id;
case GID_ACE:
DEBUG(10,("get_entry_val: gid = %u\n", (unsigned int)ace_entry->unix_ug.id ));
return (uint32_t)ace_entry->unix_ug.id;
case WORLD_ACE:
default:
DEBUG(10,("get_entry_val: world ace\n"));
return (uint32_t)-1;
}
}
/************************************************************************
Create the on-disk format (always v2 now). Caller must free.
************************************************************************/
static char *create_pai_buf_v2(canon_ace *file_ace_list,
canon_ace *dir_ace_list,
uint16_t sd_type,
size_t *store_size)
{
char *pai_buf = NULL;
canon_ace *ace_list = NULL;
char *entry_offset = NULL;
unsigned int num_entries = 0;
unsigned int num_def_entries = 0;
unsigned int i;
for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
num_entries++;
}
for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
num_def_entries++;
}
DEBUG(10,("create_pai_buf_v2: num_entries = %u, num_def_entries = %u\n", num_entries, num_def_entries ));
*store_size = PAI_V2_ENTRIES_BASE +
((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH);
pai_buf = talloc_array(talloc_tos(), char, *store_size);
if (!pai_buf) {
return NULL;
}
/* Set up the header. */
memset(pai_buf, '\0', PAI_V2_ENTRIES_BASE);
SCVAL(pai_buf,PAI_VERSION_OFFSET,PAI_V2_VERSION);
SSVAL(pai_buf,PAI_V2_TYPE_OFFSET, sd_type);
SSVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET,num_entries);
SSVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET,num_def_entries);
DEBUG(10,("create_pai_buf_v2: sd_type = 0x%x\n",
(unsigned int)sd_type ));
entry_offset = pai_buf + PAI_V2_ENTRIES_BASE;
i = 0;
for (ace_list = file_ace_list; ace_list; ace_list = ace_list->next) {
uint8_t type_val = (uint8_t)ace_list->owner_type;
uint32_t entry_val = get_entry_val(ace_list);
SCVAL(entry_offset,0,ace_list->ace_flags);
SCVAL(entry_offset,1,type_val);
SIVAL(entry_offset,2,entry_val);
DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
i,
(unsigned int)ace_list->ace_flags,
(unsigned int)type_val,
(unsigned int)entry_val ));
i++;
entry_offset += PAI_V2_ENTRY_LENGTH;
}
for (ace_list = dir_ace_list; ace_list; ace_list = ace_list->next) {
uint8_t type_val = (uint8_t)ace_list->owner_type;
uint32_t entry_val = get_entry_val(ace_list);
SCVAL(entry_offset,0,ace_list->ace_flags);
SCVAL(entry_offset,1,type_val);
SIVAL(entry_offset,2,entry_val);
DEBUG(10,("create_pai_buf_v2: entry %u [0x%x] [0x%x] [0x%x]\n",
i,
(unsigned int)ace_list->ace_flags,
(unsigned int)type_val,
(unsigned int)entry_val ));
i++;
entry_offset += PAI_V2_ENTRY_LENGTH;
}
return pai_buf;
}
/************************************************************************
Store the user.SAMBA_PAI attribute on disk.
************************************************************************/
static void store_inheritance_attributes(files_struct *fsp,
canon_ace *file_ace_list,
canon_ace *dir_ace_list,
uint16_t sd_type)
{
int ret;
size_t store_size;
char *pai_buf;
if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
return;
}
pai_buf = create_pai_buf_v2(file_ace_list, dir_ace_list,
sd_type, &store_size);
if (fsp->fh->fd != -1) {
ret = SMB_VFS_FSETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, store_size, 0);
} else {
ret = SMB_VFS_SETXATTR(fsp->conn, fsp->fsp_name->base_name,
SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, store_size, 0);
}
TALLOC_FREE(pai_buf);
DEBUG(10,("store_inheritance_attribute: type 0x%x for file %s\n",
(unsigned int)sd_type,
fsp_str_dbg(fsp)));
if (ret == -1 && !no_acl_syscall_error(errno)) {
DEBUG(1,("store_inheritance_attribute: Error %s\n", strerror(errno) ));
}
}
/************************************************************************
Delete the in memory inheritance info.
************************************************************************/
static void free_inherited_info(struct pai_val *pal)
{
if (pal) {
struct pai_entry *paie, *paie_next;
for (paie = pal->entry_list; paie; paie = paie_next) {
paie_next = paie->next;
TALLOC_FREE(paie);
}
for (paie = pal->def_entry_list; paie; paie = paie_next) {
paie_next = paie->next;
TALLOC_FREE(paie);
}
TALLOC_FREE(pal);
}
}
/************************************************************************
Get any stored ACE flags.
************************************************************************/
static uint16_t get_pai_flags(struct pai_val *pal, canon_ace *ace_entry, bool default_ace)
{
struct pai_entry *paie;
if (!pal) {
return 0;
}
/* If the entry exists it is inherited. */
for (paie = (default_ace ? pal->def_entry_list : pal->entry_list); paie; paie = paie->next) {
if (ace_entry->owner_type == paie->owner_type &&
get_entry_val(ace_entry) == get_pai_entry_val(paie))
return paie->ace_flags;
}
return 0;
}
/************************************************************************
Ensure an attribute just read is valid - v1.
************************************************************************/
static bool check_pai_ok_v1(const char *pai_buf, size_t pai_buf_data_size)
{
uint16 num_entries;
uint16 num_def_entries;
if (pai_buf_data_size < PAI_V1_ENTRIES_BASE) {
/* Corrupted - too small. */
return false;
}
if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V1_VERSION) {
return false;
}
num_entries = SVAL(pai_buf,PAI_V1_NUM_ENTRIES_OFFSET);
num_def_entries = SVAL(pai_buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
/* Check the entry lists match. */
/* Each entry is 5 bytes (type plus 4 bytes of uid or gid). */
if (((num_entries + num_def_entries)*PAI_V1_ENTRY_LENGTH) +
PAI_V1_ENTRIES_BASE != pai_buf_data_size) {
return false;
}
return true;
}
/************************************************************************
Ensure an attribute just read is valid - v2.
************************************************************************/
static bool check_pai_ok_v2(const char *pai_buf, size_t pai_buf_data_size)
{
uint16 num_entries;
uint16 num_def_entries;
if (pai_buf_data_size < PAI_V2_ENTRIES_BASE) {
/* Corrupted - too small. */
return false;
}
if (CVAL(pai_buf,PAI_VERSION_OFFSET) != PAI_V2_VERSION) {
return false;
}
num_entries = SVAL(pai_buf,PAI_V2_NUM_ENTRIES_OFFSET);
num_def_entries = SVAL(pai_buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
/* Check the entry lists match. */
/* Each entry is 6 bytes (flags + type + 4 bytes of uid or gid). */
if (((num_entries + num_def_entries)*PAI_V2_ENTRY_LENGTH) +
PAI_V2_ENTRIES_BASE != pai_buf_data_size) {
return false;
}
return true;
}
/************************************************************************
Decode the owner.
************************************************************************/
static bool get_pai_owner_type(struct pai_entry *paie, const char *entry_offset)
{
paie->owner_type = (enum ace_owner)CVAL(entry_offset,0);
switch( paie->owner_type) {
case UID_ACE:
paie->unix_ug.type = ID_TYPE_UID;
paie->unix_ug.id = (uid_t)IVAL(entry_offset,1);
DEBUG(10,("get_pai_owner_type: uid = %u\n",
(unsigned int)paie->unix_ug.id ));
break;
case GID_ACE:
paie->unix_ug.type = ID_TYPE_GID;
paie->unix_ug.id = (gid_t)IVAL(entry_offset,1);
DEBUG(10,("get_pai_owner_type: gid = %u\n",
(unsigned int)paie->unix_ug.id ));
break;
case WORLD_ACE:
paie->unix_ug.type = ID_TYPE_NOT_SPECIFIED;
paie->unix_ug.id = -1;
DEBUG(10,("get_pai_owner_type: world ace\n"));
break;
default:
DEBUG(10,("get_pai_owner_type: unknown type %u\n",
(unsigned int)paie->owner_type ));
return false;
}
return true;
}
/************************************************************************
Process v2 entries.
************************************************************************/
static const char *create_pai_v1_entries(struct pai_val *paiv,
const char *entry_offset,
bool def_entry)
{
int i;
for (i = 0; i < paiv->num_entries; i++) {
struct pai_entry *paie = talloc(talloc_tos(), struct pai_entry);
if (!paie) {
return NULL;
}
paie->ace_flags = SEC_ACE_FLAG_INHERITED_ACE;
if (!get_pai_owner_type(paie, entry_offset)) {
TALLOC_FREE(paie);
return NULL;
}
if (!def_entry) {
DLIST_ADD(paiv->entry_list, paie);
} else {
DLIST_ADD(paiv->def_entry_list, paie);
}
entry_offset += PAI_V1_ENTRY_LENGTH;
}
return entry_offset;
}
/************************************************************************
Convert to in-memory format from version 1.
************************************************************************/
static struct pai_val *create_pai_val_v1(const char *buf, size_t size)
{
const char *entry_offset;
struct pai_val *paiv = NULL;
if (!check_pai_ok_v1(buf, size)) {
return NULL;
}
paiv = talloc(talloc_tos(), struct pai_val);
if (!paiv) {
return NULL;
}
memset(paiv, '\0', sizeof(struct pai_val));
paiv->sd_type = (CVAL(buf,PAI_V1_FLAG_OFFSET) == PAI_V1_ACL_FLAG_PROTECTED) ?
SEC_DESC_DACL_PROTECTED : 0;
paiv->num_entries = SVAL(buf,PAI_V1_NUM_ENTRIES_OFFSET);
paiv->num_def_entries = SVAL(buf,PAI_V1_NUM_DEFAULT_ENTRIES_OFFSET);
entry_offset = buf + PAI_V1_ENTRIES_BASE;
DEBUG(10,("create_pai_val: num_entries = %u, num_def_entries = %u\n",
paiv->num_entries, paiv->num_def_entries ));
entry_offset = create_pai_v1_entries(paiv, entry_offset, false);
if (entry_offset == NULL) {
free_inherited_info(paiv);
return NULL;
}
entry_offset = create_pai_v1_entries(paiv, entry_offset, true);
if (entry_offset == NULL) {
free_inherited_info(paiv);
return NULL;
}
return paiv;
}
/************************************************************************
Process v2 entries.
************************************************************************/
static const char *create_pai_v2_entries(struct pai_val *paiv,
unsigned int num_entries,
const char *entry_offset,
bool def_entry)
{
unsigned int i;
for (i = 0; i < num_entries; i++) {
struct pai_entry *paie = talloc(talloc_tos(), struct pai_entry);
if (!paie) {
return NULL;
}
paie->ace_flags = CVAL(entry_offset,0);
if (!get_pai_owner_type(paie, entry_offset+1)) {
TALLOC_FREE(paie);
return NULL;
}
if (!def_entry) {
DLIST_ADD(paiv->entry_list, paie);
} else {
DLIST_ADD(paiv->def_entry_list, paie);
}
entry_offset += PAI_V2_ENTRY_LENGTH;
}
return entry_offset;
}
/************************************************************************
Convert to in-memory format from version 2.
************************************************************************/
static struct pai_val *create_pai_val_v2(const char *buf, size_t size)
{
const char *entry_offset;
struct pai_val *paiv = NULL;
if (!check_pai_ok_v2(buf, size)) {
return NULL;
}
paiv = talloc(talloc_tos(), struct pai_val);
if (!paiv) {
return NULL;
}
memset(paiv, '\0', sizeof(struct pai_val));
paiv->sd_type = SVAL(buf,PAI_V2_TYPE_OFFSET);
paiv->num_entries = SVAL(buf,PAI_V2_NUM_ENTRIES_OFFSET);
paiv->num_def_entries = SVAL(buf,PAI_V2_NUM_DEFAULT_ENTRIES_OFFSET);
entry_offset = buf + PAI_V2_ENTRIES_BASE;
DEBUG(10,("create_pai_val_v2: sd_type = 0x%x num_entries = %u, num_def_entries = %u\n",
(unsigned int)paiv->sd_type,
paiv->num_entries, paiv->num_def_entries ));
entry_offset = create_pai_v2_entries(paiv, paiv->num_entries,
entry_offset, false);
if (entry_offset == NULL) {
free_inherited_info(paiv);
return NULL;
}
entry_offset = create_pai_v2_entries(paiv, paiv->num_def_entries,
entry_offset, true);
if (entry_offset == NULL) {
free_inherited_info(paiv);
return NULL;
}
return paiv;
}
/************************************************************************
Convert to in-memory format - from either version 1 or 2.
************************************************************************/
static struct pai_val *create_pai_val(const char *buf, size_t size)
{
if (size < 1) {
return NULL;
}
if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V1_VERSION) {
return create_pai_val_v1(buf, size);
} else if (CVAL(buf,PAI_VERSION_OFFSET) == PAI_V2_VERSION) {
return create_pai_val_v2(buf, size);
} else {
return NULL;
}
}
/************************************************************************
Load the user.SAMBA_PAI attribute.
************************************************************************/
static struct pai_val *fload_inherited_info(files_struct *fsp)
{
char *pai_buf;
size_t pai_buf_size = 1024;
struct pai_val *paiv = NULL;
ssize_t ret;
if (!lp_map_acl_inherit(SNUM(fsp->conn))) {
return NULL;
}
if ((pai_buf = talloc_array(talloc_tos(), char, pai_buf_size)) == NULL) {
return NULL;
}
do {
if (fsp->fh->fd != -1) {
ret = SMB_VFS_FGETXATTR(fsp, SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
} else {
ret = SMB_VFS_GETXATTR(fsp->conn,
fsp->fsp_name->base_name,
SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
}
if (ret == -1) {
if (errno != ERANGE) {
break;
}
/* Buffer too small - enlarge it. */
pai_buf_size *= 2;
TALLOC_FREE(pai_buf);
if (pai_buf_size > 1024*1024) {
return NULL; /* Limit malloc to 1mb. */
}
if ((pai_buf = talloc_array(talloc_tos(), char, pai_buf_size)) == NULL)
return NULL;
}
} while (ret == -1);
DEBUG(10,("load_inherited_info: ret = %lu for file %s\n",
(unsigned long)ret, fsp_str_dbg(fsp)));
if (ret == -1) {
/* No attribute or not supported. */
#if defined(ENOATTR)
if (errno != ENOATTR)
DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
#else
if (errno != ENOSYS)
DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
#endif
TALLOC_FREE(pai_buf);
return NULL;
}
paiv = create_pai_val(pai_buf, ret);
if (paiv) {
DEBUG(10,("load_inherited_info: ACL type is 0x%x for file %s\n",
(unsigned int)paiv->sd_type, fsp_str_dbg(fsp)));
}
TALLOC_FREE(pai_buf);
return paiv;
}
/************************************************************************
Load the user.SAMBA_PAI attribute.
************************************************************************/
static struct pai_val *load_inherited_info(const struct connection_struct *conn,
const char *fname)
{
char *pai_buf;
size_t pai_buf_size = 1024;
struct pai_val *paiv = NULL;
ssize_t ret;
if (!lp_map_acl_inherit(SNUM(conn))) {
return NULL;
}
if ((pai_buf = talloc_array(talloc_tos(), char, pai_buf_size)) == NULL) {
return NULL;
}
do {
ret = SMB_VFS_GETXATTR(conn, fname,
SAMBA_POSIX_INHERITANCE_EA_NAME,
pai_buf, pai_buf_size);
if (ret == -1) {
if (errno != ERANGE) {
break;
}
/* Buffer too small - enlarge it. */
pai_buf_size *= 2;
TALLOC_FREE(pai_buf);
if (pai_buf_size > 1024*1024) {
return NULL; /* Limit malloc to 1mb. */
}
if ((pai_buf = talloc_array(talloc_tos(), char, pai_buf_size)) == NULL)
return NULL;
}
} while (ret == -1);
DEBUG(10,("load_inherited_info: ret = %lu for file %s\n", (unsigned long)ret, fname));
if (ret == -1) {
/* No attribute or not supported. */
#if defined(ENOATTR)
if (errno != ENOATTR)
DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
#else
if (errno != ENOSYS)
DEBUG(10,("load_inherited_info: Error %s\n", strerror(errno) ));
#endif
TALLOC_FREE(pai_buf);
return NULL;
}
paiv = create_pai_val(pai_buf, ret);
if (paiv) {
DEBUG(10,("load_inherited_info: ACL type 0x%x for file %s\n",
(unsigned int)paiv->sd_type,
fname));
}
TALLOC_FREE(pai_buf);
return paiv;
}
/****************************************************************************
Functions to manipulate the internal ACE format.
****************************************************************************/
/****************************************************************************
Count a linked list of canonical ACE entries.
****************************************************************************/
static size_t count_canon_ace_list( canon_ace *l_head )
{
size_t count = 0;
canon_ace *ace;
for (ace = l_head; ace; ace = ace->next)
count++;
return count;
}
/****************************************************************************
Free a linked list of canonical ACE entries.
****************************************************************************/
static void free_canon_ace_list( canon_ace *l_head )
{
canon_ace *list, *next;
for (list = l_head; list; list = next) {
next = list->next;
DLIST_REMOVE(l_head, list);
TALLOC_FREE(list);
}
}
/****************************************************************************
Function to duplicate a canon_ace entry.
****************************************************************************/
static canon_ace *dup_canon_ace( canon_ace *src_ace)
{
canon_ace *dst_ace = talloc(talloc_tos(), canon_ace);
if (dst_ace == NULL)
return NULL;
*dst_ace = *src_ace;
dst_ace->prev = dst_ace->next = NULL;
return dst_ace;
}
/****************************************************************************
Print out a canon ace.
****************************************************************************/
static void print_canon_ace(canon_ace *pace, int num)
{
dbgtext( "canon_ace index %d. Type = %s ", num, pace->attr == ALLOW_ACE ? "allow" : "deny" );
dbgtext( "SID = %s ", sid_string_dbg(&pace->trustee));
if (pace->owner_type == UID_ACE) {
const char *u_name = uidtoname(pace->unix_ug.id);
dbgtext( "uid %u (%s) ", (unsigned int)pace->unix_ug.id, u_name );
} else if (pace->owner_type == GID_ACE) {
char *g_name = gidtoname(pace->unix_ug.id);
dbgtext( "gid %u (%s) ", (unsigned int)pace->unix_ug.id, g_name );
} else
dbgtext( "other ");
switch (pace->type) {
case SMB_ACL_USER:
dbgtext( "SMB_ACL_USER ");
break;
case SMB_ACL_USER_OBJ:
dbgtext( "SMB_ACL_USER_OBJ ");
break;
case SMB_ACL_GROUP:
dbgtext( "SMB_ACL_GROUP ");
break;
case SMB_ACL_GROUP_OBJ:
dbgtext( "SMB_ACL_GROUP_OBJ ");
break;
case SMB_ACL_OTHER:
dbgtext( "SMB_ACL_OTHER ");
break;
default:
dbgtext( "MASK " );
break;
}
dbgtext( "ace_flags = 0x%x ", (unsigned int)pace->ace_flags);
dbgtext( "perms ");
dbgtext( "%c", pace->perms & S_IRUSR ? 'r' : '-');
dbgtext( "%c", pace->perms & S_IWUSR ? 'w' : '-');
dbgtext( "%c\n", pace->perms & S_IXUSR ? 'x' : '-');
}
/****************************************************************************
Print out a canon ace list.
****************************************************************************/
static void print_canon_ace_list(const char *name, canon_ace *ace_list)
{
int count = 0;
if( DEBUGLVL( 10 )) {
dbgtext( "print_canon_ace_list: %s\n", name );
for (;ace_list; ace_list = ace_list->next, count++)
print_canon_ace(ace_list, count );
}
}
/****************************************************************************
Map POSIX ACL perms to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
****************************************************************************/
static mode_t convert_permset_to_mode_t(SMB_ACL_PERMSET_T permset)
{
mode_t ret = 0;
ret |= (sys_acl_get_perm(permset, SMB_ACL_READ) ? S_IRUSR : 0);
ret |= (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? S_IWUSR : 0);
ret |= (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? S_IXUSR : 0);
return ret;
}
/****************************************************************************
Map generic UNIX permissions to canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits).
****************************************************************************/
static mode_t unix_perms_to_acl_perms(mode_t mode, int r_mask, int w_mask, int x_mask)
{
mode_t ret = 0;
if (mode & r_mask)
ret |= S_IRUSR;
if (mode & w_mask)
ret |= S_IWUSR;
if (mode & x_mask)
ret |= S_IXUSR;
return ret;
}
/****************************************************************************
Map canon_ace permissions (a mode_t containing only S_(R|W|X)USR bits) to
an SMB_ACL_PERMSET_T.
****************************************************************************/
static int map_acl_perms_to_permset(connection_struct *conn, mode_t mode, SMB_ACL_PERMSET_T *p_permset)
{
if (sys_acl_clear_perms(*p_permset) == -1)
return -1;
if (mode & S_IRUSR) {
if (sys_acl_add_perm(*p_permset, SMB_ACL_READ) == -1)
return -1;
}
if (mode & S_IWUSR) {
if (sys_acl_add_perm(*p_permset, SMB_ACL_WRITE) == -1)
return -1;
}
if (mode & S_IXUSR) {
if (sys_acl_add_perm(*p_permset, SMB_ACL_EXECUTE) == -1)
return -1;
}
return 0;
}
/****************************************************************************
Function to create owner and group SIDs from a SMB_STRUCT_STAT.
****************************************************************************/
void create_file_sids(const SMB_STRUCT_STAT *psbuf, struct dom_sid *powner_sid, struct dom_sid *pgroup_sid)
{
uid_to_sid( powner_sid, psbuf->st_ex_uid );
|