auth3: Centralize auth_check_ntlm_password failure handling
[sfrench/samba-autobuild/.git] / source3 / modules / nfs4_acls.c
1 /*
2  * NFS4 ACL handling
3  *
4  * Copyright (C) Jim McDonough, 2006
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 3 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14  * GNU General Public License for more details.
15  *
16  * You should have received a copy of the GNU General Public License
17  * along with this program; if not, see <http://www.gnu.org/licenses/>.
18  */
19
20 #include "includes.h"
21 #include "smbd/smbd.h"
22 #include "nfs4_acls.h"
23 #include "librpc/gen_ndr/ndr_security.h"
24 #include "../libcli/security/dom_sid.h"
25 #include "../libcli/security/security.h"
26 #include "dbwrap/dbwrap.h"
27 #include "dbwrap/dbwrap_open.h"
28 #include "system/filesys.h"
29 #include "passdb/lookup_sid.h"
30 #include "util_tdb.h"
31 #include "lib/param/loadparm.h"
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_ACLS
35
36 #define SMBACL4_PARAM_TYPE_NAME "nfs4"
37
38 extern const struct generic_mapping file_generic_mapping;
39
40 struct SMB4ACE_T
41 {
42         SMB_ACE4PROP_T  prop;
43         struct SMB4ACE_T *next;
44 };
45
46 struct SMB4ACL_T
47 {
48         uint16_t controlflags;
49         uint32_t naces;
50         struct SMB4ACE_T        *first;
51         struct SMB4ACE_T        *last;
52 };
53
54 /*
55  * Gather special parameters for NFS4 ACL handling
56  */
57 int smbacl4_get_vfs_params(struct connection_struct *conn,
58                            struct smbacl4_vfs_params *params)
59 {
60         static const struct enum_list enum_smbacl4_modes[] = {
61                 { e_simple, "simple" },
62                 { e_special, "special" },
63                 { -1 , NULL }
64         };
65         static const struct enum_list enum_smbacl4_acedups[] = {
66                 { e_dontcare, "dontcare" },
67                 { e_reject, "reject" },
68                 { e_ignore, "ignore" },
69                 { e_merge, "merge" },
70                 { -1 , NULL }
71         };
72         int enumval;
73
74         ZERO_STRUCTP(params);
75
76         enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "mode",
77                                enum_smbacl4_modes, e_simple);
78         if (enumval == -1) {
79                 DEBUG(10, ("value for %s:mode unknown\n",
80                            SMBACL4_PARAM_TYPE_NAME));
81                 return -1;
82         }
83         params->mode = (enum smbacl4_mode_enum)enumval;
84
85         params->do_chown = lp_parm_bool(SNUM(conn), SMBACL4_PARAM_TYPE_NAME,
86                 "chown", true);
87
88         enumval = lp_parm_enum(SNUM(conn), SMBACL4_PARAM_TYPE_NAME, "acedup",
89                                enum_smbacl4_acedups, e_dontcare);
90         if (enumval == -1) {
91                 DEBUG(10, ("value for %s:acedup unknown\n",
92                            SMBACL4_PARAM_TYPE_NAME));
93                 return -1;
94         }
95         params->acedup = (enum smbacl4_acedup_enum)enumval;
96
97         params->map_full_control = lp_acl_map_full_control(SNUM(conn));
98
99         DEBUG(10, ("mode:%s, do_chown:%s, acedup: %s map full control:%s\n",
100                 enum_smbacl4_modes[params->mode].name,
101                 params->do_chown ? "true" : "false",
102                 enum_smbacl4_acedups[params->acedup].name,
103                 params->map_full_control ? "true" : "false"));
104
105         return 0;
106 }
107
108 /************************************************
109  Split the ACE flag mapping between nfs4 and Windows
110  into two separate functions rather than trying to do
111  it inline. Allows us to carefully control what flags
112  are mapped to what in one place.
113 ************************************************/
114
115 static uint32_t map_nfs4_ace_flags_to_windows_ace_flags(
116         uint32_t nfs4_ace_flags)
117 {
118         uint32_t win_ace_flags = 0;
119
120         /* The nfs4 flags <= 0xf map perfectly. */
121         win_ace_flags = nfs4_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
122                                       SEC_ACE_FLAG_CONTAINER_INHERIT|
123                                       SEC_ACE_FLAG_NO_PROPAGATE_INHERIT|
124                                       SEC_ACE_FLAG_INHERIT_ONLY);
125
126         /* flags greater than 0xf have diverged :-(. */
127         /* See the nfs4 ace flag definitions here:
128            http://www.ietf.org/rfc/rfc3530.txt.
129            And the Windows ace flag definitions here:
130            librpc/idl/security.idl. */
131         if (nfs4_ace_flags & SMB_ACE4_INHERITED_ACE) {
132                 win_ace_flags |= SEC_ACE_FLAG_INHERITED_ACE;
133         }
134
135         return win_ace_flags;
136 }
137
138 static uint32_t map_windows_ace_flags_to_nfs4_ace_flags(uint32_t win_ace_flags)
139 {
140         uint32_t nfs4_ace_flags = 0;
141
142         /* The windows flags <= 0xf map perfectly. */
143         nfs4_ace_flags = win_ace_flags & (SMB_ACE4_FILE_INHERIT_ACE|
144                                       SMB_ACE4_DIRECTORY_INHERIT_ACE|
145                                       SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
146                                       SMB_ACE4_INHERIT_ONLY_ACE);
147
148         /* flags greater than 0xf have diverged :-(. */
149         /* See the nfs4 ace flag definitions here:
150            http://www.ietf.org/rfc/rfc3530.txt.
151            And the Windows ace flag definitions here:
152            librpc/idl/security.idl. */
153         if (win_ace_flags & SEC_ACE_FLAG_INHERITED_ACE) {
154                 nfs4_ace_flags |= SMB_ACE4_INHERITED_ACE;
155         }
156
157         return nfs4_ace_flags;
158 }
159
160 struct SMB4ACL_T *smb_create_smb4acl(TALLOC_CTX *mem_ctx)
161 {
162         struct SMB4ACL_T *theacl;
163
164         theacl = talloc_zero(mem_ctx, struct SMB4ACL_T);
165         if (theacl==NULL)
166         {
167                 DEBUG(0, ("TALLOC_SIZE failed\n"));
168                 errno = ENOMEM;
169                 return NULL;
170         }
171         theacl->controlflags = SEC_DESC_SELF_RELATIVE;
172         /* theacl->first, last = NULL not needed */
173         return theacl;
174 }
175
176 struct SMB4ACE_T *smb_add_ace4(struct SMB4ACL_T *acl, SMB_ACE4PROP_T *prop)
177 {
178         struct SMB4ACE_T *ace;
179
180         ace = talloc_zero(acl, struct SMB4ACE_T);
181         if (ace==NULL)
182         {
183                 DEBUG(0, ("TALLOC_SIZE failed\n"));
184                 errno = ENOMEM;
185                 return NULL;
186         }
187         /* ace->next = NULL not needed */
188         memcpy(&ace->prop, prop, sizeof(SMB_ACE4PROP_T));
189
190         if (acl->first==NULL)
191         {
192                 acl->first = ace;
193                 acl->last = ace;
194         } else {
195                 acl->last->next = ace;
196                 acl->last = ace;
197         }
198         acl->naces++;
199
200         return ace;
201 }
202
203 SMB_ACE4PROP_T *smb_get_ace4(struct SMB4ACE_T *ace)
204 {
205         if (ace == NULL) {
206                 return NULL;
207         }
208
209         return &ace->prop;
210 }
211
212 struct SMB4ACE_T *smb_next_ace4(struct SMB4ACE_T *ace)
213 {
214         if (ace == NULL) {
215                 return NULL;
216         }
217
218         return ace->next;
219 }
220
221 struct SMB4ACE_T *smb_first_ace4(struct SMB4ACL_T *acl)
222 {
223         if (acl == NULL) {
224                 return NULL;
225         }
226
227         return acl->first;
228 }
229
230 uint32_t smb_get_naces(struct SMB4ACL_T *acl)
231 {
232         if (acl == NULL) {
233                 return 0;
234         }
235
236         return acl->naces;
237 }
238
239 uint16_t smbacl4_get_controlflags(struct SMB4ACL_T *acl)
240 {
241         if (acl == NULL) {
242                 return 0;
243         }
244
245         return acl->controlflags;
246 }
247
248 bool smbacl4_set_controlflags(struct SMB4ACL_T *acl, uint16_t controlflags)
249 {
250         if (acl == NULL) {
251                 return false;
252         }
253
254         acl->controlflags = controlflags;
255         return true;
256 }
257
258 static int smbacl4_GetFileOwner(struct connection_struct *conn,
259                                 const struct smb_filename *smb_fname,
260                                 SMB_STRUCT_STAT *psbuf)
261 {
262         ZERO_STRUCTP(psbuf);
263
264         /* Get the stat struct for the owner info. */
265         if (vfs_stat_smb_basename(conn, smb_fname, psbuf) != 0)
266         {
267                 DEBUG(8, ("vfs_stat_smb_basename failed with error %s\n",
268                         strerror(errno)));
269                 return -1;
270         }
271
272         return 0;
273 }
274
275 static int smbacl4_fGetFileOwner(files_struct *fsp, SMB_STRUCT_STAT *psbuf)
276 {
277         ZERO_STRUCTP(psbuf);
278
279         if (fsp->fh->fd == -1) {
280                 return smbacl4_GetFileOwner(fsp->conn,
281                                             fsp->fsp_name, psbuf);
282         }
283         if (SMB_VFS_FSTAT(fsp, psbuf) != 0)
284         {
285                 DEBUG(8, ("SMB_VFS_FSTAT failed with error %s\n",
286                         strerror(errno)));
287                 return -1;
288         }
289
290         return 0;
291 }
292
293 static bool smbacl4_nfs42win(TALLOC_CTX *mem_ctx,
294         const struct smbacl4_vfs_params *params,
295         struct SMB4ACL_T *acl, /* in */
296         struct dom_sid *psid_owner, /* in */
297         struct dom_sid *psid_group, /* in */
298         bool is_directory, /* in */
299         struct security_ace **ppnt_ace_list, /* out */
300         int *pgood_aces /* out */
301 )
302 {
303         struct SMB4ACE_T *aceint;
304         struct security_ace *nt_ace_list = NULL;
305         int good_aces = 0;
306
307         DEBUG(10, ("%s entered\n", __func__));
308
309         nt_ace_list = talloc_zero_array(mem_ctx, struct security_ace,
310                                         2 * acl->naces);
311         if (nt_ace_list==NULL)
312         {
313                 DEBUG(10, ("talloc error with %d aces", acl->naces));
314                 errno = ENOMEM;
315                 return false;
316         }
317
318         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
319                 uint32_t mask;
320                 struct dom_sid sid;
321                 SMB_ACE4PROP_T  *ace = &aceint->prop;
322                 uint32_t win_ace_flags;
323
324                 DEBUG(10, ("type: %d, iflags: %x, flags: %x, "
325                            "mask: %x, who: %d\n",
326                            ace->aceType, ace->flags,
327                            ace->aceFlags, ace->aceMask, ace->who.id));
328
329                 if (ace->flags & SMB_ACE4_ID_SPECIAL) {
330                         switch (ace->who.special_id) {
331                         case SMB_ACE4_WHO_OWNER:
332                                 sid_copy(&sid, psid_owner);
333                                 break;
334                         case SMB_ACE4_WHO_GROUP:
335                                 sid_copy(&sid, psid_group);
336                                 break;
337                         case SMB_ACE4_WHO_EVERYONE:
338                                 sid_copy(&sid, &global_sid_World);
339                                 break;
340                         default:
341                                 DEBUG(8, ("invalid special who id %d "
342                                         "ignored\n", ace->who.special_id));
343                                 continue;
344                         }
345                 } else {
346                         if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) {
347                                 gid_to_sid(&sid, ace->who.gid);
348                         } else {
349                                 uid_to_sid(&sid, ace->who.uid);
350                         }
351                 }
352                 DEBUG(10, ("mapped %d to %s\n", ace->who.id,
353                            sid_string_dbg(&sid)));
354
355                 if (is_directory && (ace->aceMask & SMB_ACE4_ADD_FILE)) {
356                         ace->aceMask |= SMB_ACE4_DELETE_CHILD;
357                 }
358
359                 if (!is_directory && params->map_full_control) {
360                         /*
361                          * Do we have all access except DELETE_CHILD
362                          * (not caring about the delete bit).
363                          */
364                         uint32_t test_mask = ((ace->aceMask|SMB_ACE4_DELETE|SMB_ACE4_DELETE_CHILD) &
365                                                 SMB_ACE4_ALL_MASKS);
366                         if (test_mask == SMB_ACE4_ALL_MASKS) {
367                                 ace->aceMask |= SMB_ACE4_DELETE_CHILD;
368                         }
369                 }
370
371                 win_ace_flags = map_nfs4_ace_flags_to_windows_ace_flags(
372                         ace->aceFlags);
373                 if (!is_directory &&
374                     (win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT|
375                                       SEC_ACE_FLAG_CONTAINER_INHERIT))) {
376                         /*
377                          * GPFS sets inherits dir_inhert and file_inherit flags
378                          * to files, too, which confuses windows, and seems to
379                          * be wrong anyways. ==> Map these bits away for files.
380                          */
381                         DEBUG(10, ("removing inherit flags from nfs4 ace\n"));
382                         win_ace_flags &= ~(SEC_ACE_FLAG_OBJECT_INHERIT|
383                                            SEC_ACE_FLAG_CONTAINER_INHERIT);
384                 }
385                 DEBUG(10, ("Windows mapped ace flags: 0x%x => 0x%x\n",
386                       ace->aceFlags, win_ace_flags));
387
388                 mask = ace->aceMask;
389                 /* Windows clients expect SYNC on acls to
390                    correctly allow rename. See bug #7909. */
391                 /* But not on DENY ace entries. See
392                    bug #8442. */
393                 if(ace->aceType == SMB_ACE4_ACCESS_ALLOWED_ACE_TYPE) {
394                         mask = ace->aceMask | SMB_ACE4_SYNCHRONIZE;
395                 }
396
397                 /* Mapping of owner@ and group@ to creator owner and
398                    creator group. Keep old behavior in mode special. */
399                 if (params->mode != e_special &&
400                     ace->flags & SMB_ACE4_ID_SPECIAL &&
401                     (ace->who.special_id == SMB_ACE4_WHO_OWNER ||
402                      ace->who.special_id == SMB_ACE4_WHO_GROUP)) {
403                         DEBUG(10, ("Map special entry\n"));
404                         if (!(win_ace_flags & SEC_ACE_FLAG_INHERIT_ONLY)) {
405                                 uint32_t win_ace_flags_current;
406                                 DEBUG(10, ("Map current sid\n"));
407                                 win_ace_flags_current = win_ace_flags &
408                                         ~(SEC_ACE_FLAG_OBJECT_INHERIT |
409                                           SEC_ACE_FLAG_CONTAINER_INHERIT);
410                                 init_sec_ace(&nt_ace_list[good_aces++], &sid,
411                                              ace->aceType, mask,
412                                              win_ace_flags_current);
413                         }
414                         if (ace->who.special_id == SMB_ACE4_WHO_OWNER &&
415                             win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
416                                              SEC_ACE_FLAG_CONTAINER_INHERIT)) {
417                                 uint32_t win_ace_flags_creator;
418                                 DEBUG(10, ("Map creator owner\n"));
419                                 win_ace_flags_creator = win_ace_flags |
420                                         SMB_ACE4_INHERIT_ONLY_ACE;
421                                 init_sec_ace(&nt_ace_list[good_aces++],
422                                              &global_sid_Creator_Owner,
423                                              ace->aceType, mask,
424                                              win_ace_flags_creator);
425                         }
426                         if (ace->who.special_id == SMB_ACE4_WHO_GROUP &&
427                             win_ace_flags & (SEC_ACE_FLAG_OBJECT_INHERIT |
428                                              SEC_ACE_FLAG_CONTAINER_INHERIT)) {
429                                 uint32_t win_ace_flags_creator;
430                                 DEBUG(10, ("Map creator owner group\n"));
431                                 win_ace_flags_creator = win_ace_flags |
432                                         SMB_ACE4_INHERIT_ONLY_ACE;
433                                 init_sec_ace(&nt_ace_list[good_aces++],
434                                              &global_sid_Creator_Group,
435                                              ace->aceType, mask,
436                                              win_ace_flags_creator);
437                         }
438                 } else {
439                         DEBUG(10, ("Map normal sid\n"));
440                         init_sec_ace(&nt_ace_list[good_aces++], &sid,
441                                      ace->aceType, mask,
442                                      win_ace_flags);
443                 }
444         }
445
446         nt_ace_list = talloc_realloc(mem_ctx, nt_ace_list, struct security_ace,
447                                      good_aces);
448
449         /* returns a NULL ace list when good_aces is zero. */
450         if (good_aces && nt_ace_list == NULL) {
451                 DEBUG(10, ("realloc error with %d aces", good_aces));
452                 errno = ENOMEM;
453                 return false;
454         }
455
456         *ppnt_ace_list = nt_ace_list;
457         *pgood_aces = good_aces;
458
459         return true;
460 }
461
462 static NTSTATUS smb_get_nt_acl_nfs4_common(const SMB_STRUCT_STAT *sbuf,
463                                            const struct smbacl4_vfs_params *params,
464                                            uint32_t security_info,
465                                            TALLOC_CTX *mem_ctx,
466                                            struct security_descriptor **ppdesc,
467                                            struct SMB4ACL_T *theacl)
468 {
469         int good_aces = 0;
470         struct dom_sid sid_owner, sid_group;
471         size_t sd_size = 0;
472         struct security_ace *nt_ace_list = NULL;
473         struct security_acl *psa = NULL;
474         TALLOC_CTX *frame = talloc_stackframe();
475         bool ok;
476
477         if (theacl==NULL) {
478                 TALLOC_FREE(frame);
479                 return NT_STATUS_ACCESS_DENIED; /* special because we
480                                                  * need to think through
481                                                  * the null case.*/
482         }
483
484         uid_to_sid(&sid_owner, sbuf->st_ex_uid);
485         gid_to_sid(&sid_group, sbuf->st_ex_gid);
486
487         ok = smbacl4_nfs42win(frame, params, theacl, &sid_owner, &sid_group,
488                               S_ISDIR(sbuf->st_ex_mode),
489                               &nt_ace_list, &good_aces);
490         if (!ok) {
491                 DEBUG(8,("smbacl4_nfs42win failed\n"));
492                 TALLOC_FREE(frame);
493                 return map_nt_error_from_unix(errno);
494         }
495
496         psa = make_sec_acl(frame, NT4_ACL_REVISION, good_aces, nt_ace_list);
497         if (psa == NULL) {
498                 DEBUG(2,("make_sec_acl failed\n"));
499                 TALLOC_FREE(frame);
500                 return NT_STATUS_NO_MEMORY;
501         }
502
503         DEBUG(10,("after make sec_acl\n"));
504         *ppdesc = make_sec_desc(
505                 mem_ctx, SD_REVISION, smbacl4_get_controlflags(theacl),
506                 (security_info & SECINFO_OWNER) ? &sid_owner : NULL,
507                 (security_info & SECINFO_GROUP) ? &sid_group : NULL,
508                 NULL, psa, &sd_size);
509         if (*ppdesc==NULL) {
510                 DEBUG(2,("make_sec_desc failed\n"));
511                 TALLOC_FREE(frame);
512                 return NT_STATUS_NO_MEMORY;
513         }
514
515         DEBUG(10, ("smb_get_nt_acl_nfs4_common successfully exited with "
516                    "sd_size %d\n",
517                    (int)ndr_size_security_descriptor(*ppdesc, 0)));
518
519         TALLOC_FREE(frame);
520         return NT_STATUS_OK;
521 }
522
523 NTSTATUS smb_fget_nt_acl_nfs4(files_struct *fsp,
524                               const struct smbacl4_vfs_params *pparams,
525                               uint32_t security_info,
526                               TALLOC_CTX *mem_ctx,
527                               struct security_descriptor **ppdesc,
528                               struct SMB4ACL_T *theacl)
529 {
530         SMB_STRUCT_STAT sbuf;
531         struct smbacl4_vfs_params params;
532         SMB_STRUCT_STAT *psbuf = NULL;
533
534         DEBUG(10, ("smb_fget_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
535
536         if (VALID_STAT(fsp->fsp_name->st)) {
537                 psbuf = &fsp->fsp_name->st;
538         }
539
540         if (psbuf == NULL) {
541                 if (smbacl4_fGetFileOwner(fsp, &sbuf)) {
542                         return map_nt_error_from_unix(errno);
543                 }
544                 psbuf = &sbuf;
545         }
546
547         if (pparams == NULL) {
548                 /* Special behaviours */
549                 if (smbacl4_get_vfs_params(fsp->conn, &params)) {
550                         return NT_STATUS_NO_MEMORY;
551                 }
552                 pparams = &params;
553         }
554
555         return smb_get_nt_acl_nfs4_common(psbuf, pparams, security_info,
556                                           mem_ctx, ppdesc, theacl);
557 }
558
559 NTSTATUS smb_get_nt_acl_nfs4(struct connection_struct *conn,
560                              const struct smb_filename *smb_fname,
561                              const struct smbacl4_vfs_params *pparams,
562                              uint32_t security_info,
563                              TALLOC_CTX *mem_ctx,
564                              struct security_descriptor **ppdesc,
565                              struct SMB4ACL_T *theacl)
566 {
567         SMB_STRUCT_STAT sbuf;
568         struct smbacl4_vfs_params params;
569         const SMB_STRUCT_STAT *psbuf = NULL;
570
571         DEBUG(10, ("smb_get_nt_acl_nfs4 invoked for %s\n",
572                 smb_fname->base_name));
573
574         if (VALID_STAT(smb_fname->st)) {
575                 psbuf = &smb_fname->st;
576         }
577
578         if (psbuf == NULL) {
579                 if (smbacl4_GetFileOwner(conn, smb_fname, &sbuf)) {
580                         return map_nt_error_from_unix(errno);
581                 }
582                 psbuf = &sbuf;
583         }
584
585         if (pparams == NULL) {
586                 /* Special behaviours */
587                 if (smbacl4_get_vfs_params(conn, &params)) {
588                         return NT_STATUS_NO_MEMORY;
589                 }
590                 pparams = &params;
591         }
592
593         return smb_get_nt_acl_nfs4_common(psbuf, pparams, security_info,
594                                           mem_ctx, ppdesc, theacl);
595 }
596
597 static void smbacl4_dump_nfs4acl(int level, struct SMB4ACL_T *acl)
598 {
599         struct SMB4ACE_T *aceint;
600
601         DEBUG(level, ("NFS4ACL: size=%d\n", acl->naces));
602
603         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
604                 SMB_ACE4PROP_T *ace = &aceint->prop;
605
606                 DEBUG(level, ("\tACE: type=%d, flags=0x%x, fflags=0x%x, "
607                               "mask=0x%x, id=%d\n",
608                               ace->aceType,
609                               ace->aceFlags, ace->flags,
610                               ace->aceMask,
611                               ace->who.id));
612         }
613 }
614
615 /*
616  * Find 2 NFS4 who-special ACE property (non-copy!!!)
617  * match nonzero if "special" and who is equal
618  * return ace if found matching; otherwise NULL
619  */
620 static SMB_ACE4PROP_T *smbacl4_find_equal_special(
621         struct SMB4ACL_T *acl,
622         SMB_ACE4PROP_T *aceNew)
623 {
624         struct SMB4ACE_T *aceint;
625
626         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
627                 SMB_ACE4PROP_T *ace = &aceint->prop;
628
629                 DEBUG(10,("ace type:0x%x flags:0x%x aceFlags:0x%x "
630                           "new type:0x%x flags:0x%x aceFlags:0x%x\n",
631                           ace->aceType, ace->flags, ace->aceFlags,
632                           aceNew->aceType, aceNew->flags,aceNew->aceFlags));
633
634                 if (ace->flags == aceNew->flags &&
635                         ace->aceType==aceNew->aceType &&
636                         ace->aceFlags==aceNew->aceFlags)
637                 {
638                         /* keep type safety; e.g. gid is an u.short */
639                         if (ace->flags & SMB_ACE4_ID_SPECIAL)
640                         {
641                                 if (ace->who.special_id ==
642                                     aceNew->who.special_id)
643                                         return ace;
644                         } else {
645                                 if (ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP)
646                                 {
647                                         if (ace->who.gid==aceNew->who.gid)
648                                                 return ace;
649                                 } else {
650                                         if (ace->who.uid==aceNew->who.uid)
651                                                 return ace;
652                                 }
653                         }
654                 }
655         }
656
657         return NULL;
658 }
659
660
661 static bool smbacl4_fill_ace4(
662         const struct smb_filename *filename,
663         const struct smbacl4_vfs_params *params,
664         uid_t ownerUID,
665         gid_t ownerGID,
666         const struct security_ace *ace_nt, /* input */
667         SMB_ACE4PROP_T *ace_v4 /* output */
668 )
669 {
670         DEBUG(10, ("got ace for %s\n", sid_string_dbg(&ace_nt->trustee)));
671
672         ZERO_STRUCTP(ace_v4);
673
674         /* only ACCESS|DENY supported right now */
675         ace_v4->aceType = ace_nt->type;
676
677         ace_v4->aceFlags = map_windows_ace_flags_to_nfs4_ace_flags(
678                 ace_nt->flags);
679
680         /* remove inheritance flags on files */
681         if (VALID_STAT(filename->st) &&
682             !S_ISDIR(filename->st.st_ex_mode)) {
683                 DEBUG(10, ("Removing inheritance flags from a file\n"));
684                 ace_v4->aceFlags &= ~(SMB_ACE4_FILE_INHERIT_ACE|
685                                       SMB_ACE4_DIRECTORY_INHERIT_ACE|
686                                       SMB_ACE4_NO_PROPAGATE_INHERIT_ACE|
687                                       SMB_ACE4_INHERIT_ONLY_ACE);
688         }
689
690         ace_v4->aceMask = ace_nt->access_mask &
691                 (SEC_STD_ALL | SEC_FILE_ALL);
692
693         se_map_generic(&ace_v4->aceMask, &file_generic_mapping);
694
695         if (ace_v4->aceFlags!=ace_nt->flags)
696                 DEBUG(9, ("ace_v4->aceFlags(0x%x)!=ace_nt->flags(0x%x)\n",
697                         ace_v4->aceFlags, ace_nt->flags));
698
699         if (ace_v4->aceMask!=ace_nt->access_mask)
700                 DEBUG(9, ("ace_v4->aceMask(0x%x)!=ace_nt->access_mask(0x%x)\n",
701                         ace_v4->aceMask, ace_nt->access_mask));
702
703         if (dom_sid_equal(&ace_nt->trustee, &global_sid_World)) {
704                 ace_v4->who.special_id = SMB_ACE4_WHO_EVERYONE;
705                 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
706         } else if (params->mode!=e_special &&
707                    dom_sid_equal(&ace_nt->trustee,
708                                  &global_sid_Creator_Owner)) {
709                 DEBUG(10, ("Map creator owner\n"));
710                 ace_v4->who.special_id = SMB_ACE4_WHO_OWNER;
711                 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
712                 /* A non inheriting creator owner entry has no effect. */
713                 ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
714                 if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
715                     && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
716                         return false;
717                 }
718         } else if (params->mode!=e_special &&
719                    dom_sid_equal(&ace_nt->trustee,
720                                  &global_sid_Creator_Group)) {
721                 DEBUG(10, ("Map creator owner group\n"));
722                 ace_v4->who.special_id = SMB_ACE4_WHO_GROUP;
723                 ace_v4->flags |= SMB_ACE4_ID_SPECIAL;
724                 /* A non inheriting creator group entry has no effect. */
725                 ace_v4->aceFlags |= SMB_ACE4_INHERIT_ONLY_ACE;
726                 if (!(ace_v4->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)
727                     && !(ace_v4->aceFlags & SMB_ACE4_FILE_INHERIT_ACE)) {
728                         return false;
729                 }
730         } else {
731                 uid_t uid;
732                 gid_t gid;
733
734                 /*
735                  * ID_TYPE_BOTH returns both uid and gid. Explicitly
736                  * check for ownerUID to allow the mapping of the
737                  * owner to a special entry in this idmap config.
738                  */
739                 if (sid_to_uid(&ace_nt->trustee, &uid) && uid == ownerUID) {
740                         ace_v4->who.uid = uid;
741                 } else if (sid_to_gid(&ace_nt->trustee, &gid)) {
742                         ace_v4->aceFlags |= SMB_ACE4_IDENTIFIER_GROUP;
743                         ace_v4->who.gid = gid;
744                 } else if (sid_to_uid(&ace_nt->trustee, &uid)) {
745                         ace_v4->who.uid = uid;
746                 } else if (dom_sid_compare_domain(&ace_nt->trustee,
747                                                   &global_sid_Unix_NFS) == 0) {
748                         return false;
749                 } else {
750                         DEBUG(1, ("nfs4_acls.c: file [%s]: could not "
751                                   "convert %s to uid or gid\n",
752                                   filename->base_name,
753                                   sid_string_dbg(&ace_nt->trustee)));
754                         return false;
755                 }
756         }
757
758         return true; /* OK */
759 }
760
761 static int smbacl4_MergeIgnoreReject(
762         enum smbacl4_acedup_enum acedup,
763         struct SMB4ACL_T *theacl, /* may modify it */
764         SMB_ACE4PROP_T *ace, /* the "new" ACE */
765         bool    *paddNewACE,
766         int     i
767 )
768 {
769         int     result = 0;
770         SMB_ACE4PROP_T *ace4found = smbacl4_find_equal_special(theacl, ace);
771         if (ace4found)
772         {
773                 switch(acedup)
774                 {
775                 case e_merge: /* "merge" flags */
776                         *paddNewACE = false;
777                         ace4found->aceFlags |= ace->aceFlags;
778                         ace4found->aceMask |= ace->aceMask;
779                         break;
780                 case e_ignore: /* leave out this record */
781                         *paddNewACE = false;
782                         break;
783                 case e_reject: /* do an error */
784                         DEBUG(8, ("ACL rejected by duplicate nt ace#%d\n", i));
785                         errno = EINVAL; /* SHOULD be set on any _real_ error */
786                         result = -1;
787                         break;
788                 default:
789                         break;
790                 }
791         }
792         return result;
793 }
794
795 static int smbacl4_substitute_special(
796         struct SMB4ACL_T *acl,
797         uid_t ownerUID,
798         gid_t ownerGID
799 )
800 {
801         struct SMB4ACE_T *aceint;
802
803         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
804                 SMB_ACE4PROP_T *ace = &aceint->prop;
805
806                 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
807                           "mask: %x, who: %d\n",
808                           ace->aceType, ace->flags, ace->aceFlags,
809                           ace->aceMask, ace->who.id));
810
811                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
812                     !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
813                     ace->who.uid == ownerUID) {
814                         ace->flags |= SMB_ACE4_ID_SPECIAL;
815                         ace->who.special_id = SMB_ACE4_WHO_OWNER;
816                         DEBUG(10,("replaced with special owner ace\n"));
817                 }
818
819                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
820                     ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
821                     ace->who.uid == ownerGID) {
822                         ace->flags |= SMB_ACE4_ID_SPECIAL;
823                         ace->who.special_id = SMB_ACE4_WHO_GROUP;
824                         DEBUG(10,("replaced with special group ace\n"));
825                 }
826         }
827         return true; /* OK */
828 }
829
830 static int smbacl4_substitute_simple(
831         struct SMB4ACL_T *acl,
832         uid_t ownerUID,
833         gid_t ownerGID
834 )
835 {
836         struct SMB4ACE_T *aceint;
837
838         for (aceint = acl->first; aceint != NULL; aceint = aceint->next) {
839                 SMB_ACE4PROP_T *ace = &aceint->prop;
840
841                 DEBUG(10,("ace type: %d, iflags: %x, flags: %x, "
842                           "mask: %x, who: %d\n",
843                           ace->aceType, ace->flags, ace->aceFlags,
844                           ace->aceMask, ace->who.id));
845
846                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
847                     !(ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP) &&
848                     ace->who.uid == ownerUID &&
849                     !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) &&
850                     !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) &&
851                     !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) {
852                         ace->flags |= SMB_ACE4_ID_SPECIAL;
853                         ace->who.special_id = SMB_ACE4_WHO_OWNER;
854                         DEBUG(10,("replaced with special owner ace\n"));
855                 }
856
857                 if (!(ace->flags & SMB_ACE4_ID_SPECIAL) &&
858                     ace->aceFlags & SMB_ACE4_IDENTIFIER_GROUP &&
859                     ace->who.uid == ownerGID &&
860                     !(ace->aceFlags & SMB_ACE4_INHERIT_ONLY_ACE) &&
861                     !(ace->aceFlags & SMB_ACE4_FILE_INHERIT_ACE) &&
862                     !(ace->aceFlags & SMB_ACE4_DIRECTORY_INHERIT_ACE)) {
863                         ace->flags |= SMB_ACE4_ID_SPECIAL;
864                         ace->who.special_id = SMB_ACE4_WHO_GROUP;
865                         DEBUG(10,("replaced with special group ace\n"));
866                 }
867         }
868         return true; /* OK */
869 }
870
871 static struct SMB4ACL_T *smbacl4_win2nfs4(
872         TALLOC_CTX *mem_ctx,
873         const files_struct *fsp,
874         const struct security_acl *dacl,
875         const struct smbacl4_vfs_params *pparams,
876         uid_t ownerUID,
877         gid_t ownerGID
878 )
879 {
880         struct SMB4ACL_T *theacl;
881         uint32_t i;
882         const char *filename = fsp->fsp_name->base_name;
883
884         DEBUG(10, ("smbacl4_win2nfs4 invoked\n"));
885
886         theacl = smb_create_smb4acl(mem_ctx);
887         if (theacl==NULL)
888                 return NULL;
889
890         for(i=0; i<dacl->num_aces; i++) {
891                 SMB_ACE4PROP_T  ace_v4;
892                 bool    addNewACE = true;
893
894                 if (!smbacl4_fill_ace4(fsp->fsp_name, pparams,
895                                        ownerUID, ownerGID,
896                                        dacl->aces + i, &ace_v4)) {
897                         DEBUG(3, ("Could not fill ace for file %s, SID %s\n",
898                                   filename,
899                                   sid_string_dbg(&((dacl->aces+i)->trustee))));
900                         continue;
901                 }
902
903                 if (pparams->acedup!=e_dontcare) {
904                         if (smbacl4_MergeIgnoreReject(pparams->acedup, theacl,
905                                 &ace_v4, &addNewACE, i))
906                                 return NULL;
907                 }
908
909                 if (addNewACE)
910                         smb_add_ace4(theacl, &ace_v4);
911         }
912
913         if (pparams->mode==e_simple) {
914                 smbacl4_substitute_simple(theacl, ownerUID, ownerGID);
915         }
916
917         if (pparams->mode==e_special) {
918                 smbacl4_substitute_special(theacl, ownerUID, ownerGID);
919         }
920
921         return theacl;
922 }
923
924 NTSTATUS smb_set_nt_acl_nfs4(vfs_handle_struct *handle, files_struct *fsp,
925         const struct smbacl4_vfs_params *pparams,
926         uint32_t security_info_sent,
927         const struct security_descriptor *psd,
928         set_nfs4acl_native_fn_t set_nfs4_native)
929 {
930         struct smbacl4_vfs_params params;
931         struct SMB4ACL_T *theacl = NULL;
932         bool    result;
933
934         SMB_STRUCT_STAT sbuf;
935         bool set_acl_as_root = false;
936         uid_t newUID = (uid_t)-1;
937         gid_t newGID = (gid_t)-1;
938         int saved_errno;
939         TALLOC_CTX *frame = talloc_stackframe();
940
941         DEBUG(10, ("smb_set_nt_acl_nfs4 invoked for %s\n", fsp_str_dbg(fsp)));
942
943         if ((security_info_sent & (SECINFO_DACL |
944                 SECINFO_GROUP | SECINFO_OWNER)) == 0)
945         {
946                 DEBUG(9, ("security_info_sent (0x%x) ignored\n",
947                         security_info_sent));
948                 TALLOC_FREE(frame);
949                 return NT_STATUS_OK; /* won't show error - later to be
950                                       * refined... */
951         }
952
953         if (pparams == NULL) {
954                 /* Special behaviours */
955                 if (smbacl4_get_vfs_params(fsp->conn, &params)) {
956                         TALLOC_FREE(frame);
957                         return NT_STATUS_NO_MEMORY;
958                 }
959                 pparams = &params;
960         }
961
962         if (smbacl4_fGetFileOwner(fsp, &sbuf)) {
963                 TALLOC_FREE(frame);
964                 return map_nt_error_from_unix(errno);
965         }
966
967         if (pparams->do_chown) {
968                 /* chown logic is a copy/paste from posix_acl.c:set_nt_acl */
969                 NTSTATUS status = unpack_nt_owners(fsp->conn, &newUID, &newGID,
970                                                    security_info_sent, psd);
971                 if (!NT_STATUS_IS_OK(status)) {
972                         DEBUG(8, ("unpack_nt_owners failed"));
973                         TALLOC_FREE(frame);
974                         return status;
975                 }
976                 if (((newUID != (uid_t)-1) && (sbuf.st_ex_uid != newUID)) ||
977                     ((newGID != (gid_t)-1) && (sbuf.st_ex_gid != newGID))) {
978
979                         status = try_chown(fsp, newUID, newGID);
980                         if (!NT_STATUS_IS_OK(status)) {
981                                 DEBUG(3,("chown %s, %u, %u failed. Error = "
982                                          "%s.\n", fsp_str_dbg(fsp),
983                                          (unsigned int)newUID,
984                                          (unsigned int)newGID,
985                                          nt_errstr(status)));
986                                 TALLOC_FREE(frame);
987                                 return status;
988                         }
989
990                         DEBUG(10,("chown %s, %u, %u succeeded.\n",
991                                   fsp_str_dbg(fsp), (unsigned int)newUID,
992                                   (unsigned int)newGID));
993                         if (smbacl4_GetFileOwner(fsp->conn,
994                                                  fsp->fsp_name,
995                                                  &sbuf)){
996                                 TALLOC_FREE(frame);
997                                 return map_nt_error_from_unix(errno);
998                         }
999
1000                         /* If we successfully chowned, we know we must
1001                          * be able to set the acl, so do it as root.
1002                          */
1003                         set_acl_as_root = true;
1004                 }
1005         }
1006
1007         if (!(security_info_sent & SECINFO_DACL) || psd->dacl ==NULL) {
1008                 DEBUG(10, ("no dacl found; security_info_sent = 0x%x\n",
1009                            security_info_sent));
1010                 TALLOC_FREE(frame);
1011                 return NT_STATUS_OK;
1012         }
1013
1014         theacl = smbacl4_win2nfs4(frame, fsp, psd->dacl, pparams,
1015                                   sbuf.st_ex_uid, sbuf.st_ex_gid);
1016         if (!theacl) {
1017                 TALLOC_FREE(frame);
1018                 return map_nt_error_from_unix(errno);
1019         }
1020
1021         smbacl4_set_controlflags(theacl, psd->type);
1022         smbacl4_dump_nfs4acl(10, theacl);
1023
1024         if (set_acl_as_root) {
1025                 become_root();
1026         }
1027         result = set_nfs4_native(handle, fsp, theacl);
1028         saved_errno = errno;
1029         if (set_acl_as_root) {
1030                 unbecome_root();
1031         }
1032
1033         TALLOC_FREE(frame);
1034
1035         if (result!=true) {
1036                 errno = saved_errno;
1037                 DEBUG(10, ("set_nfs4_native failed with %s\n",
1038                            strerror(errno)));
1039                 return map_nt_error_from_unix(errno);
1040         }
1041
1042         DEBUG(10, ("smb_set_nt_acl_nfs4 succeeded\n"));
1043         return NT_STATUS_OK;
1044 }