1 /* NFSv4.1 client for Windows
2 * Copyright © 2012 The Regents of the University of Michigan
4 * Olga Kornievskaia <aglo@umich.edu>
5 * Casey Bodley <cbodley@umich.edu>
7 * This library is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as published by
9 * the Free Software Foundation; either version 2.1 of the License, or (at
10 * your option) any later version.
12 * This library is distributed in the hope that it will be useful, but
13 * without any warranty; without even the implied warranty of merchantability
14 * or fitness for a particular purpose. See the GNU Lesser General Public
15 * License for more details.
17 * You should have received a copy of the GNU Lesser General Public License
18 * along with this library; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA
26 #include "nfs41_ops.h"
27 #include "delegation.h"
28 #include "daemon_debug.h"
31 #include "nfs41_xdr.h"
34 #define ACLLVL 2 /* dprintf level for acl logging */
36 extern char localdomain_name
[NFS41_HOSTNAME_LEN
];
38 static int parse_getacl(unsigned char *buffer
, uint32_t length
,
42 getacl_upcall_args
*args
= &upcall
->args
.getacl
;
44 status
= safe_read(&buffer
, &length
, &args
->query
, sizeof(args
->query
));
47 dprintf(1, "parsing NFS41_ACL_QUERY: info_class=%d\n", args
->query
);
52 static int create_unknownsid(WELL_KNOWN_SID_TYPE type
, PSID
*sid
,
59 status
= CreateWellKnownSid(type
, NULL
, *sid
, sid_len
);
60 dprintf(ACLLVL
, "create_unknownsid: CreateWellKnownSid type %d returned %d "
61 "GetLastError %d sid len %d needed\n", type
, status
,
62 GetLastError(), *sid_len
);
64 return ERROR_INTERNAL_ERROR
;
65 status
= GetLastError();
66 if (status
!= ERROR_INSUFFICIENT_BUFFER
)
68 *sid
= malloc(*sid_len
);
70 return ERROR_INSUFFICIENT_BUFFER
;
71 status
= CreateWellKnownSid(type
, NULL
, *sid
, sid_len
);
75 status
= GetLastError();
76 eprintf("create_unknownsid: CreateWellKnownSid failed with %d\n", status
);
80 static void convert_nfs4name_2_user_domain(LPSTR nfs4name
,
84 for(; p
[0] != '\0'; p
++) {
93 static int map_name_2_sid(DWORD
*sid_len
, PSID
*sid
, LPCSTR name
)
95 int status
= ERROR_INTERNAL_ERROR
;
96 SID_NAME_USE sid_type
;
100 status
= LookupAccountName(NULL
, name
, NULL
, sid_len
, NULL
, &tmp
, &sid_type
);
101 dprintf(ACLLVL
, "map_name_2_sid: LookupAccountName for %s returned %d "
102 "GetLastError %d name len %d domain len %d\n", name
, status
,
103 GetLastError(), *sid_len
, tmp
);
105 return ERROR_INTERNAL_ERROR
;
107 status
= GetLastError();
109 case ERROR_INSUFFICIENT_BUFFER
:
110 *sid
= malloc(*sid_len
);
112 status
= GetLastError();
115 tmp_buf
= (LPSTR
) malloc(tmp
);
118 status
= LookupAccountName(NULL
, name
, *sid
, sid_len
, tmp_buf
,
122 eprintf("map_name_2_sid: LookupAccountName for %s failed "
123 "with %d\n", name
, GetLastError());
128 if (IsValidSid(*sid
))
129 if (ConvertSidToStringSidA(*sid
, &ssid
))
130 dprintf(1, "map_name_2_sid: sid_type = %d SID %s\n",
133 dprintf(1, "map_name_2_sid: ConvertSidToStringSidA failed "
134 "with %d\n", GetLastError());
136 dprintf(1, "map_name_2_sid: Invalid Sid ?\n");
137 if (ssid
) LocalFree(ssid
);
140 status
= ERROR_SUCCESS
;
142 case ERROR_NONE_MAPPED
:
143 status
= create_unknownsid(WinNullSid
, sid
, sid_len
);
150 status
= GetLastError();
155 static void free_sids(PSID
*sids
, int count
)
158 for(i
= 0; i
< count
; i
++)
163 static int check_4_special_identifiers(char *who
, PSID
*sid
, DWORD
*sid_len
,
166 int status
= ERROR_SUCCESS
;
167 WELL_KNOWN_SID_TYPE type
= 0;
169 if (!strncmp(who
, ACE4_OWNER
, strlen(ACE4_OWNER
)-1))
170 type
= WinCreatorOwnerSid
;
171 else if (!strncmp(who
, ACE4_GROUP
, strlen(ACE4_GROUP
)-1))
172 type
= WinCreatorGroupSid
;
173 else if (!strncmp(who
, ACE4_EVERYONE
, strlen(ACE4_EVERYONE
)-1))
175 else if (!strncmp(who
, ACE4_NOBODY
, strlen(ACE4_NOBODY
)))
180 status
= create_unknownsid(type
, sid
, sid_len
);
184 static int convert_nfs4acl_2_dacl(nfsacl41
*acl
, int file_type
,
185 PACL
*dacl_out
, PSID
**sids_out
)
187 int status
= ERROR_NOT_SUPPORTED
, size
= 0;
195 sids
= malloc(acl
->count
* sizeof(PSID
));
197 status
= GetLastError();
200 for (i
= 0; i
< acl
->count
; i
++) {
201 convert_nfs4name_2_user_domain(acl
->aces
[i
].who
, &domain
);
202 dprintf(ACLLVL
, "handle_getacl: for user=%s domain=%s\n",
203 acl
->aces
[i
].who
, domain
?domain
:"<null>");
204 status
= check_4_special_identifiers(acl
->aces
[i
].who
, &sids
[i
],
211 status
= map_name_2_sid(&sid_len
, &sids
[i
], acl
->aces
[i
].who
);
217 size
+= sid_len
- sizeof(DWORD
);
219 size
+= sizeof(ACL
) + (sizeof(ACCESS_ALLOWED_ACE
)*acl
->count
);
220 size
= (size
+ sizeof(DWORD
) - 1) & 0xfffffffc; //align size on word boundry
225 if (InitializeAcl(dacl
, size
, ACL_REVISION
)) {
227 for (i
= 0; i
< acl
->count
; i
++) {
228 // nfs4 acemask should be exactly the same as file access mask
229 mask
= acl
->aces
[i
].acemask
;
230 dprintf(ACLLVL
, "access mask %x ace type %s\n", mask
,
231 acl
->aces
[i
].acetype
?"DENIED ACE":"ALLOWED ACE");
232 if (acl
->aces
[i
].acetype
== ACE4_ACCESS_ALLOWED_ACE_TYPE
) {
233 status
= AddAccessAllowedAce(dacl
, ACL_REVISION
, mask
, sids
[i
]);
235 eprintf("convert_nfs4acl_2_dacl: AddAccessAllowedAce failed "
236 "with %d\n", status
);
239 else status
= ERROR_SUCCESS
;
240 } else if (acl
->aces
[i
].acetype
== ACE4_ACCESS_DENIED_ACE_TYPE
) {
241 status
= AddAccessDeniedAce(dacl
, ACL_REVISION
, mask
, sids
[i
]);
243 eprintf("convert_nfs4acl_2_dacl: AddAccessDeniedAce failed "
244 "with %d\n", status
);
247 else status
= ERROR_SUCCESS
;
249 eprintf("convert_nfs4acl_2_dacl: unknown acetype %d\n",
250 acl
->aces
[i
].acetype
);
251 status
= ERROR_INTERNAL_ERROR
;
253 free_sids(sids
, acl
->count
);
258 eprintf("convert_nfs4acl_2_dacl: InitializeAcl failed with %d\n", status
);
261 status
= ERROR_SUCCESS
;
269 free_sids(sids
, acl
->count
);
270 status
= GetLastError();
274 static int handle_getacl(nfs41_upcall
*upcall
)
276 int status
= ERROR_NOT_SUPPORTED
;
277 getacl_upcall_args
*args
= &upcall
->args
.getacl
;
278 nfs41_open_state
*state
= upcall
->state_ref
;
279 nfs41_file_info info
= { 0 };
280 bitmap4 attr_request
= { 0 };
282 SECURITY_DESCRIPTOR sec_desc
;
285 PSID osid
= NULL
, gsid
= NULL
;
287 char owner
[NFS4_OPAQUE_LIMIT
], group
[NFS4_OPAQUE_LIMIT
];
288 nfsacl41 acl
= { 0 };
290 // need to cache owner/group information XX
291 attr_request
.count
= 2;
292 attr_request
.arr
[1] = FATTR4_WORD1_OWNER
| FATTR4_WORD1_OWNER_GROUP
;
293 if (args
->query
& DACL_SECURITY_INFORMATION
) {
295 attr_request
.arr
[0] |= FATTR4_WORD0_ACL
;
298 info
.owner_group
= group
;
299 status
= nfs41_getattr(state
->session
, &state
->file
, &attr_request
, &info
);
301 eprintf("handle_getacl: nfs41_cached_getattr() failed with %d\n",
306 status
= InitializeSecurityDescriptor(&sec_desc
,
307 SECURITY_DESCRIPTOR_REVISION
);
309 status
= GetLastError();
310 eprintf("handle_getacl: InitializeSecurityDescriptor failed with %d\n",
314 /* can't (re)use the same sid variable for both owner and group sids
315 * because security descriptor is created in absolute-form and it just
316 * stores pointers to the sids. thus each owner and group needs its own
317 * memory. free them after creating self-relative security descriptor.
319 if (args
->query
& OWNER_SECURITY_INFORMATION
) {
320 // parse user@domain. currently ignoring domain part XX
321 convert_nfs4name_2_user_domain(info
.owner
, &domain
);
322 dprintf(ACLLVL
, "handle_getacl: OWNER_SECURITY_INFORMATION: for user=%s "
323 "domain=%s\n", info
.owner
, domain
?domain
:"<null>");
325 status
= map_name_2_sid(&sid_len
, &osid
, info
.owner
);
328 status
= SetSecurityDescriptorOwner(&sec_desc
, osid
, TRUE
);
330 status
= GetLastError();
331 eprintf("handle_getacl: SetSecurityDescriptorOwner failed with "
336 if (args
->query
& GROUP_SECURITY_INFORMATION
) {
337 convert_nfs4name_2_user_domain(info
.owner_group
, &domain
);
338 dprintf(ACLLVL
, "handle_getacl: GROUP_SECURITY_INFORMATION: for %s "
339 "domain=%s\n", info
.owner_group
, domain
?domain
:"<null>");
341 status
= map_name_2_sid(&sid_len
, &gsid
, info
.owner_group
);
344 status
= SetSecurityDescriptorGroup(&sec_desc
, gsid
, TRUE
);
346 status
= GetLastError();
347 eprintf("handle_getacl: SetSecurityDescriptorGroup failed with "
352 if (args
->query
& DACL_SECURITY_INFORMATION
) {
353 dprintf(ACLLVL
, "handle_getacl: DACL_SECURITY_INFORMATION\n");
354 status
= convert_nfs4acl_2_dacl(info
.acl
, state
->type
, &dacl
, &sids
);
357 status
= SetSecurityDescriptorDacl(&sec_desc
, TRUE
, dacl
, TRUE
);
359 status
= GetLastError();
360 eprintf("handle_getacl: SetSecurityDescriptorDacl failed with "
366 args
->sec_desc_len
= 0;
367 status
= MakeSelfRelativeSD(&sec_desc
, args
->sec_desc
, &args
->sec_desc_len
);
369 status
= ERROR_INTERNAL_ERROR
;
372 status
= GetLastError();
373 if (status
!= ERROR_INSUFFICIENT_BUFFER
) {
374 eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status
);
377 args
->sec_desc
= malloc(args
->sec_desc_len
);
378 if (args
->sec_desc
== NULL
) {
379 status
= GetLastError();
382 status
= MakeSelfRelativeSD(&sec_desc
, args
->sec_desc
, &args
->sec_desc_len
);
384 status
= GetLastError();
385 eprintf("handle_getacl: MakeSelfRelativeSD failes with %d\n", status
);
386 free(args
->sec_desc
);
388 } else status
= ERROR_SUCCESS
;
391 if (args
->query
& OWNER_SECURITY_INFORMATION
) {
392 if (osid
) free(osid
);
394 if (args
->query
& GROUP_SECURITY_INFORMATION
) {
395 if (gsid
) free(gsid
);
397 if (args
->query
& DACL_SECURITY_INFORMATION
) {
398 if (sids
) free_sids(sids
, info
.acl
->count
);
400 nfsacl41_free(info
.acl
);
405 static int marshall_getacl(unsigned char *buffer
, uint32_t *length
,
406 nfs41_upcall
*upcall
)
408 int status
= ERROR_NOT_SUPPORTED
;
409 getacl_upcall_args
*args
= &upcall
->args
.getacl
;
411 status
= safe_write(&buffer
, length
, &args
->sec_desc_len
, sizeof(DWORD
));
412 if (status
) goto out
;
413 status
= safe_write(&buffer
, length
, args
->sec_desc
, args
->sec_desc_len
);
414 free(args
->sec_desc
);
415 if (status
) goto out
;
420 const nfs41_upcall_op nfs41_op_getacl
= {
426 static int parse_setacl(unsigned char *buffer
, uint32_t length
,
427 nfs41_upcall
*upcall
)
430 setacl_upcall_args
*args
= &upcall
->args
.setacl
;
433 status
= safe_read(&buffer
, &length
, &args
->query
, sizeof(args
->query
));
434 if (status
) goto out
;
435 status
= safe_read(&buffer
, &length
, &sec_desc_len
, sizeof(ULONG
));
436 if (status
) goto out
;
437 args
->sec_desc
= (PSECURITY_DESCRIPTOR
)buffer
;
439 dprintf(1, "parsing NFS41_ACL_SET: info_class=%d sec_desc_len=%d\n",
440 args
->query
, sec_desc_len
);
445 static int is_well_known_sid(PSID sid
, char *who
)
448 for (i
= 0; i
< 78; i
++) {
449 status
= IsWellKnownSid(sid
, (WELL_KNOWN_SID_TYPE
)i
);
450 if (!status
) continue;
452 dprintf(ACLLVL
, "WELL_KNOWN_SID_TYPE %d\n", i
);
453 switch((WELL_KNOWN_SID_TYPE
)i
) {
454 case WinCreatorOwnerSid
:
455 memcpy(who
, ACE4_OWNER
, strlen(ACE4_OWNER
)+1);
458 memcpy(who
, ACE4_NOBODY
, strlen(ACE4_NOBODY
)+1);
460 case WinAnonymousSid
:
461 memcpy(who
, ACE4_ANONYMOUS
, strlen(ACE4_ANONYMOUS
)+1);
464 memcpy(who
, ACE4_EVERYONE
, strlen(ACE4_EVERYONE
)+1);
466 case WinCreatorGroupSid
:
467 case WinBuiltinUsersSid
:
468 memcpy(who
, ACE4_GROUP
, strlen(ACE4_GROUP
)+1);
470 case WinAuthenticatedUserSid
:
471 memcpy(who
, ACE4_AUTHENTICATED
, strlen(ACE4_AUTHENTICATED
)+1);
474 memcpy(who
, ACE4_DIALUP
, strlen(ACE4_DIALUP
)+1);
477 memcpy(who
, ACE4_NETWORK
, strlen(ACE4_NETWORK
)+1);
480 memcpy(who
, ACE4_BATCH
, strlen(ACE4_BATCH
)+1);
482 case WinInteractiveSid
:
483 memcpy(who
, ACE4_INTERACTIVE
, strlen(ACE4_INTERACTIVE
)+1);
485 case WinNetworkServiceSid
:
486 case WinLocalServiceSid
:
488 memcpy(who
, ACE4_SERVICE
, strlen(ACE4_SERVICE
)+1);
490 default: return FALSE
;
497 static void map_aceflags(BYTE win_aceflags
, uint32_t *nfs4_aceflags
)
499 if (win_aceflags
& OBJECT_INHERIT_ACE
)
500 *nfs4_aceflags
|= ACE4_FILE_INHERIT_ACE
;
501 if (win_aceflags
& CONTAINER_INHERIT_ACE
)
502 *nfs4_aceflags
|= ACE4_DIRECTORY_INHERIT_ACE
;
503 if (win_aceflags
& NO_PROPAGATE_INHERIT_ACE
)
504 *nfs4_aceflags
|= ACE4_NO_PROPAGATE_INHERIT_ACE
;
505 if (win_aceflags
& INHERIT_ONLY_ACE
)
506 *nfs4_aceflags
|= ACE4_INHERIT_ONLY_ACE
;
507 if (win_aceflags
& INHERITED_ACE
)
508 *nfs4_aceflags
|= ACE4_INHERITED_ACE
;
509 dprintf(ACLLVL
, "ACE FLAGS: %x nfs4 aceflags %x\n",
510 win_aceflags
, *nfs4_aceflags
);
513 static void map_acemask(ACCESS_MASK mask
, int file_type
, uint32_t *nfs4_mask
)
515 dprintf(ACLLVL
, "ACE MASK: %x\n", mask
);
516 print_windows_access_mask(0, mask
);
517 /* check if any GENERIC bits set */
518 if (mask
& 0xf000000) {
519 if (mask
& GENERIC_ALL
) {
520 if (file_type
== NF4DIR
)
521 *nfs4_mask
|= ACE4_ALL_DIR
;
523 *nfs4_mask
|= ACE4_ALL_FILE
;
525 if (mask
& GENERIC_READ
)
526 *nfs4_mask
|= ACE4_GENERIC_READ
;
527 if (mask
& GENERIC_WRITE
)
528 *nfs4_mask
|= ACE4_GENERIC_WRITE
;
529 if (mask
& GENERIC_EXECUTE
)
530 *nfs4_mask
|= ACE4_GENERIC_EXECUTE
;
533 else /* ignoring generic and reserved bits */
534 *nfs4_mask
= mask
& 0x00ffffff;
535 print_nfs_access_mask(0, *nfs4_mask
);
538 static int map_nfs4ace_who(PSID sid
, PSID owner_sid
, PSID group_sid
, char *who_out
, char *domain
)
540 int status
= ERROR_INTERNAL_ERROR
;
541 DWORD size
= 0, tmp_size
= 0;
542 SID_NAME_USE sid_type
;
543 LPSTR tmp_buf
= NULL
, who
= NULL
;
545 /* for ace mapping, we want to map owner's sid into "owner@"
546 * but for set_owner attribute we want to map owner into a user name
547 * same applies to group
551 if (EqualSid(sid
, owner_sid
)) {
552 dprintf(ACLLVL
, "map_nfs4ace_who: this is owner's sid\n");
553 memcpy(who_out
, ACE4_OWNER
, strlen(ACE4_OWNER
)+1);
554 return ERROR_SUCCESS
;
558 if (EqualSid(sid
, group_sid
)) {
559 dprintf(ACLLVL
, "map_nfs4ace_who: this is group's sid\n");
560 memcpy(who_out
, ACE4_GROUP
, strlen(ACE4_GROUP
)+1);
561 return ERROR_SUCCESS
;
564 status
= is_well_known_sid(sid
, who_out
);
566 if (!strncmp(who_out
, ACE4_NOBODY
, strlen(ACE4_NOBODY
))) {
567 size
= (DWORD
)strlen(ACE4_NOBODY
);
571 return ERROR_SUCCESS
;
574 status
= LookupAccountSid(NULL
, sid
, who
, &size
, tmp_buf
,
575 &tmp_size
, &sid_type
);
576 dprintf(ACLLVL
, "map_nfs4ace_who: LookupAccountSid returned %d GetLastError "
577 "%d name len %d domain len %d\n", status
, GetLastError(),
580 return ERROR_INTERNAL_ERROR
;
581 status
= GetLastError();
582 if (status
!= ERROR_INSUFFICIENT_BUFFER
)
583 return ERROR_INTERNAL_ERROR
;
586 status
= GetLastError();
589 tmp_buf
= malloc(tmp_size
);
592 status
= LookupAccountSid(NULL
, sid
, who
, &size
, tmp_buf
,
593 &tmp_size
, &sid_type
);
596 eprintf("map_nfs4ace_who: LookupAccountSid failed with %d\n",
600 memcpy(who_out
, who
, size
);
602 memcpy(who_out
+size
, "@", sizeof(char));
603 memcpy(who_out
+size
+1, domain
, strlen(domain
)+1);
604 dprintf(ACLLVL
, "map_nfs4ace_who: who=%s\n", who_out
);
606 status
= ERROR_SUCCESS
;
611 status
= GetLastError();
614 static int map_dacl_2_nfs4acl(PACL acl
, PSID sid
, PSID gsid
, nfsacl41
*nfs4_acl
,
615 int file_type
, char *domain
)
619 dprintf(ACLLVL
, "this is a NULL dacl: all access to an object\n");
621 nfs4_acl
->aces
= calloc(1, sizeof(nfsace4
));
622 if (nfs4_acl
->aces
== NULL
) {
623 status
= GetLastError();
627 memcpy(nfs4_acl
->aces
->who
, ACE4_EVERYONE
, strlen(ACE4_EVERYONE
)+1);
628 nfs4_acl
->aces
->acetype
= ACE4_ACCESS_ALLOWED_ACE_TYPE
;
629 if (file_type
== NF4DIR
)
630 nfs4_acl
->aces
->acemask
= ACE4_ALL_DIR
;
632 nfs4_acl
->aces
->acemask
= ACE4_ALL_FILE
;
633 nfs4_acl
->aces
->aceflag
= 0;
639 dprintf(ACLLVL
, "NON-NULL dacl with %d ACEs\n", acl
->AceCount
);
640 print_hexbuf_no_asci(3, (unsigned char *)"ACL\n",
641 (unsigned char *)acl
, acl
->AclSize
);
642 nfs4_acl
->count
= acl
->AceCount
;
643 nfs4_acl
->aces
= calloc(nfs4_acl
->count
, sizeof(nfsace4
));
644 if (nfs4_acl
->aces
== NULL
) {
645 status
= GetLastError();
649 for (i
= 0; i
< acl
->AceCount
; i
++) {
650 status
= GetAce(acl
, i
, &ace
);
652 status
= GetLastError();
653 eprintf("map_dacl_2_nfs4acl: GetAce failed with %d\n", status
);
656 tmp_pointer
= (PBYTE
)ace
;
657 print_hexbuf_no_asci(3, (unsigned char *)"ACE\n",
658 (unsigned char *)ace
, ace
->AceSize
);
659 dprintf(ACLLVL
, "ACE TYPE: %x\n", ace
->AceType
);
660 if (ace
->AceType
== ACCESS_ALLOWED_ACE_TYPE
)
661 nfs4_acl
->aces
[i
].acetype
= ACE4_ACCESS_ALLOWED_ACE_TYPE
;
662 else if (ace
->AceType
== ACCESS_DENIED_ACE_TYPE
)
663 nfs4_acl
->aces
[i
].acetype
= ACE4_ACCESS_DENIED_ACE_TYPE
;
665 eprintf("map_dacl_2_nfs4acl: unsupported ACE type %d\n",
667 status
= ERROR_NOT_SUPPORTED
;
671 map_aceflags(ace
->AceFlags
, &nfs4_acl
->aces
[i
].aceflag
);
672 map_acemask(*(PACCESS_MASK
)(ace
+ 1), file_type
,
673 &nfs4_acl
->aces
[i
].acemask
);
675 tmp_pointer
+= sizeof(ACCESS_MASK
) + sizeof(ACE_HEADER
);
676 status
= map_nfs4ace_who(tmp_pointer
, sid
, gsid
, nfs4_acl
->aces
[i
].who
,
682 status
= ERROR_SUCCESS
;
686 free(nfs4_acl
->aces
);
690 static int handle_setacl(nfs41_upcall
*upcall
)
692 int status
= ERROR_NOT_SUPPORTED
;
693 setacl_upcall_args
*args
= &upcall
->args
.setacl
;
694 nfs41_open_state
*state
= upcall
->state_ref
;
695 nfs41_file_info info
= { 0 };
697 nfsacl41 nfs4_acl
= { 0 };
698 PSID sid
= NULL
, gsid
= NULL
;
699 BOOL sid_default
, gsid_default
;
701 if (args
->query
& OWNER_SECURITY_INFORMATION
) {
702 char owner
[NFS4_OPAQUE_LIMIT
];
703 dprintf(ACLLVL
, "handle_setacl: OWNER_SECURITY_INFORMATION\n");
704 status
= GetSecurityDescriptorOwner(args
->sec_desc
, &sid
, &sid_default
);
706 status
= GetLastError();
707 eprintf("GetSecurityDescriptorOwner failed with %d\n", status
);
711 status
= map_nfs4ace_who(sid
, NULL
, NULL
, info
.owner
, localdomain_name
);
715 info
.attrmask
.arr
[1] |= FATTR4_WORD1_OWNER
;
716 info
.attrmask
.count
= 2;
719 if (args
->query
& GROUP_SECURITY_INFORMATION
) {
720 char group
[NFS4_OPAQUE_LIMIT
];
721 dprintf(ACLLVL
, "handle_setacl: GROUP_SECURITY_INFORMATION\n");
722 status
= GetSecurityDescriptorGroup(args
->sec_desc
, &sid
, &sid_default
);
724 status
= GetLastError();
725 eprintf("GetSecurityDescriptorOwner failed with %d\n", status
);
728 info
.owner_group
= group
;
729 status
= map_nfs4ace_who(sid
, NULL
, NULL
, info
.owner_group
,
734 info
.attrmask
.arr
[1] |= FATTR4_WORD1_OWNER_GROUP
;
735 info
.attrmask
.count
= 2;
738 if (args
->query
& DACL_SECURITY_INFORMATION
) {
739 BOOL dacl_present
, dacl_default
;
741 dprintf(ACLLVL
, "handle_setacl: DACL_SECURITY_INFORMATION\n");
742 status
= GetSecurityDescriptorDacl(args
->sec_desc
, &dacl_present
,
743 &acl
, &dacl_default
);
745 status
= GetLastError();
746 eprintf("GetSecurityDescriptorDacl failed with %d\n", status
);
749 status
= GetSecurityDescriptorOwner(args
->sec_desc
, &sid
, &sid_default
);
751 status
= GetLastError();
752 eprintf("GetSecurityDescriptorOwner failed with %d\n", status
);
755 status
= GetSecurityDescriptorGroup(args
->sec_desc
, &gsid
, &gsid_default
);
757 status
= GetLastError();
758 eprintf("GetSecurityDescriptorOwner failed with %d\n", status
);
761 status
= map_dacl_2_nfs4acl(acl
, sid
, gsid
, &nfs4_acl
, state
->type
,
766 info
.acl
= &nfs4_acl
;
767 info
.attrmask
.arr
[0] |= FATTR4_WORD0_ACL
;
768 if (!info
.attrmask
.count
)
769 info
.attrmask
.count
= 1;
773 /* break read delegations before SETATTR */
774 nfs41_delegation_return(state
->session
, &state
->file
,
775 OPEN_DELEGATE_WRITE
, FALSE
);
777 nfs41_open_stateid_arg(state
, &stateid
);
778 status
= nfs41_setattr(state
->session
, &state
->file
, &stateid
, &info
);
780 dprintf(ACLLVL
, "handle_setacl: nfs41_setattr() failed with error %s.\n",
781 nfs_error_string(status
));
782 status
= nfs_to_windows_error(status
, ERROR_NOT_SUPPORTED
);
784 args
->ctime
= info
.change
;
785 if (args
->query
& DACL_SECURITY_INFORMATION
)
791 static int marshall_setacl(unsigned char *buffer
, uint32_t *length
, nfs41_upcall
*upcall
)
793 setacl_upcall_args
*args
= &upcall
->args
.setacl
;
794 return safe_write(&buffer
, length
, &args
->ctime
, sizeof(args
->ctime
));
797 const nfs41_upcall_op nfs41_op_setacl
= {