[2/3] netapi32: Add support for info level 502 in NetShareAdd.
Hans Leidekker
hans at codeweavers.com
Wed Nov 20 03:30:32 CST 2013
---
dlls/netapi32/netapi32.c | 463 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 463 insertions(+)
diff --git a/dlls/netapi32/netapi32.c b/dlls/netapi32/netapi32.c
index c0343ce..d5f30c0 100644
--- a/dlls/netapi32/netapi32.c
+++ b/dlls/netapi32/netapi32.c
@@ -298,11 +298,474 @@ static NET_API_STATUS share_info_2_to_samba( const BYTE *buf, unsigned char **bu
return NERR_Success;
}
+struct sid
+{
+ unsigned char sid_rev_num;
+ unsigned char num_auths;
+ unsigned char id_auth[6];
+ unsigned int sub_auths[15];
+};
+
+enum ace_type
+{
+ ACE_TYPE_ACCESS_ALLOWED,
+ ACE_TYPE_ACCESS_DENIED,
+ ACE_TYPE_SYSTEM_AUDIT,
+ ACE_TYPE_SYSTEM_ALARM,
+ ACE_TYPE_ALLOWED_COMPOUND,
+ ACE_TYPE_ACCESS_ALLOWED_OBJECT,
+ ACE_TYPE_ACCESS_DENIED_OBJECT,
+ ACE_TYPE_SYSTEM_AUDIT_OBJECT,
+ ACE_TYPE_SYSTEM_ALARM_OBJECT
+};
+
+#define SEC_ACE_FLAG_OBJECT_INHERIT 0x01
+#define SEC_ACE_FLAG_CONTAINER_INHERIT 0x02
+#define SEC_ACE_FLAG_NO_PROPAGATE_INHERIT 0x04
+#define SEC_ACE_FLAG_INHERIT_ONLY 0x08
+#define SEC_ACE_FLAG_INHERITED_ACE 0x10
+#define SEC_ACE_FLAG_SUCCESSFUL_ACCESS 0x40
+#define SEC_ACE_FLAG_FAILED_ACCESS 0x80
+
+struct guid
+{
+ unsigned int time_low;
+ unsigned short time_mid;
+ unsigned short time_hi_and_version;
+ unsigned char clock_seq[2];
+ unsigned char node[6];
+};
+
+union ace_object_type
+{
+ struct guid type;
+};
+
+union ace_object_inherited_type
+{
+ struct guid inherited_type;
+};
+
+struct ace_object
+{
+ unsigned int flags;
+ union ace_object_type type;
+ union ace_object_inherited_type inherited_type;
+};
+
+union ace_object_ctr
+{
+ struct ace_object object;
+};
+
+struct ace
+{
+ enum ace_type type;
+ unsigned char flags;
+ unsigned short size;
+ unsigned int access_mask;
+ union ace_object_ctr object;
+ struct sid trustee;
+};
+
+enum acl_revision
+{
+ ACL_REVISION_NT4 = 2,
+ ACL_REVISION_ADS = 4
+};
+
+struct acl
+{
+ enum acl_revision revision;
+ unsigned short size;
+ unsigned int num_aces;
+ struct ace *aces;
+};
+
+enum security_descriptor_revision
+{
+ SECURITY_DESCRIPTOR_REVISION_1 = 1
+};
+
+#define SEC_DESC_OWNER_DEFAULTED 0x0001
+#define SEC_DESC_GROUP_DEFAULTED 0x0002
+#define SEC_DESC_DACL_PRESENT 0x0004
+#define SEC_DESC_DACL_DEFAULTED 0x0008
+#define SEC_DESC_SACL_PRESENT 0x0010
+#define SEC_DESC_SACL_DEFAULTED 0x0020
+#define SEC_DESC_DACL_TRUSTED 0x0040
+#define SEC_DESC_SERVER_SECURITY 0x0080
+#define SEC_DESC_DACL_AUTO_INHERIT_REQ 0x0100
+#define SEC_DESC_SACL_AUTO_INHERIT_REQ 0x0200
+#define SEC_DESC_DACL_AUTO_INHERITED 0x0400
+#define SEC_DESC_SACL_AUTO_INHERITED 0x0800
+#define SEC_DESC_DACL_PROTECTED 0x1000
+#define SEC_DESC_SACL_PROTECTED 0x2000
+#define SEC_DESC_RM_CONTROL_VALID 0x4000
+#define SEC_DESC_SELF_RELATIVE 0x8000
+
+struct security_descriptor
+{
+ enum security_descriptor_revision revision;
+ unsigned short type;
+ struct sid *owner_sid;
+ struct sid *group_sid;
+ struct acl *sacl;
+ struct acl *dacl;
+};
+
+struct share_info_502
+{
+ const char *shi502_netname;
+ unsigned int shi502_type;
+ const char *shi502_remark;
+ unsigned int shi502_permissions;
+ unsigned int shi502_max_uses;
+ unsigned int shi502_current_uses;
+ const char *shi502_path;
+ const char *shi502_passwd;
+ unsigned int shi502_reserved;
+ struct security_descriptor *shi502_security_descriptor;
+};
+
+static unsigned short sd_control_to_samba( SECURITY_DESCRIPTOR_CONTROL control )
+{
+ unsigned short ret = 0;
+
+ if (control & SE_OWNER_DEFAULTED) ret |= SEC_DESC_OWNER_DEFAULTED;
+ if (control & SE_GROUP_DEFAULTED) ret |= SEC_DESC_GROUP_DEFAULTED;
+ if (control & SE_DACL_PRESENT) ret |= SEC_DESC_DACL_PRESENT;
+ if (control & SE_DACL_DEFAULTED) ret |= SEC_DESC_DACL_DEFAULTED;
+ if (control & SE_SACL_PRESENT) ret |= SEC_DESC_SACL_PRESENT;
+ if (control & SE_SACL_DEFAULTED) ret |= SEC_DESC_SACL_DEFAULTED;
+ if (control & SE_DACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_DACL_AUTO_INHERIT_REQ;
+ if (control & SE_SACL_AUTO_INHERIT_REQ) ret |= SEC_DESC_SACL_AUTO_INHERIT_REQ;
+ if (control & SE_DACL_AUTO_INHERITED) ret |= SEC_DESC_DACL_AUTO_INHERITED;
+ if (control & SE_SACL_AUTO_INHERITED) ret |= SEC_DESC_SACL_AUTO_INHERITED;
+ if (control & SE_DACL_PROTECTED) ret |= SEC_DESC_DACL_PROTECTED;
+ if (control & SE_SACL_PROTECTED) ret |= SEC_DESC_SACL_PROTECTED;
+ if (control & SE_RM_CONTROL_VALID) ret |= SEC_DESC_RM_CONTROL_VALID;
+ return ret;
+}
+
+static NET_API_STATUS sid_to_samba( const SID *src, struct sid *dst )
+{
+ unsigned int i;
+
+ if (src->Revision != 1)
+ {
+ ERR( "unknown revision %u\n", src->Revision );
+ return ERROR_UNKNOWN_REVISION;
+ }
+ if (src->SubAuthorityCount > SID_MAX_SUB_AUTHORITIES)
+ {
+ WARN( "invalid subauthority count %u\n", src->SubAuthorityCount );
+ return ERROR_INVALID_PARAMETER;
+ }
+ dst->sid_rev_num = SECURITY_DESCRIPTOR_REVISION_1;
+ dst->num_auths = src->SubAuthorityCount;
+ for (i = 0; i < 6; i++) dst->id_auth[i] = src->IdentifierAuthority.Value[i];
+ for (i = 0; i < dst->num_auths; i++) dst->sub_auths[i] = src->SubAuthority[i];
+ return NERR_Success;
+}
+
+static enum ace_type ace_type_to_samba( BYTE type )
+{
+ switch (type)
+ {
+ case ACCESS_ALLOWED_ACE_TYPE: return ACE_TYPE_ACCESS_ALLOWED;
+ case ACCESS_DENIED_ACE_TYPE: return ACE_TYPE_ACCESS_DENIED;
+ case SYSTEM_AUDIT_ACE_TYPE: return ACE_TYPE_SYSTEM_AUDIT;
+ case SYSTEM_ALARM_ACE_TYPE: return ACE_TYPE_SYSTEM_ALARM;
+ default:
+ ERR( "unhandled type %u\n", type );
+ return 0;
+ }
+}
+
+static unsigned char ace_flags_to_samba( BYTE flags )
+{
+ static const BYTE known_flags =
+ OBJECT_INHERIT_ACE | CONTAINER_INHERIT_ACE | NO_PROPAGATE_INHERIT_ACE |
+ INHERIT_ONLY_ACE | INHERITED_ACE | SUCCESSFUL_ACCESS_ACE_FLAG | FAILED_ACCESS_ACE_FLAG;
+ unsigned char ret = 0;
+
+ if (flags & ~known_flags)
+ {
+ ERR( "unknown flags %x\n", flags & ~known_flags );
+ return 0;
+ }
+ if (flags & OBJECT_INHERIT_ACE) ret |= SEC_ACE_FLAG_OBJECT_INHERIT;
+ if (flags & CONTAINER_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
+ if (flags & NO_PROPAGATE_INHERIT_ACE) ret |= SEC_ACE_FLAG_NO_PROPAGATE_INHERIT;
+ if (flags & INHERIT_ONLY_ACE) ret |= SEC_ACE_FLAG_INHERIT_ONLY;
+ if (flags & INHERITED_ACE) ret |= SEC_ACE_FLAG_INHERITED_ACE;
+ if (flags & SUCCESSFUL_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_SUCCESSFUL_ACCESS;
+ if (flags & FAILED_ACCESS_ACE_FLAG) ret |= SEC_ACE_FLAG_FAILED_ACCESS;
+ return ret;
+}
+
+#define GENERIC_ALL_ACCESS (1 << 28)
+#define GENERIC_EXECUTE_ACCESS (1 << 29)
+#define GENERIC_WRITE_ACCESS (1 << 30)
+#define GENERIC_READ_ACCESS (1 << 31)
+
+unsigned int access_mask_to_samba( DWORD mask )
+{
+ static const DWORD known_rights =
+ GENERIC_ALL | GENERIC_EXECUTE | GENERIC_WRITE | GENERIC_READ;
+ unsigned int ret = 0;
+
+ if (mask & ~known_rights)
+ {
+ ERR( "unknown rights %x\n", mask & ~known_rights );
+ return 0;
+ }
+ if (mask & GENERIC_ALL) ret |= GENERIC_ALL_ACCESS;
+ if (mask & GENERIC_EXECUTE) ret |= GENERIC_EXECUTE_ACCESS;
+ if (mask & GENERIC_WRITE) ret |= GENERIC_WRITE_ACCESS;
+ if (mask & GENERIC_READ) ret |= GENERIC_READ_ACCESS;
+ return ret;
+}
+
+static NET_API_STATUS ace_to_samba( const ACE_HEADER *src, struct ace *dst )
+{
+ dst->type = ace_type_to_samba( src->AceType );
+ dst->flags = ace_flags_to_samba( src->AceFlags );
+ dst->size = sizeof(*dst);
+ switch (src->AceType)
+ {
+ case ACCESS_ALLOWED_ACE_TYPE:
+ {
+ ACCESS_ALLOWED_ACE *ace = (ACCESS_ALLOWED_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ }
+ case ACCESS_DENIED_ACE_TYPE:
+ {
+ ACCESS_DENIED_ACE *ace = (ACCESS_DENIED_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ }
+ case SYSTEM_AUDIT_ACE_TYPE:
+ {
+ SYSTEM_AUDIT_ACE *ace = (SYSTEM_AUDIT_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ }
+ case SYSTEM_ALARM_ACE_TYPE:
+ {
+ SYSTEM_ALARM_ACE *ace = (SYSTEM_ALARM_ACE *)src;
+ dst->access_mask = access_mask_to_samba( ace->Mask );
+ memset( &dst->object, 0, sizeof(dst->object) );
+ sid_to_samba( (const SID *)&ace->SidStart, &dst->trustee );
+ }
+ default:
+ ERR( "unhandled type %u\n", src->AceType );
+ return ERROR_INVALID_PARAMETER;
+ }
+ return NERR_Success;
+}
+
+static NET_API_STATUS acl_to_samba( const ACL *src, struct acl *dst )
+{
+ NET_API_STATUS status;
+ ACE_HEADER *src_ace;
+ unsigned int i;
+
+ switch (src->AclRevision)
+ {
+ case ACL_REVISION4:
+ dst->revision = ACL_REVISION_ADS;
+ break;
+ default:
+ ERR( "unkhandled revision %u\n", src->AclRevision );
+ return ERROR_UNKNOWN_REVISION;
+ }
+ dst->size = sizeof(*dst);
+ src_ace = (ACE_HEADER *)(src + 1);
+ dst->aces = (struct ace *)(dst + 1);
+ for (i = 0; i < src->AceCount; i++)
+ {
+ if ((status = ace_to_samba( src_ace, &dst->aces[i] ))) return status;
+ src_ace = (ACE_HEADER *)((char *)src_ace + src_ace->AceSize);
+ dst->size += dst->aces[i].size;
+ }
+ return NERR_Success;
+}
+
+#define SELF_RELATIVE_FIELD(sd,field)\
+ ((char *)(sd) + ((SECURITY_DESCRIPTOR_RELATIVE *)(sd))->field)
+
+static NET_API_STATUS sd_to_samba( const SECURITY_DESCRIPTOR *src, struct security_descriptor *dst )
+{
+ NET_API_STATUS status;
+ const SID *owner, *group;
+ const ACL *dacl, *sacl;
+ unsigned int offset = sizeof(*dst);
+
+ if (src->Revision != SECURITY_DESCRIPTOR_REVISION1)
+ return ERROR_UNKNOWN_REVISION;
+
+ dst->revision = SECURITY_DESCRIPTOR_REVISION_1;
+ dst->type = sd_control_to_samba( src->Control );
+
+ if (src->Control & SE_SELF_RELATIVE)
+ {
+ if (!src->Owner) dst->owner_sid = NULL;
+ else
+ {
+ dst->owner_sid = (struct sid *)((char *)dst + offset);
+ owner = (const SID *)SELF_RELATIVE_FIELD( src, Owner );
+ if ((status = sid_to_samba( owner, dst->owner_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!src->Group) dst->group_sid = NULL;
+ else
+ {
+ dst->group_sid = (struct sid *)((char *)dst + offset);
+ group = (const SID *)SELF_RELATIVE_FIELD( src, Group );
+ if ((status = sid_to_samba( group, dst->group_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
+ else
+ {
+ dst->sacl = (struct acl *)((char *)dst + offset);
+ sacl = (const ACL *)SELF_RELATIVE_FIELD( src, Sacl );
+ if ((status = acl_to_samba( sacl, dst->sacl ))) return status;
+ offset += dst->sacl->size;
+ }
+ if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
+ else
+ {
+ dst->dacl = (struct acl *)((char *)dst + offset);
+ dacl = (const ACL *)SELF_RELATIVE_FIELD( src, Dacl );
+ if ((status = acl_to_samba( dacl, dst->dacl ))) return status;
+ }
+ }
+ else
+ {
+ if (!src->Owner) dst->owner_sid = NULL;
+ else
+ {
+ dst->owner_sid = (struct sid *)((char *)dst + offset);
+ if ((status = sid_to_samba( src->Owner, dst->owner_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!src->Group) dst->group_sid = NULL;
+ else
+ {
+ dst->group_sid = (struct sid *)((char *)dst + offset);
+ if ((status = sid_to_samba( src->Group, dst->group_sid ))) return status;
+ offset += sizeof(struct sid);
+ }
+ if (!(src->Control & SE_SACL_PRESENT)) dst->sacl = NULL;
+ else
+ {
+ dst->sacl = (struct acl *)((char *)dst + offset);
+ if ((status = acl_to_samba( src->Sacl, dst->sacl ))) return status;
+ offset += dst->sacl->size;
+ }
+ if (!(src->Control & SE_DACL_PRESENT)) dst->dacl = NULL;
+ else
+ {
+ dst->dacl = (struct acl *)((char *)dst + offset);
+ if ((status = acl_to_samba( src->Dacl, dst->dacl ))) return status;
+ }
+ }
+ return NERR_Success;
+}
+
+static unsigned int sd_to_samba_size( const SECURITY_DESCRIPTOR *sd )
+{
+ unsigned int ret = sizeof(struct security_descriptor);
+
+ if (sd->Owner) ret += sizeof(struct sid);
+ if (sd->Group) ret += sizeof(struct sid);
+ if (sd->Control & SE_SACL_PRESENT)
+ ret += sizeof(struct acl) + sd->Sacl->AceCount * sizeof(struct ace);
+ if (sd->Control & SE_DACL_PRESENT)
+ ret += sizeof(struct acl) + sd->Dacl->AceCount * sizeof(struct ace);
+ return ret;
+}
+
+static NET_API_STATUS share_info_502_to_samba( const BYTE *buf, unsigned char **bufptr )
+{
+ NET_API_STATUS status;
+ struct share_info_502 *ret;
+ SHARE_INFO_502 *info = (SHARE_INFO_502 *)buf;
+ DWORD len = 0, size = 0;
+ char *ptr;
+
+ *bufptr = NULL;
+ if (info->shi502_netname)
+ len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_netname, -1, NULL, 0, NULL, NULL );
+ if (info->shi502_remark)
+ len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_remark, -1, NULL, 0, NULL, NULL );
+ if (info->shi502_path)
+ len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_path, -1, NULL, 0, NULL, NULL );
+ if (info->shi502_passwd)
+ len += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_passwd, -1, NULL, 0, NULL, NULL );
+ if (info->shi502_security_descriptor)
+ size = sd_to_samba_size( info->shi502_security_descriptor );
+ if (!(ret = HeapAlloc( GetProcessHeap(), 0, sizeof(*ret) + (len * sizeof(WCHAR)) + size )))
+ return ERROR_OUTOFMEMORY;
+
+ ptr = (char *)(ret + 1);
+ if (!info->shi502_netname) ret->shi502_netname = NULL;
+ else
+ {
+ ret->shi502_netname = ptr;
+ ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_netname, -1, ptr, len, NULL, NULL );
+ }
+ ret->shi502_type = info->shi502_type;
+ if (!info->shi502_remark) ret->shi502_remark = NULL;
+ else
+ {
+ ret->shi502_remark = ptr;
+ ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_remark, -1, ptr, len, NULL, NULL );
+ }
+ ret->shi502_permissions = info->shi502_permissions;
+ ret->shi502_max_uses = info->shi502_max_uses;
+ ret->shi502_current_uses = info->shi502_current_uses;
+ if (!info->shi502_path) ret->shi502_path = NULL;
+ else
+ {
+ ret->shi502_path = ptr;
+ ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_path, -1, ptr, len, NULL, NULL );
+ }
+ if (!info->shi502_passwd) ret->shi502_passwd = NULL;
+ else
+ {
+ ret->shi502_passwd = ptr;
+ ptr += WideCharToMultiByte( CP_UNIXCP, 0, info->shi502_passwd, -1, ptr, len, NULL, NULL );
+ }
+ ret->shi502_reserved = info->shi502_reserved;
+ if (!info->shi502_security_descriptor) ret->shi502_security_descriptor = NULL;
+ else
+ {
+ status = sd_to_samba( info->shi502_security_descriptor, (struct security_descriptor *)ptr );
+ if (status)
+ {
+ HeapFree( GetProcessHeap(), 0, ret );
+ return status;
+ }
+ ret->shi502_security_descriptor = (struct security_descriptor *)ptr;
+ }
+ *bufptr = (unsigned char *)ret;
+ return NERR_Success;
+}
+
static NET_API_STATUS share_info_to_samba( DWORD level, const BYTE *buf, unsigned char **bufptr )
{
switch (level)
{
case 2: return share_info_2_to_samba( buf, bufptr );
+ case 502: return share_info_502_to_samba( buf, bufptr );
default:
FIXME( "level %u not supported\n", level );
return ERROR_NOT_SUPPORTED;
--
1.8.1.5
More information about the wine-patches
mailing list