[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