more acl
reformated some of the old functions. finalized mapping functions for windows to nfs4 access mask bits. satisfying nfs41_acl_query for dacl. when doing setacl and creating "who" field of the format user@nfs4domain, use dns domain name of the windows client machine
This commit is contained in:
parent
80b3d11609
commit
f78cc24925
2 changed files with 386 additions and 313 deletions
591
daemon/acl.c
591
daemon/acl.c
|
|
@ -31,7 +31,8 @@
|
|||
#include "upcall.h"
|
||||
#include "nfs41_xdr.h"
|
||||
|
||||
static int parse_getacl(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
|
||||
static int parse_getacl(unsigned char *buffer, uint32_t length,
|
||||
nfs41_upcall *upcall)
|
||||
{
|
||||
int status;
|
||||
getacl_upcall_args *args = &upcall->args.getacl;
|
||||
|
|
@ -45,30 +46,38 @@ static int parse_getacl(unsigned char *buffer, uint32_t length, nfs41_upcall *up
|
|||
status = safe_read(&buffer, &length, &args->query, sizeof(args->query));
|
||||
if (status) goto out;
|
||||
|
||||
dprintf(1, "parsing NFS41_ACL_QUERY: info_class=%d root=0x%p open_state=0x%p\n",
|
||||
args->query, args->root, args->state);
|
||||
dprintf(1, "parsing NFS41_ACL_QUERY: info_class=%d root=0x%p "
|
||||
"open_state=0x%p\n", args->query, args->root, args->state);
|
||||
out:
|
||||
return status;
|
||||
}
|
||||
|
||||
static int create_unknownsid(WELL_KNOWN_SID_TYPE type, PSID *sid, DWORD *sid_len)
|
||||
static int create_unknownsid(WELL_KNOWN_SID_TYPE type, PSID *sid,
|
||||
DWORD *sid_len)
|
||||
{
|
||||
int status;
|
||||
*sid_len = 0;
|
||||
*sid = NULL;
|
||||
if (!CreateWellKnownSid(type, NULL, *sid, sid_len)) {
|
||||
|
||||
status = CreateWellKnownSid(type, NULL, *sid, sid_len);
|
||||
dprintf(1, "create_unknownsid: CreateWellKnownSid type %d returned %d "
|
||||
"GetLastError %d sid len %d needed\n", type, status,
|
||||
GetLastError(), *sid_len);
|
||||
if (status)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
status = GetLastError();
|
||||
if (status == ERROR_INSUFFICIENT_BUFFER) {
|
||||
if (status != ERROR_INSUFFICIENT_BUFFER)
|
||||
return status;
|
||||
*sid = malloc(*sid_len);
|
||||
if (*sid == NULL) return ERROR_INSUFFICIENT_BUFFER;
|
||||
if (!CreateWellKnownSid(type, NULL, *sid, sid_len)) {
|
||||
if (*sid == NULL)
|
||||
return ERROR_INSUFFICIENT_BUFFER;
|
||||
status = CreateWellKnownSid(type, NULL, *sid, sid_len);
|
||||
if (status)
|
||||
return ERROR_SUCCESS;
|
||||
free(*sid);
|
||||
status = GetLastError();
|
||||
dprintf(1, "CreateWellKnownSid failed with %d\n", status);
|
||||
eprintf("create_unknownsid: CreateWellKnownSid failed with %d\n", status);
|
||||
return status;
|
||||
} else return 0;
|
||||
} else return status;
|
||||
} else return ERROR_INTERNAL_ERROR;
|
||||
}
|
||||
|
||||
static void convert_nfs4name_2_user_domain(LPSTR nfs4name,
|
||||
|
|
@ -86,15 +95,18 @@ static void convert_nfs4name_2_user_domain(LPSTR nfs4name,
|
|||
|
||||
static int map_name_2_sid(DWORD *sid_len, PSID *sid, LPCSTR name)
|
||||
{
|
||||
int status;
|
||||
int status = ERROR_INTERNAL_ERROR;
|
||||
SID_NAME_USE sid_type;
|
||||
LPSTR tmp_buf = NULL;
|
||||
DWORD tmp = 0;
|
||||
|
||||
status = LookupAccountName(NULL, name, NULL, sid_len, NULL, &tmp, &sid_type);
|
||||
dprintf(1, "LookupAccountName returned %d GetLastError %d owner len %d "
|
||||
"domain len %d\n", status, GetLastError(), *sid_len, tmp);
|
||||
if (!status) {
|
||||
dprintf(1, "map_name_2_sid: LookupAccountName for %s returned %d "
|
||||
"GetLastError %d name len %d domain len %d\n", name, status,
|
||||
GetLastError(), *sid_len, tmp);
|
||||
if (status)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
|
||||
status = GetLastError();
|
||||
switch(status) {
|
||||
case ERROR_INSUFFICIENT_BUFFER:
|
||||
|
|
@ -104,42 +116,157 @@ static int map_name_2_sid(DWORD *sid_len, PSID *sid, LPCSTR name)
|
|||
goto out;
|
||||
}
|
||||
tmp_buf = (LPSTR) malloc(tmp);
|
||||
if (tmp_buf == NULL) {
|
||||
status = GetLastError();
|
||||
free(*sid);
|
||||
goto out;
|
||||
}
|
||||
if (tmp_buf == NULL)
|
||||
goto out_free_sid;
|
||||
status = LookupAccountName(NULL, name, *sid, sid_len, tmp_buf,
|
||||
&tmp, &sid_type);
|
||||
dprintf(1, "sid_type = %d\n", sid_type);
|
||||
free(tmp_buf);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
free(*sid);
|
||||
dprintf(1, "handle_getacl: LookupAccountName for owner failed "
|
||||
"with %d\n", status);
|
||||
goto out;
|
||||
eprintf("map_name_2_sid: LookupAccountName for %s failed "
|
||||
"with %d\n", name, GetLastError());
|
||||
goto out_free_sid;
|
||||
} else {
|
||||
LPSTR ssid = NULL;
|
||||
if (IsValidSid(*sid))
|
||||
if (ConvertSidToStringSidA(*sid, &ssid))
|
||||
printf("SID %s\n", ssid);
|
||||
dprintf(1, "map_name_2_sid: sid_type = %d SID %s\n",
|
||||
sid_type, ssid);
|
||||
else
|
||||
printf("ConvertSidToStringSidA failed with %d\n", GetLastError());
|
||||
dprintf(1, "map_name_2_sid: ConvertSidToStringSidA failed "
|
||||
"with %d\n", GetLastError());
|
||||
else
|
||||
printf("Invalid Sid\n");
|
||||
dprintf(1, "map_name_2_sid: Invalid Sid ?\n");
|
||||
if (ssid) LocalFree(ssid);
|
||||
}
|
||||
status = 0;
|
||||
status = ERROR_SUCCESS;
|
||||
break;
|
||||
case ERROR_NONE_MAPPED:
|
||||
status = create_unknownsid(WinNullSid, sid, sid_len);
|
||||
break;
|
||||
if (status)
|
||||
goto out_free_sid;
|
||||
}
|
||||
} else // This shouldn't happen
|
||||
status = ERROR_INTERNAL_ERROR;
|
||||
out:
|
||||
return status;
|
||||
out_free_sid:
|
||||
status = GetLastError();
|
||||
free(*sid);
|
||||
goto out;
|
||||
}
|
||||
|
||||
static void free_sids(PSID *sids, int count)
|
||||
{
|
||||
int i;
|
||||
for(i = 0; i < count; i++)
|
||||
free(sids[i]);
|
||||
free(sids);
|
||||
}
|
||||
|
||||
static int check_4_special_identifiers(char *who, PSID *sid, DWORD *sid_len,
|
||||
BOOLEAN *flag)
|
||||
{
|
||||
int status = ERROR_SUCCESS;
|
||||
WELL_KNOWN_SID_TYPE type = 0;
|
||||
*flag = TRUE;
|
||||
if (!strncmp(who, ACE4_OWNER, strlen(ACE4_OWNER)-1))
|
||||
type = WinCreatorOwnerSid;
|
||||
else if (!strncmp(who, ACE4_GROUP, strlen(ACE4_GROUP)-1))
|
||||
type = WinCreatorGroupSid;
|
||||
else if (!strncmp(who, ACE4_EVERYONE, strlen(ACE4_EVERYONE)-1))
|
||||
type = WinWorldSid;
|
||||
else if (!strncmp(who, ACE4_NOBODY, strlen(ACE4_NOBODY)))
|
||||
type = WinNullSid;
|
||||
else
|
||||
*flag = FALSE;
|
||||
if (*flag)
|
||||
status = create_unknownsid(type, sid, sid_len);
|
||||
return status;
|
||||
}
|
||||
|
||||
static int convert_nfs4acl_2_dacl(nfsacl41 *acl, int file_type,
|
||||
PACL *dacl_out, PSID **sids_out)
|
||||
{
|
||||
int status = ERROR_NOT_SUPPORTED, size = 0;
|
||||
uint32_t i;
|
||||
DWORD sid_len;
|
||||
PSID *sids;
|
||||
PACL dacl;
|
||||
LPSTR domain = NULL;
|
||||
BOOLEAN flag;
|
||||
|
||||
sids = malloc(acl->count * sizeof(PSID));
|
||||
if (sids == NULL) {
|
||||
status = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
for (i = 0; i < acl->count; i++) {
|
||||
convert_nfs4name_2_user_domain((LPSTR)acl->aces[i].who, &domain);
|
||||
dprintf(1, "handle_getacl: for user=%s domain=%s\n",
|
||||
acl->aces[i].who, domain?domain:"<null>");
|
||||
status = check_4_special_identifiers(acl->aces[i].who, &sids[i],
|
||||
&sid_len, &flag);
|
||||
if (status) {
|
||||
free_sids(sids, i);
|
||||
goto out;
|
||||
}
|
||||
if (!flag) {
|
||||
status = map_name_2_sid(&sid_len, &sids[i], (LPSTR)acl->aces[i].who);
|
||||
if (status) {
|
||||
free_sids(sids, i);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
size += sid_len - sizeof(DWORD);
|
||||
}
|
||||
size += sizeof(ACL) + (sizeof(ACCESS_ALLOWED_ACE)*acl->count);
|
||||
size = (size + sizeof(DWORD) - 1) & 0xfffffffc; //align size on word boundry
|
||||
dacl = malloc(size);
|
||||
if (dacl == NULL)
|
||||
goto out_free_sids;
|
||||
|
||||
if (InitializeAcl(dacl, size, ACL_REVISION)) {
|
||||
ACCESS_MASK mask;
|
||||
for (i = 0; i < acl->count; i++) {
|
||||
// nfs4 acemask should be exactly the same as file access mask
|
||||
mask = acl->aces[i].acemask;
|
||||
if (acl->aces[i].acetype == ACE4_ACCESS_ALLOWED_ACE_TYPE) {
|
||||
status = AddAccessAllowedAce(dacl, ACL_REVISION, mask, sids[i]);
|
||||
if (!status) {
|
||||
eprintf("convert_nfs4acl_2_dacl: AddAccessAllowedAce failed "
|
||||
"with %d\n", status);
|
||||
goto out_free_dacl;
|
||||
}
|
||||
else status = ERROR_SUCCESS;
|
||||
} else if (acl->aces[i].acetype == ACE4_ACCESS_DENIED_ACE_TYPE) {
|
||||
status = AddAccessDeniedAce(dacl, ACL_REVISION, mask, sids[i]);
|
||||
if (!status) {
|
||||
eprintf("convert_nfs4acl_2_dacl: AddAccessDeniedAce failed "
|
||||
"with %d\n", status);
|
||||
goto out_free_dacl;
|
||||
}
|
||||
else status = ERROR_SUCCESS;
|
||||
} else {
|
||||
eprintf("convert_nfs4acl_2_dacl: unknown acetype %d\n",
|
||||
acl->aces[i].acetype);
|
||||
status = ERROR_INTERNAL_ERROR;
|
||||
free(dacl);
|
||||
free_sids(sids, acl->count);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
eprintf("convert_nfs4acl_2_dacl: InitializeAcl failed with %d\n", status);
|
||||
goto out_free_dacl;
|
||||
}
|
||||
*sids_out = sids;
|
||||
*dacl_out = dacl;
|
||||
out:
|
||||
return status;
|
||||
out_free_dacl:
|
||||
free(dacl);
|
||||
out_free_sids:
|
||||
free_sids(sids, acl->count);
|
||||
status = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
|
||||
static int handle_getacl(nfs41_upcall *upcall)
|
||||
|
|
@ -151,6 +278,10 @@ static int handle_getacl(nfs41_upcall *upcall)
|
|||
bitmap4 attr_request;
|
||||
LPSTR domain = NULL;
|
||||
SECURITY_DESCRIPTOR sec_desc;
|
||||
PACL dacl = NULL;
|
||||
PSID *sids = NULL;
|
||||
PSID osid = NULL, gsid = NULL;
|
||||
DWORD sid_len;
|
||||
|
||||
// need to cache owner/group information XX
|
||||
ZeroMemory(&info, sizeof(info));
|
||||
|
|
@ -165,59 +296,82 @@ static int handle_getacl(nfs41_upcall *upcall)
|
|||
}
|
||||
status = nfs41_getattr(state->session, &state->file, &attr_request, &info);
|
||||
if (status) {
|
||||
eprintf("nfs41_cached_getattr() failed with %d\n", status);
|
||||
eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
|
||||
status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
status = InitializeSecurityDescriptor(&sec_desc, SECURITY_DESCRIPTOR_REVISION);
|
||||
status = InitializeSecurityDescriptor(&sec_desc,
|
||||
SECURITY_DESCRIPTOR_REVISION);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
eprintf("handle_getacl: InitializeSecurityDescriptor failed with %d\n", status);
|
||||
eprintf("handle_getacl: InitializeSecurityDescriptor failed with %d\n",
|
||||
status);
|
||||
goto out;
|
||||
}
|
||||
|
||||
args->osid_len = args->gsid_len = 0;
|
||||
/* can't (re)use the same sid variable for both owner and group sids
|
||||
* because security descriptor is created in absolute-form and it just
|
||||
* stores pointers to the sids. thus each owner and group needs its own
|
||||
* memory. free them after creating self-relative security descriptor.
|
||||
*/
|
||||
if (args->query & OWNER_SECURITY_INFORMATION) {
|
||||
// parse user@domain. currently ignoring domain part XX
|
||||
convert_nfs4name_2_user_domain((LPSTR)info.owner, &domain);
|
||||
dprintf(1, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s domain=%s\n",
|
||||
info.owner, domain?domain:"<null>");
|
||||
status = map_name_2_sid(&args->osid_len, &args->osid, (LPSTR)info.owner);
|
||||
dprintf(1, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s "
|
||||
"domain=%s\n", info.owner, domain?domain:"<null>");
|
||||
sid_len = 0;
|
||||
status = map_name_2_sid(&sid_len, &osid, (LPSTR)info.owner);
|
||||
if (status)
|
||||
goto out;
|
||||
status = SetSecurityDescriptorOwner(&sec_desc, args->osid, TRUE);
|
||||
free(args->osid);
|
||||
status = SetSecurityDescriptorOwner(&sec_desc, osid, TRUE);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
eprintf("handle_getacl: SetSecurityDescriptorOwner failed with %d\n", status);
|
||||
eprintf("handle_getacl: SetSecurityDescriptorOwner failed with "
|
||||
"%d\n", status);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (args->query & GROUP_SECURITY_INFORMATION) {
|
||||
convert_nfs4name_2_user_domain((LPSTR)info.owner_group, &domain);
|
||||
dprintf(1, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s domain=%s\n",
|
||||
info.owner_group, domain?domain:"<null>");
|
||||
status = map_name_2_sid(&args->gsid_len, &args->gsid, (LPSTR)info.owner_group);
|
||||
dprintf(1, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s "
|
||||
"domain=%s\n", info.owner_group, domain?domain:"<null>");
|
||||
sid_len = 0;
|
||||
status = map_name_2_sid(&sid_len, &gsid, (LPSTR)info.owner_group);
|
||||
if (status)
|
||||
goto out;
|
||||
status = SetSecurityDescriptorGroup(&sec_desc, args->gsid, TRUE);
|
||||
free(args->gsid);
|
||||
status = SetSecurityDescriptorGroup(&sec_desc, gsid, TRUE);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
eprintf("handle_getacl: SetSecurityDescriptorGroup failed with %d\n", status);
|
||||
eprintf("handle_getacl: SetSecurityDescriptorGroup failed with "
|
||||
"%d\n", status);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
if (args->query & DACL_SECURITY_INFORMATION)
|
||||
if (args->query & DACL_SECURITY_INFORMATION) {
|
||||
dprintf(1, "handle_getacl: DACL_SECURITY_INFORMATION\n");
|
||||
if (args->query & SACL_SECURITY_INFORMATION)
|
||||
dprintf(1, "handle_getacl: SACL_SECURITY_INFORMATION\n");
|
||||
status = convert_nfs4acl_2_dacl(info.acl, state->type, &dacl, &sids);
|
||||
if (status)
|
||||
goto out;
|
||||
status = SetSecurityDescriptorDacl(&sec_desc, TRUE, dacl, TRUE);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
eprintf("handle_getacl: SetSecurityDescriptorDacl failed with "
|
||||
"%d\n", status);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
args->sec_desc_len = 0;
|
||||
status = MakeSelfRelativeSD(&sec_desc, args->sec_desc, &args->sec_desc_len);
|
||||
if (!status) {
|
||||
if (status) {
|
||||
status = ERROR_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
status = GetLastError();
|
||||
if (status == ERROR_INSUFFICIENT_BUFFER) {
|
||||
if (status != ERROR_INSUFFICIENT_BUFFER) {
|
||||
eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
args->sec_desc = malloc(args->sec_desc_len);
|
||||
if (args->sec_desc == NULL) {
|
||||
status = GetLastError();
|
||||
|
|
@ -229,25 +383,26 @@ static int handle_getacl(nfs41_upcall *upcall)
|
|||
eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status);
|
||||
free(args->sec_desc);
|
||||
goto out;
|
||||
} else status = 0;
|
||||
} else {
|
||||
eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
} else { // this shouldn't happen
|
||||
status = ERROR_INTERNAL_ERROR;
|
||||
goto out;
|
||||
}
|
||||
} else status = ERROR_SUCCESS;
|
||||
|
||||
out:
|
||||
if (args->query & OWNER_SECURITY_INFORMATION) {
|
||||
if (osid) free(osid);
|
||||
}
|
||||
if (args->query & GROUP_SECURITY_INFORMATION) {
|
||||
if (gsid) free(gsid);
|
||||
}
|
||||
if (args->query & DACL_SECURITY_INFORMATION) {
|
||||
if (sids) free_sids(sids, info.acl->count);
|
||||
free(dacl);
|
||||
nfsacl41_free(info.acl);
|
||||
free(info.acl);
|
||||
}
|
||||
return status;
|
||||
}
|
||||
|
||||
static int marshall_getacl(unsigned char *buffer, uint32_t *length, nfs41_upcall *upcall)
|
||||
static int marshall_getacl(unsigned char *buffer, uint32_t *length,
|
||||
nfs41_upcall *upcall)
|
||||
{
|
||||
int status = ERROR_NOT_SUPPORTED;
|
||||
getacl_upcall_args *args = &upcall->args.getacl;
|
||||
|
|
@ -267,7 +422,8 @@ const nfs41_upcall_op nfs41_op_getacl = {
|
|||
marshall_getacl
|
||||
};
|
||||
|
||||
static int parse_setacl(unsigned char *buffer, uint32_t length, nfs41_upcall *upcall)
|
||||
static int parse_setacl(unsigned char *buffer, uint32_t length,
|
||||
nfs41_upcall *upcall)
|
||||
{
|
||||
int status;
|
||||
setacl_upcall_args *args = &upcall->args.setacl;
|
||||
|
|
@ -298,7 +454,8 @@ static int parse_setacl(unsigned char *buffer, uint32_t length, nfs41_upcall *up
|
|||
} else status = 0;
|
||||
|
||||
dprintf(1, "parsing NFS41_ACL_SET: info_class=%d root=0x%p open_state=0x%p"
|
||||
"sec_desc_len=%d\n", args->query, args->root, args->state, sec_desc_len);
|
||||
" sec_desc_len=%d\n", args->query, args->root, args->state,
|
||||
sec_desc_len);
|
||||
out:
|
||||
return status;
|
||||
out_free:
|
||||
|
|
@ -316,30 +473,41 @@ static int is_well_known_sid(PSID sid, char *who)
|
|||
dprintf(1, "WELL_KNOWN_SID_TYPE %d\n", i);
|
||||
switch((WELL_KNOWN_SID_TYPE)i) {
|
||||
case WinCreatorOwnerSid:
|
||||
memcpy(who, ACE4_OWNER, strlen(ACE4_OWNER)+1); return TRUE;
|
||||
memcpy(who, ACE4_OWNER, strlen(ACE4_OWNER)+1);
|
||||
return TRUE;
|
||||
case WinNullSid:
|
||||
memcpy(who, ACE4_NOBODY, strlen(ACE4_NOBODY)+1); return TRUE;
|
||||
memcpy(who, ACE4_NOBODY, strlen(ACE4_NOBODY)+1);
|
||||
return TRUE;
|
||||
case WinAnonymousSid:
|
||||
memcpy(who, ACE4_ANONYMOUS, strlen(ACE4_ANONYMOUS)+1); return TRUE;
|
||||
memcpy(who, ACE4_ANONYMOUS, strlen(ACE4_ANONYMOUS)+1);
|
||||
return TRUE;
|
||||
case WinWorldSid:
|
||||
memcpy(who, ACE4_EVERYONE, strlen(ACE4_EVERYONE)+1); return TRUE;
|
||||
memcpy(who, ACE4_EVERYONE, strlen(ACE4_EVERYONE)+1);
|
||||
return TRUE;
|
||||
case WinCreatorGroupSid:
|
||||
case WinBuiltinUsersSid:
|
||||
memcpy(who, ACE4_GROUP, strlen(ACE4_GROUP)+1); return TRUE;
|
||||
memcpy(who, ACE4_GROUP, strlen(ACE4_GROUP)+1);
|
||||
return TRUE;
|
||||
case WinAuthenticatedUserSid:
|
||||
memcpy(who, ACE4_AUTHENTICATED, strlen(ACE4_AUTHENTICATED)+1); return TRUE;
|
||||
memcpy(who, ACE4_AUTHENTICATED, strlen(ACE4_AUTHENTICATED)+1);
|
||||
return TRUE;
|
||||
case WinDialupSid:
|
||||
memcpy(who, ACE4_DIALUP, strlen(ACE4_DIALUP)+1); return TRUE;
|
||||
memcpy(who, ACE4_DIALUP, strlen(ACE4_DIALUP)+1);
|
||||
return TRUE;
|
||||
case WinNetworkSid:
|
||||
memcpy(who, ACE4_NETWORK, strlen(ACE4_NETWORK)+1); return TRUE;
|
||||
memcpy(who, ACE4_NETWORK, strlen(ACE4_NETWORK)+1);
|
||||
return TRUE;
|
||||
case WinBatchSid:
|
||||
memcpy(who, ACE4_BATCH, strlen(ACE4_BATCH)+1); return TRUE;
|
||||
memcpy(who, ACE4_BATCH, strlen(ACE4_BATCH)+1);
|
||||
return TRUE;
|
||||
case WinInteractiveSid:
|
||||
memcpy(who, ACE4_INTERACTIVE, strlen(ACE4_INTERACTIVE)+1); return TRUE;
|
||||
memcpy(who, ACE4_INTERACTIVE, strlen(ACE4_INTERACTIVE)+1);
|
||||
return TRUE;
|
||||
case WinNetworkServiceSid:
|
||||
case WinLocalServiceSid:
|
||||
case WinServiceSid:
|
||||
memcpy(who, ACE4_SERVICE, strlen(ACE4_SERVICE)+1); return TRUE;
|
||||
memcpy(who, ACE4_SERVICE, strlen(ACE4_SERVICE)+1);
|
||||
return TRUE;
|
||||
default: return FALSE;
|
||||
}
|
||||
}
|
||||
|
|
@ -359,151 +527,36 @@ static void map_aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags)
|
|||
*nfs4_aceflags |= ACE4_INHERIT_ONLY_ACE;
|
||||
if (win_aceflags & INHERITED_ACE)
|
||||
*nfs4_aceflags |= ACE4_INHERITED_ACE;
|
||||
dprintf(1, "ACE FLAGS: %x nfs4 aceflags %x\n", win_aceflags, *nfs4_aceflags);
|
||||
}
|
||||
|
||||
static void set_ace4_read_data(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding STANDARD_RIGHTS_READ . winnt.h defines that as read_control which is acl/owner */
|
||||
/* excluding STANDARD_RIGHTS_REQUIRED, STANDARD_RIGHTS_ALL, SPECIFIC_RIGHTS_ALL,
|
||||
* FILE_GENERIC_READ, FILE_ALL_ACCESS */
|
||||
if (mask & FILE_READ_DATA || mask & GENERIC_READ || mask & GENERIC_ALL /*||
|
||||
(mask & FILE_GENERIC_READ || mask & FILE_ALL_ACCESS)*/)
|
||||
*nfs4_mask |= ACE4_READ_DATA;
|
||||
}
|
||||
|
||||
static void set_ace4_list_directory(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask)
|
||||
{
|
||||
if (file_type == NF4DIR && (mask & FILE_TRAVERSE))
|
||||
*nfs4_mask |= ACE4_LIST_DIRECTORY;
|
||||
}
|
||||
|
||||
static void set_ace4_writeappend_data(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding STANDARD_RIGHTS_WRITE . winnt.h defines that as read_control which is acl/owner */
|
||||
/* excluding STANDARD_RIGHTS_REQUIRED, STANDARD_RIGHTS_ALL and SPECIFIC_RIGHTS_ALL,
|
||||
* FILE_GENERIC_WRITE, FILE_ALL_ACCESS NEED IT ???*/
|
||||
if (mask & FILE_WRITE_DATA || mask & GENERIC_WRITE
|
||||
|| mask & GENERIC_ALL || mask & FILE_APPEND_DATA ||
|
||||
(mask & FILE_GENERIC_WRITE /*|| mask & FILE_ALL_ACCESS*/))
|
||||
*nfs4_mask |= ACE4_WRITE_DATA | ACE4_APPEND_DATA;
|
||||
}
|
||||
|
||||
static void set_ace4_read_named_attributes(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_GENERIC_READ, FILE_ALL_ACCESS, GENERIC_ALL */
|
||||
if (mask & FILE_READ_EA /*||
|
||||
(mask & FILE_GENERIC_READ || mask & FILE_ALL_ACCESS || mask & GENERIC_ALL)*/)
|
||||
*nfs4_mask |= ACE4_READ_NAMED_ATTRS;
|
||||
}
|
||||
|
||||
static void set_ace4_write_named_attributes(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_GENERIC_WRITE, FILE_ALL_ACCESS, GENERIC_ALL */
|
||||
if (mask & FILE_WRITE_EA /*||
|
||||
(mask & FILE_GENERIC_WRITE || mask & FILE_ALL_ACCESS || mask & GENERIC_ALL)*/)
|
||||
*nfs4_mask |= ACE4_WRITE_NAMED_ATTRS;
|
||||
}
|
||||
|
||||
static void set_ace4_execute(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding STANDARD_RIGHTS_EXECUTE . winnt.h defines that as read_control which is acl/owner */
|
||||
/* excluding STANDARD_RIGHTS_REQUIRED, STANDARD_RIGHTS_ALL and SPECIFIC_RIGHTS_ALL,
|
||||
* FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS NEED IT ???*/
|
||||
if (mask & FILE_EXECUTE || mask & GENERIC_EXECUTE || mask & GENERIC_ALL ||
|
||||
(mask & FILE_GENERIC_EXECUTE || mask & FILE_ALL_ACCESS))
|
||||
*nfs4_mask |= ACE4_EXECUTE;
|
||||
}
|
||||
|
||||
static void set_ace4_delete(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_ALL_ACCESS, GENERIC_ALL */
|
||||
if (mask & FILE_DELETE_CHILD || mask & DELETE ||
|
||||
mask & STANDARD_RIGHTS_REQUIRED || mask & STANDARD_RIGHTS_ALL ||
|
||||
mask & SPECIFIC_RIGHTS_ALL)
|
||||
if (file_type == NF4DIR)
|
||||
*nfs4_mask |= ACE4_DELETE_CHILD;
|
||||
else
|
||||
*nfs4_mask |= ACE4_DELETE;
|
||||
}
|
||||
|
||||
static void set_ace4_read_attributes(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding STANDARD_RIGHTS_REQUIRED, STANDARD_RIGHTS_ALL and SPECIFIC_RIGHTS_ALL,
|
||||
* FILE_GENERIC_READ, FILE_ALL_ACCESS, GENERIC_ALL*/
|
||||
if (mask & FILE_READ_ATTRIBUTES)
|
||||
*nfs4_mask |= ACE4_READ_ATTRIBUTES;
|
||||
}
|
||||
|
||||
static void set_ace4_write_attributes(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding STANDARD_RIGHTS_REQUIRED, STANDARD_RIGHTS_ALL and SPECIFIC_RIGHTS_ALL,
|
||||
* FILE_GENERIC_WRITE, FILE_ALL_ACCESS, GENERIC_ALL*/
|
||||
if (mask & FILE_WRITE_ATTRIBUTES)
|
||||
*nfs4_mask |= ACE4_WRITE_ATTRIBUTES;
|
||||
}
|
||||
|
||||
static void set_ace4_read_acl(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_ALL_ACCESS */
|
||||
if (mask & READ_CONTROL || mask & STANDARD_RIGHTS_READ ||
|
||||
mask & STANDARD_RIGHTS_ALL || mask & SPECIFIC_RIGHTS_ALL ||
|
||||
mask & STANDARD_RIGHTS_REQUIRED)
|
||||
*nfs4_mask |= ACE4_READ_ACL;
|
||||
}
|
||||
|
||||
static void set_ace4_write_acl(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_ALL_ACCESS */
|
||||
if (mask & WRITE_DAC || mask & STANDARD_RIGHTS_WRITE ||
|
||||
mask & STANDARD_RIGHTS_ALL || mask & SPECIFIC_RIGHTS_ALL ||
|
||||
mask & STANDARD_RIGHTS_REQUIRED)
|
||||
*nfs4_mask |= ACE4_WRITE_ACL;
|
||||
}
|
||||
|
||||
static void set_ace4_write_owner(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_ALL_ACCESS */
|
||||
if (mask & WRITE_OWNER || mask & STANDARD_RIGHTS_WRITE ||
|
||||
mask & STANDARD_RIGHTS_ALL || mask & SPECIFIC_RIGHTS_ALL ||
|
||||
mask & STANDARD_RIGHTS_REQUIRED)
|
||||
*nfs4_mask |= ACE4_WRITE_OWNER;
|
||||
}
|
||||
|
||||
static void set_ace4_synchronize(ACCESS_MASK mask, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* excluding FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE,
|
||||
* FILE_ALL_ACCESS */
|
||||
if (mask & SYNCHRONIZE || mask & STANDARD_RIGHTS_ALL ||
|
||||
mask & SPECIFIC_RIGHTS_ALL)
|
||||
*nfs4_mask |= ACE4_SYNCHRONIZE;
|
||||
dprintf(1, "ACE FLAGS: %x nfs4 aceflags %x\n",
|
||||
win_aceflags, *nfs4_aceflags);
|
||||
}
|
||||
|
||||
static void map_acemask(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask)
|
||||
{
|
||||
/* 03/31/2011 NOT HANDLING LINKS */
|
||||
print_windows_access_mask(mask);
|
||||
|
||||
set_ace4_read_data(mask, file_type, nfs4_mask);
|
||||
set_ace4_list_directory(mask, file_type, nfs4_mask);
|
||||
set_ace4_writeappend_data(mask, file_type, nfs4_mask);
|
||||
set_ace4_read_named_attributes(mask, nfs4_mask);
|
||||
set_ace4_write_named_attributes(mask, nfs4_mask);
|
||||
set_ace4_execute(mask, nfs4_mask);
|
||||
set_ace4_delete(mask, file_type, nfs4_mask);
|
||||
set_ace4_read_attributes(mask, nfs4_mask);
|
||||
set_ace4_write_attributes(mask, nfs4_mask);
|
||||
set_ace4_read_acl(mask, nfs4_mask);
|
||||
set_ace4_write_acl(mask, nfs4_mask);
|
||||
set_ace4_write_owner(mask, nfs4_mask);
|
||||
set_ace4_synchronize(mask, nfs4_mask);
|
||||
|
||||
dprintf(1, "ACCESS MASK %d object type=%d nfs4 mask %x\n",
|
||||
mask, file_type, *nfs4_mask);
|
||||
print_nfs_access_mask(*nfs4_mask);
|
||||
dprintf(1, "ACE MASK: %x\n", mask);
|
||||
print_windows_access_mask(0, mask);
|
||||
/* check if any GENERIC bits set */
|
||||
if (mask & 0xf000000) {
|
||||
if (mask & GENERIC_ALL) {
|
||||
if (file_type == NF4DIR)
|
||||
*nfs4_mask |= ACE4_ALL_DIR;
|
||||
else
|
||||
*nfs4_mask |= ACE4_ALL_FILE;
|
||||
} else {
|
||||
if (mask & GENERIC_READ)
|
||||
*nfs4_mask |= ACE4_GENERIC_READ;
|
||||
if (mask & GENERIC_WRITE)
|
||||
*nfs4_mask |= ACE4_GENERIC_WRITE;
|
||||
if (mask & GENERIC_EXECUTE)
|
||||
*nfs4_mask |= ACE4_GENERIC_EXECUTE;
|
||||
}
|
||||
}
|
||||
else /* ignoring generic and reserved bits */
|
||||
*nfs4_mask = mask & 0x00ffffff;
|
||||
print_nfs_access_mask(0, *nfs4_mask);
|
||||
}
|
||||
|
||||
static int map_who(PSID sid, char *who_out)
|
||||
static int map_nfs4ace_who(PSID sid, PSID owner_sid, char *who_out, char *domain)
|
||||
{
|
||||
int status = ERROR_INTERNAL_ERROR;
|
||||
DWORD size = 0, tmp_size = 0;
|
||||
|
|
@ -516,53 +569,63 @@ static int map_who(PSID sid, char *who_out)
|
|||
status = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
if (EqualSid(sid, owner_sid)) {
|
||||
dprintf(1, "map_nfs4ace_who: this is owner's sid\n");
|
||||
memcpy(who_out, ACE4_OWNER, strlen(ACE4_OWNER)+1);
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
status = is_well_known_sid(sid, who_out);
|
||||
if (status)
|
||||
return 0;
|
||||
if (status) {
|
||||
if (!strncmp(who_out, ACE4_NOBODY, strlen(ACE4_NOBODY))) {
|
||||
size = strlen(ACE4_NOBODY);
|
||||
goto add_domain;
|
||||
}
|
||||
else
|
||||
return ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
status = LookupAccountSid(NULL, sid, who, &size, tmp_buf,
|
||||
&tmp_size, &sid_type);
|
||||
if (!status) {
|
||||
dprintf(1, "map_nfs4ace_who: LookupAccountSid returned %d GetLastError "
|
||||
"%d name len %d domain len %d\n", status, GetLastError(),
|
||||
size, tmp_size);
|
||||
if (status)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
status = GetLastError();
|
||||
if (status == ERROR_INSUFFICIENT_BUFFER) {
|
||||
if (status != ERROR_INSUFFICIENT_BUFFER)
|
||||
return ERROR_INTERNAL_ERROR;
|
||||
who = malloc(size);
|
||||
if (who == NULL) {
|
||||
status = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
tmp_buf = malloc(tmp_size);
|
||||
if (tmp_buf == NULL) {
|
||||
status = GetLastError();
|
||||
free(who);
|
||||
goto out;
|
||||
}
|
||||
if (tmp_buf == NULL)
|
||||
goto out_free_who;
|
||||
status = LookupAccountSid(NULL, sid, who, &size, tmp_buf,
|
||||
&tmp_size, &sid_type);
|
||||
free(tmp_buf);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
eprintf("map_dacl_2_nfs4acl: failed to lookup account name "
|
||||
"for sid %d\n", status);
|
||||
free(who);
|
||||
goto out;
|
||||
eprintf("map_nfs4ace_who: LookupAccountSid failed with %d\n",
|
||||
GetLastError());
|
||||
goto out_free_who;
|
||||
}
|
||||
memcpy(who_out, who, size);
|
||||
memcpy(who_out+size, "@citi.umich.edu", 15);
|
||||
|
||||
free(who);
|
||||
status = 0;
|
||||
} else {
|
||||
eprintf("map_dacl_2_nfs4acl: failed to lookup account name for "
|
||||
"sid %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
} else {
|
||||
dprintf(1, "this shouldn't happen\n");
|
||||
goto out;
|
||||
}
|
||||
add_domain:
|
||||
memcpy(who_out+size, "@", sizeof(char));
|
||||
memcpy(who_out+size+1, domain, strlen(domain)+1);
|
||||
dprintf(1, "map_nfs4ace_who: who=%s\n", who_out);
|
||||
if (who) free(who);
|
||||
status = ERROR_SUCCESS;
|
||||
out:
|
||||
return status;
|
||||
out_free_who:
|
||||
free(who);
|
||||
status = GetLastError();
|
||||
goto out;
|
||||
}
|
||||
static int map_dacl_2_nfs4acl(PACL acl, nfsacl41 *nfs4_acl, int file_type)
|
||||
static int map_dacl_2_nfs4acl(PACL acl, PSID sid, nfsacl41 *nfs4_acl,
|
||||
int file_type, char *domain)
|
||||
{
|
||||
int status;
|
||||
if (acl == NULL) {
|
||||
|
|
@ -576,7 +639,10 @@ static int map_dacl_2_nfs4acl(PACL acl, nfsacl41 *nfs4_acl, int file_type)
|
|||
nfs4_acl->flag = 0;
|
||||
memcpy(nfs4_acl->aces->who, ACE4_EVERYONE, strlen(ACE4_EVERYONE)+1);
|
||||
nfs4_acl->aces->acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE;
|
||||
nfs4_acl->aces->acemask = ACE4_ALL;
|
||||
if (file_type == NF4DIR)
|
||||
nfs4_acl->aces->acemask = ACE4_ALL_DIR;
|
||||
else
|
||||
nfs4_acl->aces->acemask = ACE4_ALL_FILE;
|
||||
nfs4_acl->aces->aceflag = 0;
|
||||
} else {
|
||||
int i;
|
||||
|
|
@ -584,7 +650,8 @@ static int map_dacl_2_nfs4acl(PACL acl, nfsacl41 *nfs4_acl, int file_type)
|
|||
PBYTE tmp_pointer;
|
||||
|
||||
dprintf(1, "NON-NULL dacl with %d ACEs\n", acl->AceCount);
|
||||
print_hexbuf_no_asci(3, (unsigned char *)"ACL\n", (unsigned char *)acl, acl->AclSize);
|
||||
print_hexbuf_no_asci(3, (unsigned char *)"ACL\n",
|
||||
(unsigned char *)acl, acl->AclSize);
|
||||
nfs4_acl->count = acl->AceCount;
|
||||
nfs4_acl->aces = calloc(nfs4_acl->count, sizeof(nfsace4));
|
||||
if (nfs4_acl->aces == NULL) {
|
||||
|
|
@ -596,10 +663,12 @@ static int map_dacl_2_nfs4acl(PACL acl, nfsacl41 *nfs4_acl, int file_type)
|
|||
status = GetAce(acl, i, &ace);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
goto out;
|
||||
eprintf("map_dacl_2_nfs4acl: GetAce failed with %d\n", status);
|
||||
goto out_free;
|
||||
}
|
||||
tmp_pointer = (PBYTE)ace;
|
||||
print_hexbuf_no_asci(3, (unsigned char *)"ACE\n", (unsigned char *)ace, ace->AceSize);
|
||||
print_hexbuf_no_asci(3, (unsigned char *)"ACE\n",
|
||||
(unsigned char *)ace, ace->AceSize);
|
||||
dprintf(1, "ACE TYPE: %x\n", ace->AceType);
|
||||
if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
|
||||
nfs4_acl->aces[i].acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE;
|
||||
|
|
@ -613,15 +682,17 @@ static int map_dacl_2_nfs4acl(PACL acl, nfsacl41 *nfs4_acl, int file_type)
|
|||
}
|
||||
|
||||
map_aceflags(ace->AceFlags, &nfs4_acl->aces[i].aceflag);
|
||||
map_acemask(*(PACCESS_MASK)(ace + 1), file_type, &nfs4_acl->aces[i].acemask);
|
||||
map_acemask(*(PACCESS_MASK)(ace + 1), file_type,
|
||||
&nfs4_acl->aces[i].acemask);
|
||||
|
||||
tmp_pointer += sizeof(ACCESS_MASK) + sizeof(ACE_HEADER);
|
||||
status = map_who(tmp_pointer, nfs4_acl->aces[i].who);
|
||||
status = map_nfs4ace_who(tmp_pointer, sid, nfs4_acl->aces[i].who,
|
||||
domain);
|
||||
if (status)
|
||||
goto out_free;
|
||||
}
|
||||
}
|
||||
status = 0;
|
||||
status = ERROR_SUCCESS;
|
||||
out:
|
||||
return status;
|
||||
out_free:
|
||||
|
|
@ -645,8 +716,9 @@ static int handle_setacl(nfs41_upcall *upcall)
|
|||
if (args->query & GROUP_SECURITY_INFORMATION)
|
||||
dprintf(1, "handle_setacl: GROUP_SECURITY_INFORMATION\n");
|
||||
if (args->query & DACL_SECURITY_INFORMATION) {
|
||||
BOOL dacl_present, dacl_default;
|
||||
BOOL dacl_present, dacl_default, sid_default;
|
||||
PACL acl;
|
||||
PSID sid;
|
||||
dprintf(1, "handle_setacl: DACL_SECURITY_INFORMATION\n");
|
||||
status = GetSecurityDescriptorDacl(args->sec_desc, &dacl_present,
|
||||
&acl, &dacl_default);
|
||||
|
|
@ -655,7 +727,14 @@ static int handle_setacl(nfs41_upcall *upcall)
|
|||
eprintf("GetSecurityDescriptorDacl failed with %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
status = map_dacl_2_nfs4acl(acl, &nfs4_acl, state->type);
|
||||
status = GetSecurityDescriptorOwner(args->sec_desc, &sid, &sid_default);
|
||||
if (!status) {
|
||||
status = GetLastError();
|
||||
eprintf("GetSecurityDescriptorOwner failed with %d\n", status);
|
||||
goto out;
|
||||
}
|
||||
status = map_dacl_2_nfs4acl(acl, sid, &nfs4_acl, state->type,
|
||||
state->session->client->domain_name);
|
||||
if (status)
|
||||
goto out;
|
||||
else {
|
||||
|
|
@ -672,10 +751,8 @@ static int handle_setacl(nfs41_upcall *upcall)
|
|||
nfs_error_string(status));
|
||||
status = nfs_to_windows_error(status, ERROR_NOT_SUPPORTED);
|
||||
}
|
||||
|
||||
if (args->query & DACL_SECURITY_INFORMATION)
|
||||
free(nfs4_acl.aces);
|
||||
|
||||
out:
|
||||
free(args->sec_desc);
|
||||
return status;
|
||||
|
|
|
|||
|
|
@ -160,10 +160,6 @@ typedef struct __getacl_upcall_args {
|
|||
nfs41_root *root;
|
||||
nfs41_open_state *state;
|
||||
SECURITY_INFORMATION query;
|
||||
PSID osid;
|
||||
DWORD osid_len;
|
||||
PSID gsid;
|
||||
DWORD gsid_len;
|
||||
PSECURITY_DESCRIPTOR sec_desc;
|
||||
DWORD sec_desc_len;
|
||||
} getacl_upcall_args;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue