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:
Olga Kornievskaia 2011-04-12 16:47:14 -04:00
parent 80b3d11609
commit f78cc24925
2 changed files with 386 additions and 313 deletions

View file

@ -31,7 +31,8 @@
#include "upcall.h" #include "upcall.h"
#include "nfs41_xdr.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; int status;
getacl_upcall_args *args = &upcall->args.getacl; 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)); status = safe_read(&buffer, &length, &args->query, sizeof(args->query));
if (status) goto out; if (status) goto out;
dprintf(1, "parsing NFS41_ACL_QUERY: info_class=%d root=0x%p open_state=0x%p\n", dprintf(1, "parsing NFS41_ACL_QUERY: info_class=%d root=0x%p "
args->query, args->root, args->state); "open_state=0x%p\n", args->query, args->root, args->state);
out: out:
return status; 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; int status;
*sid_len = 0; *sid_len = 0;
*sid = NULL; *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(); status = GetLastError();
if (status == ERROR_INSUFFICIENT_BUFFER) { if (status != ERROR_INSUFFICIENT_BUFFER)
return status;
*sid = malloc(*sid_len); *sid = malloc(*sid_len);
if (*sid == NULL) return ERROR_INSUFFICIENT_BUFFER; if (*sid == NULL)
if (!CreateWellKnownSid(type, NULL, *sid, sid_len)) { return ERROR_INSUFFICIENT_BUFFER;
status = CreateWellKnownSid(type, NULL, *sid, sid_len);
if (status)
return ERROR_SUCCESS;
free(*sid); free(*sid);
status = GetLastError(); status = GetLastError();
dprintf(1, "CreateWellKnownSid failed with %d\n", status); eprintf("create_unknownsid: CreateWellKnownSid failed with %d\n", status);
return status; return status;
} else return 0;
} else return status;
} else return ERROR_INTERNAL_ERROR;
} }
static void convert_nfs4name_2_user_domain(LPSTR nfs4name, 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) 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; SID_NAME_USE sid_type;
LPSTR tmp_buf = NULL; LPSTR tmp_buf = NULL;
DWORD tmp = 0; DWORD tmp = 0;
status = LookupAccountName(NULL, name, NULL, sid_len, NULL, &tmp, &sid_type); status = LookupAccountName(NULL, name, NULL, sid_len, NULL, &tmp, &sid_type);
dprintf(1, "LookupAccountName returned %d GetLastError %d owner len %d " dprintf(1, "map_name_2_sid: LookupAccountName for %s returned %d "
"domain len %d\n", status, GetLastError(), *sid_len, tmp); "GetLastError %d name len %d domain len %d\n", name, status,
if (!status) { GetLastError(), *sid_len, tmp);
if (status)
return ERROR_INTERNAL_ERROR;
status = GetLastError(); status = GetLastError();
switch(status) { switch(status) {
case ERROR_INSUFFICIENT_BUFFER: case ERROR_INSUFFICIENT_BUFFER:
@ -104,42 +116,157 @@ static int map_name_2_sid(DWORD *sid_len, PSID *sid, LPCSTR name)
goto out; goto out;
} }
tmp_buf = (LPSTR) malloc(tmp); tmp_buf = (LPSTR) malloc(tmp);
if (tmp_buf == NULL) { if (tmp_buf == NULL)
status = GetLastError(); goto out_free_sid;
free(*sid);
goto out;
}
status = LookupAccountName(NULL, name, *sid, sid_len, tmp_buf, status = LookupAccountName(NULL, name, *sid, sid_len, tmp_buf,
&tmp, &sid_type); &tmp, &sid_type);
dprintf(1, "sid_type = %d\n", sid_type);
free(tmp_buf); free(tmp_buf);
if (!status) { if (!status) {
status = GetLastError(); eprintf("map_name_2_sid: LookupAccountName for %s failed "
free(*sid); "with %d\n", name, GetLastError());
dprintf(1, "handle_getacl: LookupAccountName for owner failed " goto out_free_sid;
"with %d\n", status);
goto out;
} else { } else {
LPSTR ssid = NULL; LPSTR ssid = NULL;
if (IsValidSid(*sid)) if (IsValidSid(*sid))
if (ConvertSidToStringSidA(*sid, &ssid)) 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 else
printf("ConvertSidToStringSidA failed with %d\n", GetLastError()); dprintf(1, "map_name_2_sid: ConvertSidToStringSidA failed "
"with %d\n", GetLastError());
else else
printf("Invalid Sid\n"); dprintf(1, "map_name_2_sid: Invalid Sid ?\n");
if (ssid) LocalFree(ssid); if (ssid) LocalFree(ssid);
} }
status = 0; status = ERROR_SUCCESS;
break; break;
case ERROR_NONE_MAPPED: case ERROR_NONE_MAPPED:
status = create_unknownsid(WinNullSid, sid, sid_len); status = create_unknownsid(WinNullSid, sid, sid_len);
break; if (status)
goto out_free_sid;
} }
} else // This shouldn't happen
status = ERROR_INTERNAL_ERROR;
out: out:
return status; 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) static int handle_getacl(nfs41_upcall *upcall)
@ -151,6 +278,10 @@ static int handle_getacl(nfs41_upcall *upcall)
bitmap4 attr_request; bitmap4 attr_request;
LPSTR domain = NULL; LPSTR domain = NULL;
SECURITY_DESCRIPTOR sec_desc; 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 // need to cache owner/group information XX
ZeroMemory(&info, sizeof(info)); 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); status = nfs41_getattr(state->session, &state->file, &attr_request, &info);
if (status) { if (status) {
eprintf("nfs41_cached_getattr() failed with %d\n", status); eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
status);
goto out; goto out;
} }
status = InitializeSecurityDescriptor(&sec_desc, SECURITY_DESCRIPTOR_REVISION); status = InitializeSecurityDescriptor(&sec_desc,
SECURITY_DESCRIPTOR_REVISION);
if (!status) { if (!status) {
status = GetLastError(); status = GetLastError();
eprintf("handle_getacl: InitializeSecurityDescriptor failed with %d\n", status); eprintf("handle_getacl: InitializeSecurityDescriptor failed with %d\n",
status);
goto out; goto out;
} }
/* can't (re)use the same sid variable for both owner and group sids
args->osid_len = args->gsid_len = 0; * 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) { if (args->query & OWNER_SECURITY_INFORMATION) {
// parse user@domain. currently ignoring domain part XX // parse user@domain. currently ignoring domain part XX
convert_nfs4name_2_user_domain((LPSTR)info.owner, &domain); convert_nfs4name_2_user_domain((LPSTR)info.owner, &domain);
dprintf(1, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s domain=%s\n", dprintf(1, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s "
info.owner, domain?domain:"<null>"); "domain=%s\n", info.owner, domain?domain:"<null>");
status = map_name_2_sid(&args->osid_len, &args->osid, (LPSTR)info.owner); sid_len = 0;
status = map_name_2_sid(&sid_len, &osid, (LPSTR)info.owner);
if (status) if (status)
goto out; goto out;
status = SetSecurityDescriptorOwner(&sec_desc, args->osid, TRUE); status = SetSecurityDescriptorOwner(&sec_desc, osid, TRUE);
free(args->osid);
if (!status) { if (!status) {
status = GetLastError(); status = GetLastError();
eprintf("handle_getacl: SetSecurityDescriptorOwner failed with %d\n", status); eprintf("handle_getacl: SetSecurityDescriptorOwner failed with "
"%d\n", status);
goto out; goto out;
} }
} }
if (args->query & GROUP_SECURITY_INFORMATION) { if (args->query & GROUP_SECURITY_INFORMATION) {
convert_nfs4name_2_user_domain((LPSTR)info.owner_group, &domain); convert_nfs4name_2_user_domain((LPSTR)info.owner_group, &domain);
dprintf(1, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s domain=%s\n", dprintf(1, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s "
info.owner_group, domain?domain:"<null>"); "domain=%s\n", info.owner_group, domain?domain:"<null>");
status = map_name_2_sid(&args->gsid_len, &args->gsid, (LPSTR)info.owner_group); sid_len = 0;
status = map_name_2_sid(&sid_len, &gsid, (LPSTR)info.owner_group);
if (status) if (status)
goto out; goto out;
status = SetSecurityDescriptorGroup(&sec_desc, args->gsid, TRUE); status = SetSecurityDescriptorGroup(&sec_desc, gsid, TRUE);
free(args->gsid);
if (!status) { if (!status) {
status = GetLastError(); status = GetLastError();
eprintf("handle_getacl: SetSecurityDescriptorGroup failed with %d\n", status); eprintf("handle_getacl: SetSecurityDescriptorGroup failed with "
"%d\n", status);
goto out; goto out;
} }
} }
if (args->query & DACL_SECURITY_INFORMATION) if (args->query & DACL_SECURITY_INFORMATION) {
dprintf(1, "handle_getacl: DACL_SECURITY_INFORMATION\n"); dprintf(1, "handle_getacl: DACL_SECURITY_INFORMATION\n");
if (args->query & SACL_SECURITY_INFORMATION) status = convert_nfs4acl_2_dacl(info.acl, state->type, &dacl, &sids);
dprintf(1, "handle_getacl: SACL_SECURITY_INFORMATION\n"); 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; args->sec_desc_len = 0;
status = MakeSelfRelativeSD(&sec_desc, args->sec_desc, &args->sec_desc_len); status = MakeSelfRelativeSD(&sec_desc, args->sec_desc, &args->sec_desc_len);
if (!status) { if (status) {
status = ERROR_INTERNAL_ERROR;
goto out;
}
status = GetLastError(); 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); args->sec_desc = malloc(args->sec_desc_len);
if (args->sec_desc == NULL) { if (args->sec_desc == NULL) {
status = GetLastError(); status = GetLastError();
@ -229,25 +383,26 @@ static int handle_getacl(nfs41_upcall *upcall)
eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status); eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status);
free(args->sec_desc); free(args->sec_desc);
goto out; goto out;
} else status = 0; } else status = ERROR_SUCCESS;
} else {
eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status);
goto out;
}
} else { // this shouldn't happen
status = ERROR_INTERNAL_ERROR;
goto out;
}
out: 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 (args->query & DACL_SECURITY_INFORMATION) {
if (sids) free_sids(sids, info.acl->count);
free(dacl);
nfsacl41_free(info.acl); nfsacl41_free(info.acl);
free(info.acl); free(info.acl);
} }
return status; 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; int status = ERROR_NOT_SUPPORTED;
getacl_upcall_args *args = &upcall->args.getacl; getacl_upcall_args *args = &upcall->args.getacl;
@ -267,7 +422,8 @@ const nfs41_upcall_op nfs41_op_getacl = {
marshall_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; int status;
setacl_upcall_args *args = &upcall->args.setacl; 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; } else status = 0;
dprintf(1, "parsing NFS41_ACL_SET: info_class=%d root=0x%p open_state=0x%p" 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: out:
return status; return status;
out_free: 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); dprintf(1, "WELL_KNOWN_SID_TYPE %d\n", i);
switch((WELL_KNOWN_SID_TYPE)i) { switch((WELL_KNOWN_SID_TYPE)i) {
case WinCreatorOwnerSid: case WinCreatorOwnerSid:
memcpy(who, ACE4_OWNER, strlen(ACE4_OWNER)+1); return TRUE; memcpy(who, ACE4_OWNER, strlen(ACE4_OWNER)+1);
return TRUE;
case WinNullSid: case WinNullSid:
memcpy(who, ACE4_NOBODY, strlen(ACE4_NOBODY)+1); return TRUE; memcpy(who, ACE4_NOBODY, strlen(ACE4_NOBODY)+1);
return TRUE;
case WinAnonymousSid: case WinAnonymousSid:
memcpy(who, ACE4_ANONYMOUS, strlen(ACE4_ANONYMOUS)+1); return TRUE; memcpy(who, ACE4_ANONYMOUS, strlen(ACE4_ANONYMOUS)+1);
return TRUE;
case WinWorldSid: 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 WinCreatorGroupSid:
case WinBuiltinUsersSid: case WinBuiltinUsersSid:
memcpy(who, ACE4_GROUP, strlen(ACE4_GROUP)+1); return TRUE; memcpy(who, ACE4_GROUP, strlen(ACE4_GROUP)+1);
return TRUE;
case WinAuthenticatedUserSid: case WinAuthenticatedUserSid:
memcpy(who, ACE4_AUTHENTICATED, strlen(ACE4_AUTHENTICATED)+1); return TRUE; memcpy(who, ACE4_AUTHENTICATED, strlen(ACE4_AUTHENTICATED)+1);
return TRUE;
case WinDialupSid: case WinDialupSid:
memcpy(who, ACE4_DIALUP, strlen(ACE4_DIALUP)+1); return TRUE; memcpy(who, ACE4_DIALUP, strlen(ACE4_DIALUP)+1);
return TRUE;
case WinNetworkSid: case WinNetworkSid:
memcpy(who, ACE4_NETWORK, strlen(ACE4_NETWORK)+1); return TRUE; memcpy(who, ACE4_NETWORK, strlen(ACE4_NETWORK)+1);
return TRUE;
case WinBatchSid: case WinBatchSid:
memcpy(who, ACE4_BATCH, strlen(ACE4_BATCH)+1); return TRUE; memcpy(who, ACE4_BATCH, strlen(ACE4_BATCH)+1);
return TRUE;
case WinInteractiveSid: 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 WinNetworkServiceSid:
case WinLocalServiceSid: case WinLocalServiceSid:
case WinServiceSid: 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; default: return FALSE;
} }
} }
@ -359,151 +527,36 @@ static void map_aceflags(BYTE win_aceflags, uint32_t *nfs4_aceflags)
*nfs4_aceflags |= ACE4_INHERIT_ONLY_ACE; *nfs4_aceflags |= ACE4_INHERIT_ONLY_ACE;
if (win_aceflags & INHERITED_ACE) if (win_aceflags & INHERITED_ACE)
*nfs4_aceflags |= ACE4_INHERITED_ACE; *nfs4_aceflags |= ACE4_INHERITED_ACE;
dprintf(1, "ACE FLAGS: %x nfs4 aceflags %x\n", win_aceflags, *nfs4_aceflags); 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;
} }
static void map_acemask(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask) static void map_acemask(ACCESS_MASK mask, int file_type, uint32_t *nfs4_mask)
{ {
/* 03/31/2011 NOT HANDLING LINKS */ dprintf(1, "ACE MASK: %x\n", mask);
print_windows_access_mask(mask); print_windows_access_mask(0, mask);
/* check if any GENERIC bits set */
set_ace4_read_data(mask, file_type, nfs4_mask); if (mask & 0xf000000) {
set_ace4_list_directory(mask, file_type, nfs4_mask); if (mask & GENERIC_ALL) {
set_ace4_writeappend_data(mask, file_type, nfs4_mask); if (file_type == NF4DIR)
set_ace4_read_named_attributes(mask, nfs4_mask); *nfs4_mask |= ACE4_ALL_DIR;
set_ace4_write_named_attributes(mask, nfs4_mask); else
set_ace4_execute(mask, nfs4_mask); *nfs4_mask |= ACE4_ALL_FILE;
set_ace4_delete(mask, file_type, nfs4_mask); } else {
set_ace4_read_attributes(mask, nfs4_mask); if (mask & GENERIC_READ)
set_ace4_write_attributes(mask, nfs4_mask); *nfs4_mask |= ACE4_GENERIC_READ;
set_ace4_read_acl(mask, nfs4_mask); if (mask & GENERIC_WRITE)
set_ace4_write_acl(mask, nfs4_mask); *nfs4_mask |= ACE4_GENERIC_WRITE;
set_ace4_write_owner(mask, nfs4_mask); if (mask & GENERIC_EXECUTE)
set_ace4_synchronize(mask, nfs4_mask); *nfs4_mask |= ACE4_GENERIC_EXECUTE;
}
dprintf(1, "ACCESS MASK %d object type=%d nfs4 mask %x\n", }
mask, file_type, *nfs4_mask); else /* ignoring generic and reserved bits */
print_nfs_access_mask(*nfs4_mask); *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; int status = ERROR_INTERNAL_ERROR;
DWORD size = 0, tmp_size = 0; DWORD size = 0, tmp_size = 0;
@ -516,53 +569,63 @@ static int map_who(PSID sid, char *who_out)
status = GetLastError(); status = GetLastError();
goto out; 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); status = is_well_known_sid(sid, who_out);
if (status) if (status) {
return 0; 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, status = LookupAccountSid(NULL, sid, who, &size, tmp_buf,
&tmp_size, &sid_type); &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(); status = GetLastError();
if (status == ERROR_INSUFFICIENT_BUFFER) { if (status != ERROR_INSUFFICIENT_BUFFER)
return ERROR_INTERNAL_ERROR;
who = malloc(size); who = malloc(size);
if (who == NULL) { if (who == NULL) {
status = GetLastError(); status = GetLastError();
goto out; goto out;
} }
tmp_buf = malloc(tmp_size); tmp_buf = malloc(tmp_size);
if (tmp_buf == NULL) { if (tmp_buf == NULL)
status = GetLastError(); goto out_free_who;
free(who);
goto out;
}
status = LookupAccountSid(NULL, sid, who, &size, tmp_buf, status = LookupAccountSid(NULL, sid, who, &size, tmp_buf,
&tmp_size, &sid_type); &tmp_size, &sid_type);
free(tmp_buf); free(tmp_buf);
if (!status) { if (!status) {
status = GetLastError(); eprintf("map_nfs4ace_who: LookupAccountSid failed with %d\n",
eprintf("map_dacl_2_nfs4acl: failed to lookup account name " GetLastError());
"for sid %d\n", status); goto out_free_who;
free(who);
goto out;
} }
memcpy(who_out, who, size); memcpy(who_out, who, size);
memcpy(who_out+size, "@citi.umich.edu", 15); add_domain:
memcpy(who_out+size, "@", sizeof(char));
free(who); memcpy(who_out+size+1, domain, strlen(domain)+1);
status = 0; dprintf(1, "map_nfs4ace_who: who=%s\n", who_out);
} else { if (who) free(who);
eprintf("map_dacl_2_nfs4acl: failed to lookup account name for " status = ERROR_SUCCESS;
"sid %d\n", status);
goto out;
}
} else {
dprintf(1, "this shouldn't happen\n");
goto out;
}
out: out:
return status; 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; int status;
if (acl == NULL) { 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; nfs4_acl->flag = 0;
memcpy(nfs4_acl->aces->who, ACE4_EVERYONE, strlen(ACE4_EVERYONE)+1); memcpy(nfs4_acl->aces->who, ACE4_EVERYONE, strlen(ACE4_EVERYONE)+1);
nfs4_acl->aces->acetype = ACE4_ACCESS_ALLOWED_ACE_TYPE; 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; nfs4_acl->aces->aceflag = 0;
} else { } else {
int i; int i;
@ -584,7 +650,8 @@ static int map_dacl_2_nfs4acl(PACL acl, nfsacl41 *nfs4_acl, int file_type)
PBYTE tmp_pointer; PBYTE tmp_pointer;
dprintf(1, "NON-NULL dacl with %d ACEs\n", acl->AceCount); 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->count = acl->AceCount;
nfs4_acl->aces = calloc(nfs4_acl->count, sizeof(nfsace4)); nfs4_acl->aces = calloc(nfs4_acl->count, sizeof(nfsace4));
if (nfs4_acl->aces == NULL) { 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); status = GetAce(acl, i, &ace);
if (!status) { if (!status) {
status = GetLastError(); status = GetLastError();
goto out; eprintf("map_dacl_2_nfs4acl: GetAce failed with %d\n", status);
goto out_free;
} }
tmp_pointer = (PBYTE)ace; 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); dprintf(1, "ACE TYPE: %x\n", ace->AceType);
if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE) if (ace->AceType == ACCESS_ALLOWED_ACE_TYPE)
nfs4_acl->aces[i].acetype = ACE4_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_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); 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) if (status)
goto out_free; goto out_free;
} }
} }
status = 0; status = ERROR_SUCCESS;
out: out:
return status; return status;
out_free: out_free:
@ -645,8 +716,9 @@ static int handle_setacl(nfs41_upcall *upcall)
if (args->query & GROUP_SECURITY_INFORMATION) if (args->query & GROUP_SECURITY_INFORMATION)
dprintf(1, "handle_setacl: GROUP_SECURITY_INFORMATION\n"); dprintf(1, "handle_setacl: GROUP_SECURITY_INFORMATION\n");
if (args->query & DACL_SECURITY_INFORMATION) { if (args->query & DACL_SECURITY_INFORMATION) {
BOOL dacl_present, dacl_default; BOOL dacl_present, dacl_default, sid_default;
PACL acl; PACL acl;
PSID sid;
dprintf(1, "handle_setacl: DACL_SECURITY_INFORMATION\n"); dprintf(1, "handle_setacl: DACL_SECURITY_INFORMATION\n");
status = GetSecurityDescriptorDacl(args->sec_desc, &dacl_present, status = GetSecurityDescriptorDacl(args->sec_desc, &dacl_present,
&acl, &dacl_default); &acl, &dacl_default);
@ -655,7 +727,14 @@ static int handle_setacl(nfs41_upcall *upcall)
eprintf("GetSecurityDescriptorDacl failed with %d\n", status); eprintf("GetSecurityDescriptorDacl failed with %d\n", status);
goto out; 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) if (status)
goto out; goto out;
else { else {
@ -672,10 +751,8 @@ static int handle_setacl(nfs41_upcall *upcall)
nfs_error_string(status)); nfs_error_string(status));
status = nfs_to_windows_error(status, ERROR_NOT_SUPPORTED); status = nfs_to_windows_error(status, ERROR_NOT_SUPPORTED);
} }
if (args->query & DACL_SECURITY_INFORMATION) if (args->query & DACL_SECURITY_INFORMATION)
free(nfs4_acl.aces); free(nfs4_acl.aces);
out: out:
free(args->sec_desc); free(args->sec_desc);
return status; return status;

View file

@ -160,10 +160,6 @@ typedef struct __getacl_upcall_args {
nfs41_root *root; nfs41_root *root;
nfs41_open_state *state; nfs41_open_state *state;
SECURITY_INFORMATION query; SECURITY_INFORMATION query;
PSID osid;
DWORD osid_len;
PSID gsid;
DWORD gsid_len;
PSECURITY_DESCRIPTOR sec_desc; PSECURITY_DESCRIPTOR sec_desc;
DWORD sec_desc_len; DWORD sec_desc_len;
} getacl_upcall_args; } getacl_upcall_args;