s3:libsmb: allow store_cldap_reply() to work with a ipv6 response
[samba.git] / source3 / modules / vfs_solarisacl.c
1 /*
2    Unix SMB/Netbios implementation.
3    VFS module to get and set Solaris ACLs
4    Copyright (C) Michael Adam 2006,2008
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
21 #include "includes.h"
22 #include "system/filesys.h"
23 #include "smbd/smbd.h"
24 #include "modules/vfs_solarisacl.h"
25
26 /* typedef struct acl SOLARIS_ACE_T; */
27 typedef aclent_t SOLARIS_ACE_T;
28 typedef aclent_t *SOLARIS_ACL_T;
29 typedef int SOLARIS_ACL_TAG_T;   /* the type of an ACL entry */
30 typedef o_mode_t SOLARIS_PERM_T;
31
32 /* for convenience: check if solaris acl entry is a default entry?  */
33 #define _IS_DEFAULT(ace) ((ace).a_type & ACL_DEFAULT)
34 #define _IS_OF_TYPE(ace, type) ( \
35         (((type) == SMB_ACL_TYPE_ACCESS) && !_IS_DEFAULT(ace)) \
36         || \
37         (((type) == SMB_ACL_TYPE_DEFAULT) && _IS_DEFAULT(ace)) \
38 )
39
40
41 /* prototypes for private functions */
42
43 static SOLARIS_ACL_T solaris_acl_init(int count);
44 static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
45                 SOLARIS_ACL_T *solariacl, int *count, 
46                 SMB_ACL_TYPE_T type);
47 static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solarisacl, int count,
48                                         SMB_ACL_TYPE_T type, TALLOC_CTX *mem_ctx);
49 static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag);
50 static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag);
51 static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
52                 SOLARIS_ACL_T add_acl, int add_count, SMB_ACL_TYPE_T type);
53 static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solarisacl, 
54                 int *count);
55 static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solarisacl, int *count);
56 static bool solaris_acl_sort(SOLARIS_ACL_T theacl, int count);
57 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm);
58 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm);
59 #if 0
60 static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count);
61 #endif
62
63 /* public functions - the api */
64
65 static SMB_ACL_T solarisacl_sys_acl_get_file(vfs_handle_struct *handle,
66                                 const struct smb_filename *smb_fname,
67                                 SMB_ACL_TYPE_T type,
68                                 TALLOC_CTX *mem_ctx)
69 {
70         SMB_ACL_T result = NULL;
71         int count;
72         SOLARIS_ACL_T solaris_acl = NULL;
73         const char *path_p = smb_fname->base_name;
74         
75         DEBUG(10, ("solarisacl_sys_acl_get_file called for file '%s'.\n", 
76                    path_p));
77
78         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
79                 DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type));
80                 errno = EINVAL;
81                 goto done;
82         }
83
84         DEBUGADD(10, ("getting %s acl\n", 
85                       ((type == SMB_ACL_TYPE_ACCESS) ? "access" : "default")));
86
87         if (!solaris_acl_get_file(path_p, &solaris_acl, &count)) {
88                 goto done;
89         }
90         result = solaris_acl_to_smb_acl(solaris_acl, count, type, mem_ctx);
91         if (result == NULL) {
92                 DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
93                            strerror(errno)));
94         }
95         
96  done:
97         DEBUG(10, ("solarisacl_sys_acl_get_file %s.\n",
98                    ((result == NULL) ? "failed" : "succeeded" )));
99         SAFE_FREE(solaris_acl);
100         return result;
101 }
102
103
104 /*
105  * get the access ACL of a file referred to by a fd
106  */
107 SMB_ACL_T solarisacl_sys_acl_get_fd(vfs_handle_struct *handle,
108                                     files_struct *fsp,
109                                     SMB_ACL_TYPE_T type,
110                                     TALLOC_CTX *mem_ctx)
111 {
112         SMB_ACL_T result = NULL;
113         int count;
114         SOLARIS_ACL_T solaris_acl = NULL;
115
116         DEBUG(10, ("entering solarisacl_sys_acl_get_fd.\n"));
117
118         if (!solaris_acl_get_fd(fsp_get_io_fd(fsp), &solaris_acl, &count)) {
119                 goto done;
120         }
121
122         if (type != SMB_ACL_TYPE_ACCESS && type != SMB_ACL_TYPE_DEFAULT) {
123                 DEBUG(10, ("invalid SMB_ACL_TYPE given (%d)\n", type));
124                 errno = EINVAL;
125                 goto done;
126         }
127         /* 
128          * The facl call returns both ACCESS and DEFAULT acls (as present). 
129          * The posix acl_get_fd function returns only the
130          * access acl. So we need to filter this out here.  
131          */
132         result = solaris_acl_to_smb_acl(solaris_acl, count,
133                                         type, mem_ctx);
134         if (result == NULL) {
135                 DEBUG(10, ("conversion solaris_acl -> smb_acl failed (%s).\n",
136                            strerror(errno)));
137         }
138         
139  done:
140         DEBUG(10, ("solarisacl_sys_acl_get_fd %s.\n", 
141                    ((result == NULL) ? "failed" : "succeeded")));
142         SAFE_FREE(solaris_acl);
143         return result;
144 }
145
146 /*
147  * set the access ACL on the file referred to by a fd 
148  */
149 int solarisacl_sys_acl_set_fd(vfs_handle_struct *handle,
150                               files_struct *fsp,
151                               SMB_ACL_TYPE_T type,
152                               SMB_ACL_T theacl)
153 {
154         SOLARIS_ACL_T solaris_acl = NULL;
155         int count;
156         SOLARIS_ACL_T other_acl = NULL;
157         int other_count;
158         SMB_ACL_TYPE_T other_type;
159         int ret = -1;
160
161         DEBUG(10, ("entering solarisacl_sys_acl_set_fd\n"));
162
163         /* 
164          * the posix acl_set_fd call sets the access acl of the
165          * file referred to by fd. the solaris facl-SETACL call
166          * sets the access and default acl as provided, so we
167          * have to retrieve the default acl of the file and 
168          * concatenate it with the access acl provided.
169          */
170         if (!smb_acl_to_solaris_acl(theacl, &solaris_acl, &count, 
171                                     type))
172         {
173                 DEBUG(10, ("conversion smb_acl -> solaris_acl failed (%s).\n",
174                            strerror(errno)));
175                 goto done;
176         }
177         if (!solaris_acl_get_fd(fsp_get_io_fd(fsp), &other_acl, &other_count)) {
178                 DEBUG(10, ("error getting (default) acl from fd\n"));
179                 goto done;
180         }
181
182         other_type = (type == SMB_ACL_TYPE_ACCESS)
183                 ? SMB_ACL_TYPE_DEFAULT
184                 : SMB_ACL_TYPE_ACCESS;
185
186         if (!solaris_add_to_acl(&solaris_acl, &count,
187                                 other_acl, other_count,
188                                 other_type))
189         {
190                 DEBUG(10, ("error adding default acl to solaris acl\n"));
191                 goto done;
192         }
193         if (!solaris_acl_sort(solaris_acl, count)) {
194                 DEBUG(10, ("resulting acl is not valid!\n"));
195                 goto done;
196         }
197
198         ret = facl(fsp_get_io_fd(fsp), SETACL, count, solaris_acl);
199         if (ret != 0) {
200                 DEBUG(10, ("call of facl failed (%s).\n", strerror(errno)));
201         }
202
203  done:
204         DEBUG(10, ("solarisacl_sys_acl_set_fd %s.\n",
205                    ((ret == 0) ? "succeeded" : "failed" )));
206         SAFE_FREE(solaris_acl);
207         SAFE_FREE(other_acl);
208         return ret;
209 }
210
211 /*
212  * delete the default ACL of a directory
213  *
214  * This is achieved by fetching the access ACL and rewriting it
215  * directly, via the solaris system call: the SETACL call on
216  * directories writes both the access and the default ACL as provided.
217  *
218  * XXX: posix acl_delete_def_file returns an error if
219  * the file referred to by path is not a directory.
220  * this function does not complain but the actions
221  * have no effect on a file other than a directory.
222  * But sys_acl_delete_default_file is only called in
223  * smbd/posixacls.c after having checked that the file
224  * is a directory, anyways. So implementing the extra
225  * check is considered unnecessary. --- Agreed? XXX
226  */
227 int solarisacl_sys_acl_delete_def_fd(vfs_handle_struct *handle,
228                                 files_struct *fsp)
229 {
230         SMB_ACL_T smb_acl;
231         int ret = -1;
232         SOLARIS_ACL_T solaris_acl = NULL;
233         int count;
234
235         DBG_DEBUG("entering solarisacl_sys_acl_delete_def_fd.\n");
236
237         smb_acl = solarisacl_sys_acl_get_file(handle, fsp->fsp_name->base_name,
238                                               SMB_ACL_TYPE_ACCESS, talloc_tos());
239         if (smb_acl == NULL) {
240                 DBG_DEBUG("getting file acl failed!\n");
241                 goto done;
242         }
243         if (!smb_acl_to_solaris_acl(smb_acl, &solaris_acl, &count,
244                                     SMB_ACL_TYPE_ACCESS))
245         {
246                 DBG_DEBUG("conversion smb_acl -> solaris_acl failed.\n");
247                 goto done;
248         }
249         if (!solaris_acl_sort(solaris_acl, count)) {
250                 DBG_DEBUG("resulting acl is not valid!\n");
251                 goto done;
252         }
253         ret = acl(fsp->fsp_name->base_name, SETACL, count, solaris_acl);
254         if (ret != 0) {
255                 DBG_DEBG("settinge file acl failed!\n");
256         }
257
258  done:
259         DBG_DEBUG("solarisacl_sys_acl_delete_def_fd %s.\n",
260                    ((ret != 0) ? "failed" : "succeeded" ));
261         TALLOC_FREE(smb_acl);
262         return ret;
263 }
264
265 /* private functions */
266
267 static SOLARIS_ACL_T solaris_acl_init(int count)
268 {
269         SOLARIS_ACL_T solaris_acl = 
270                 (SOLARIS_ACL_T)SMB_MALLOC(sizeof(aclent_t) * count);
271         if (solaris_acl == NULL) {
272                 errno = ENOMEM;
273         }
274         return solaris_acl;
275 }
276
277 /*
278  * Convert the SMB acl to the ACCESS or DEFAULT part of a 
279  * solaris ACL, as desired.
280  */
281 static bool smb_acl_to_solaris_acl(SMB_ACL_T smb_acl, 
282                                    SOLARIS_ACL_T *solaris_acl, int *count, 
283                                    SMB_ACL_TYPE_T type)
284 {
285         bool ret = False;
286         int i;
287
288         DEBUG(10, ("entering smb_acl_to_solaris_acl\n"));
289         
290         *solaris_acl = NULL;
291         *count = 0;
292
293         for (i = 0; i < smb_acl->count; i++) {
294                 const struct smb_acl_entry *smb_entry = &(smb_acl->acl[i]);
295                 SOLARIS_ACE_T solaris_entry;
296
297                 ZERO_STRUCT(solaris_entry);
298
299                 solaris_entry.a_type = smb_tag_to_solaris_tag(smb_entry->a_type);
300                 if (solaris_entry.a_type == 0) {
301                         DEBUG(10, ("smb_tag to solaris_tag failed\n"));
302                         goto fail;
303                 }
304                 switch(solaris_entry.a_type) {
305                 case USER:
306                         DEBUG(10, ("got tag type USER with uid %u\n", 
307                                    (unsigned int)smb_entry->info.user.uid));
308                         solaris_entry.a_id = (uid_t)smb_entry->info.user.uid;
309                         break;
310                 case GROUP:
311                         DEBUG(10, ("got tag type GROUP with gid %u\n", 
312                                    (unsigned int)smb_entry->info.group.gid));
313                         solaris_entry.a_id = (uid_t)smb_entry->info.group.gid;
314                         break;
315                 default:
316                         break;
317                 }
318                 if (type == SMB_ACL_TYPE_DEFAULT) {
319                         DEBUG(10, ("adding default bit to solaris ace\n"));
320                         solaris_entry.a_type |= ACL_DEFAULT;
321                 }
322                 
323                 solaris_entry.a_perm = 
324                         smb_perm_to_solaris_perm(smb_entry->a_perm);
325                 DEBUG(10, ("assembled the following solaris ace:\n"));
326                 DEBUGADD(10, (" - type: 0x%04x\n", solaris_entry.a_type));
327                 DEBUGADD(10, (" - id: %u\n", (unsigned int)solaris_entry.a_id));
328                 DEBUGADD(10, (" - perm: o%o\n", solaris_entry.a_perm));
329                 if (!solaris_add_to_acl(solaris_acl, count, &solaris_entry, 
330                                         1, type))
331                 {
332                         DEBUG(10, ("error adding acl entry\n"));
333                         goto fail;
334                 }
335                 DEBUG(10, ("count after adding: %d (i: %d)\n", *count, i));
336                 DEBUG(10, ("test, if entry has been copied into acl:\n"));
337                 DEBUGADD(10, (" - type: 0x%04x\n",
338                               (*solaris_acl)[(*count)-1].a_type));
339                 DEBUGADD(10, (" - id: %u\n",
340                               (unsigned int)(*solaris_acl)[(*count)-1].a_id));
341                 DEBUGADD(10, (" - perm: o%o\n",
342                               (*solaris_acl)[(*count)-1].a_perm));
343         }
344
345         ret = True;
346         goto done;
347         
348  fail:
349         SAFE_FREE(*solaris_acl);
350  done:
351         DEBUG(10, ("smb_acl_to_solaris_acl %s\n",
352                    ((ret == True) ? "succeeded" : "failed")));
353         return ret;
354 }
355
356 /* 
357  * convert either the access or the default part of a 
358  * soaris acl to the SMB_ACL format.
359  */
360 static SMB_ACL_T solaris_acl_to_smb_acl(SOLARIS_ACL_T solaris_acl, int count, 
361                                         SMB_ACL_TYPE_T type, TALLOC_CTX *mem_ctx)
362 {
363         SMB_ACL_T result;
364         int i;
365
366         if ((result = sys_acl_init(mem_ctx)) == NULL) {
367                 DEBUG(10, ("error allocating memory for SMB_ACL\n"));
368                 goto fail;
369         }
370         for (i = 0; i < count; i++) {
371                 SMB_ACL_ENTRY_T smb_entry;
372                 SMB_ACL_PERM_T smb_perm;
373                 
374                 if (!_IS_OF_TYPE(solaris_acl[i], type)) {
375                         continue;
376                 }
377                 result->acl = talloc_realloc(result, result->acl, struct smb_acl_entry, result->count + 1);
378                 if (result->acl == NULL) {
379                         DEBUG(10, ("error reallocating memory for SMB_ACL\n"));
380                         goto fail;
381                 }
382                 smb_entry = &result->acl[result->count];
383                 if (sys_acl_set_tag_type(smb_entry,
384                                          solaris_tag_to_smb_tag(solaris_acl[i].a_type)) != 0)
385                 {
386                         DEBUG(10, ("invalid tag type given: 0x%04x\n",
387                                    solaris_acl[i].a_type));
388                         goto fail;
389                 }
390                 /* intentionally not checking return code here: */
391                 sys_acl_set_qualifier(smb_entry, (void *)&solaris_acl[i].a_id);
392                 smb_perm = solaris_perm_to_smb_perm(solaris_acl[i].a_perm);
393                 if (sys_acl_set_permset(smb_entry, &smb_perm) != 0) {
394                         DEBUG(10, ("invalid permset given: %d\n", 
395                                    solaris_acl[i].a_perm));
396                         goto fail;
397                 }
398                 result->count += 1;
399         }
400         goto done;
401         
402  fail:
403         TALLOC_FREE(result);
404  done:
405         DEBUG(10, ("solaris_acl_to_smb_acl %s\n",
406                    ((result == NULL) ? "failed" : "succeeded")));
407         return result;
408 }
409
410
411
412 static SOLARIS_ACL_TAG_T smb_tag_to_solaris_tag(SMB_ACL_TAG_T smb_tag)
413 {
414         SOLARIS_ACL_TAG_T solaris_tag = 0;
415
416         DEBUG(10, ("smb_tag_to_solaris_tag\n"));
417         DEBUGADD(10, (" --> got smb tag 0x%04x\n", smb_tag));
418         
419         switch (smb_tag) {
420         case SMB_ACL_USER:
421                 solaris_tag = USER;
422                 break;
423         case SMB_ACL_USER_OBJ:
424                 solaris_tag = USER_OBJ;
425                 break;
426         case SMB_ACL_GROUP:
427                 solaris_tag = GROUP;
428                 break;
429         case SMB_ACL_GROUP_OBJ:
430                 solaris_tag = GROUP_OBJ;
431                 break;
432         case SMB_ACL_OTHER:
433                 solaris_tag = OTHER_OBJ;
434                 break;
435         case SMB_ACL_MASK:
436                 solaris_tag = CLASS_OBJ;
437                 break;
438         default:
439                 DEBUGADD(10, (" !!! unknown smb tag type 0x%04x\n", smb_tag));
440                 break;
441         }
442         
443         DEBUGADD(10, (" --> determined solaris tag 0x%04x\n", solaris_tag));
444
445         return solaris_tag;
446 }
447
448 static SMB_ACL_TAG_T solaris_tag_to_smb_tag(SOLARIS_ACL_TAG_T solaris_tag)
449 {
450         SMB_ACL_TAG_T smb_tag = 0;
451
452         DEBUG(10, ("solaris_tag_to_smb_tag:\n"));
453         DEBUGADD(10, (" --> got solaris tag 0x%04x\n", solaris_tag)); 
454         
455         solaris_tag &= ~ACL_DEFAULT; 
456
457         switch (solaris_tag) {
458         case USER:
459                 smb_tag = SMB_ACL_USER;
460                 break;
461         case USER_OBJ:
462                 smb_tag = SMB_ACL_USER_OBJ;
463                 break;
464         case GROUP:
465                 smb_tag = SMB_ACL_GROUP;
466                 break;
467         case GROUP_OBJ:
468                 smb_tag = SMB_ACL_GROUP_OBJ;
469                 break;
470         case OTHER_OBJ:
471                 smb_tag = SMB_ACL_OTHER;
472                 break;
473         case CLASS_OBJ:
474                 smb_tag = SMB_ACL_MASK;
475                 break;
476         default:
477                 DEBUGADD(10, (" !!! unknown solaris tag type: 0x%04x\n", 
478                                         solaris_tag));
479                 break;
480         }
481
482         DEBUGADD(10, (" --> determined smb tag 0x%04x\n", smb_tag));
483         
484         return smb_tag;
485 }
486
487
488 static SMB_ACL_PERM_T solaris_perm_to_smb_perm(const SOLARIS_PERM_T perm)
489 {
490         SMB_ACL_PERM_T smb_perm = 0;
491         smb_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
492         smb_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
493         smb_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
494         return smb_perm;
495 }
496
497
498 static SOLARIS_PERM_T smb_perm_to_solaris_perm(const SMB_ACL_PERM_T perm)
499 {
500         SOLARIS_PERM_T solaris_perm = 0;
501         solaris_perm |= ((perm & SMB_ACL_READ) ? SMB_ACL_READ : 0);
502         solaris_perm |= ((perm & SMB_ACL_WRITE) ? SMB_ACL_WRITE : 0);
503         solaris_perm |= ((perm & SMB_ACL_EXECUTE) ? SMB_ACL_EXECUTE : 0);
504         return solaris_perm;
505 }
506
507
508 static bool solaris_acl_get_file(const char *name, SOLARIS_ACL_T *solaris_acl, 
509                                  int *count)
510 {
511         bool result = False;
512
513         DEBUG(10, ("solaris_acl_get_file called for file '%s'\n", name));
514         
515         /* 
516          * The original code tries some INITIAL_ACL_SIZE
517          * and only did the GETACLCNT call upon failure
518          * (for performance reasons).
519          * For the sake of simplicity, I skip this for now. 
520          */
521         *count = acl(name, GETACLCNT, 0, NULL);
522         if (*count < 0) {
523                 DEBUG(10, ("acl GETACLCNT failed: %s\n", strerror(errno)));
524                 goto done;
525         }
526         *solaris_acl = solaris_acl_init(*count);
527         if (*solaris_acl == NULL) {
528                 DEBUG(10, ("error allocating memory for solaris acl...\n"));
529                 goto done;
530         }
531         *count = acl(name, GETACL, *count, *solaris_acl);
532         if (*count < 0) {
533                 DEBUG(10, ("acl GETACL failed: %s\n", strerror(errno)));
534                 goto done;
535         }
536         result = True;
537
538  done:
539         DEBUG(10, ("solaris_acl_get_file %s.\n",
540                    ((result == True) ? "succeeded" : "failed" )));
541         return result;
542 }
543
544
545 static bool solaris_acl_get_fd(int fd, SOLARIS_ACL_T *solaris_acl, int *count)
546 {
547         bool ret = False;
548
549         DEBUG(10, ("entering solaris_acl_get_fd\n"));
550
551         /* 
552          * see solaris_acl_get_file for comment about omission 
553          * of INITIAL_ACL_SIZE... 
554          */
555         *count = facl(fd, GETACLCNT, 0, NULL);
556         if (*count < 0) {
557                 DEBUG(10, ("facl GETACLCNT failed: %s\n", strerror(errno)));
558                 goto done;
559         }
560         *solaris_acl = solaris_acl_init(*count);
561         if (*solaris_acl == NULL) {
562                 DEBUG(10, ("error allocating memory for solaris acl...\n"));
563                 goto done;
564         }
565         *count = facl(fd, GETACL, *count, *solaris_acl);
566         if (*count < 0) {
567                 DEBUG(10, ("facl GETACL failed: %s\n", strerror(errno)));
568                 goto done;
569         }
570         ret = True;
571
572  done:
573         DEBUG(10, ("solaris_acl_get_fd %s\n",
574                    ((ret == True) ? "succeeded" : "failed")));
575         return ret;
576 }
577
578
579
580 /*
581  * Add entries to a solaris ACL.
582  *
583  * Entries are directly added to the solarisacl parameter.
584  * if memory allocation fails, this may result in solarisacl 
585  * being NULL. if the resulting acl is to be checked and is 
586  * not valid, it is kept in solarisacl but False is returned.
587  *
588  * The type of ACEs (access/default) to be added to the ACL can 
589  * be selected via the type parameter. 
590  * I use the SMB_ACL_TYPE_T type here. Since SMB_ACL_TYPE_ACCESS
591  * is defined as "0", this means that one can only add either
592  * access or default ACEs, not both at the same time. If it 
593  * should become necessary to add all of an ACL, one would have
594  * to replace this parameter by another type.
595  */
596 static bool solaris_add_to_acl(SOLARIS_ACL_T *solaris_acl, int *count,
597                                SOLARIS_ACL_T add_acl, int add_count, 
598                                SMB_ACL_TYPE_T type)
599 {
600         int i;
601         
602         if ((type != SMB_ACL_TYPE_ACCESS) && (type != SMB_ACL_TYPE_DEFAULT)) 
603         {
604                 DEBUG(10, ("invalid acl type given: %d\n", type));
605                 errno = EINVAL;
606                 return False;
607         }
608         for (i = 0; i < add_count; i++) {
609                 if (!_IS_OF_TYPE(add_acl[i], type)) {
610                         continue;
611                 }
612                 ADD_TO_ARRAY(NULL, SOLARIS_ACE_T, add_acl[i], 
613                              solaris_acl, count);
614                 if (solaris_acl == NULL) {
615                         DEBUG(10, ("error enlarging acl.\n"));
616                         errno = ENOMEM;
617                         return False;
618                 }
619         }
620         return True;
621 }
622
623
624 /* 
625  * sort the ACL and check it for validity
626  *
627  * [original comment from lib/sysacls.c:]
628  * 
629  * if it's a minimal ACL with only 4 entries then we
630  * need to recalculate the mask permissions to make
631  * sure that they are the same as the GROUP_OBJ
632  * permissions as required by the UnixWare acl() system call.
633  *
634  * (note: since POSIX allows minimal ACLs which only contain
635  * 3 entries - ie there is no mask entry - we should, in theory,
636  * check for this and add a mask entry if necessary - however
637  * we "know" that the caller of this interface always specifies
638  * a mask, so in practice "this never happens" (tm) - if it *does*
639  * happen aclsort() will fail and return an error and someone will
640  * have to fix it...)
641  */
642 static bool solaris_acl_sort(SOLARIS_ACL_T solaris_acl, int count)
643 {
644         int fixmask = (count <= 4);
645
646         if (aclsort(count, fixmask, solaris_acl) != 0) {
647                 errno = EINVAL;
648                 return False;
649         }
650         return True;
651 }
652
653 #if 0
654 /*
655  * acl check function:
656  *   unused at the moment but could be used to get more
657  *   concrete error messages for debugging...
658  *   (acl sort just says that the acl is invalid...)
659  */
660 static bool solaris_acl_check(SOLARIS_ACL_T solaris_acl, int count)
661 {
662         int check_rc;
663         int check_which;
664         
665         check_rc = aclcheck(solaris_acl, count, &check_which);
666         if (check_rc != 0) {
667                 DEBUG(10, ("acl is not valid:\n"));
668                 DEBUGADD(10, (" - return code: %d\n", check_rc));
669                 DEBUGADD(10, (" - which: %d\n", check_which));
670                 if (check_which != -1) {
671                         DEBUGADD(10, (" - invalid entry:\n"));
672                         DEBUGADD(10, ("   * type: %d:\n", 
673                                       solaris_acl[check_which].a_type));
674                         DEBUGADD(10, ("   * id: %d\n",
675                                       solaris_acl[check_which].a_id));
676                         DEBUGADD(10, ("   * perm: 0o%o\n",
677                                       solaris_acl[check_which].a_perm));
678                 }
679                 return False;
680         }
681         return True;
682 }
683 #endif
684
685 static struct vfs_fn_pointers solarisacl_fns = {
686         .sys_acl_get_fd_fn = solarisacl_sys_acl_get_fd,
687         .sys_acl_blob_get_fd_fn = posix_sys_acl_blob_get_fd,
688         .sys_acl_set_fd_fn = solarisacl_sys_acl_set_fd,
689         .sys_acl_delete_def_fd_fn = solarisacl_sys_acl_delete_def_fd,
690 };
691
692 static_decl_vfs;
693 NTSTATUS vfs_solarisacl_init(TALLOC_CTX *ctx)
694 {
695         return smb_register_vfs(SMB_VFS_INTERFACE_VERSION, "solarisacl",
696                                 &solarisacl_fns);
697 }
698
699 /* ENTE */