]> sourceware.org Git - newlib-cygwin.git/blame - winsup/cygwin/sec_acl.cc
Throughout, update copyrights to reflect dates which correspond to main-branch
[newlib-cygwin.git] / winsup / cygwin / sec_acl.cc
CommitLineData
ab2dbccc 1/* sec_acl.cc: Sun compatible ACL functions.
c0d1968a 2
bc837d22
CF
3 Copyright 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010,
4 2011, 2012 Red Hat, Inc.
c0d1968a
CV
5
6 Written by Corinna Vinschen <corinna@vinschen.de>
7
8This file is part of Cygwin.
9
10This software is a copyrighted work licensed under the terms of the
11Cygwin license. Please consult the file "CYGWIN_LICENSE" for
12details. */
13
14#include "winsup.h"
c0d1968a 15#include <stdlib.h>
c0d1968a
CV
16#include <sys/acl.h>
17#include <ctype.h>
c0d1968a 18#include "cygerrno.h"
6b91b8d5 19#include "security.h"
c0d1968a 20#include "path.h"
7ac61736 21#include "fhandler.h"
c0d1968a 22#include "dtable.h"
c0d1968a 23#include "cygheap.h"
1754539e 24#include "ntdll.h"
d6ffc075 25#include "pwdgrp.h"
4e8f539f 26#include "tls_pbuf.h"
c0d1968a
CV
27
28static int
62cd433e 29searchace (__aclent32_t *aclp, int nentries, int type, __uid32_t id = ILLEGAL_UID)
c0d1968a
CV
30{
31 int i;
32
33 for (i = 0; i < nentries; ++i)
62cd433e 34 if ((aclp[i].a_type == type && (id == ILLEGAL_UID || aclp[i].a_id == id))
c0d1968a
CV
35 || !aclp[i].a_type)
36 return i;
37 return -1;
38}
39
e3d1d515 40int
eea4e482 41setacl (HANDLE handle, path_conv &pc, int nentries, __aclent32_t *aclbufp,
6bcc8fd7 42 bool &writable)
c0d1968a 43{
12069cf3 44 security_descriptor sd_ret;
4e8f539f 45 tmp_pathbuf tp;
c0d1968a 46
67a93078 47 if (get_file_sd (handle, pc, sd_ret, false))
eea4e482 48 return -1;
c0d1968a 49
1838d97b
CV
50 NTSTATUS status;
51 BOOLEAN dummy;
c0d1968a
CV
52
53 /* Get owner SID. */
62cd433e 54 PSID owner_sid;
1838d97b
CV
55 status = RtlGetOwnerSecurityDescriptor (sd_ret, &owner_sid, &dummy);
56 if (!NT_SUCCESS (status))
c0d1968a 57 {
1838d97b 58 __seterrno_from_nt_status (status);
c0d1968a
CV
59 return -1;
60 }
d551169a 61 cygsid owner (owner_sid);
c0d1968a
CV
62
63 /* Get group SID. */
62cd433e 64 PSID group_sid;
1838d97b
CV
65 status = RtlGetGroupSecurityDescriptor (sd_ret, &group_sid, &dummy);
66 if (!NT_SUCCESS (status))
c0d1968a 67 {
1838d97b 68 __seterrno_from_nt_status (status);
c0d1968a
CV
69 return -1;
70 }
d551169a 71 cygsid group (group_sid);
c0d1968a
CV
72
73 /* Initialize local security descriptor. */
74 SECURITY_DESCRIPTOR sd;
1754539e 75 RtlCreateSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION);
fd04c2f0
CV
76 status = RtlSetOwnerSecurityDescriptor (&sd, owner, FALSE);
77 if (!NT_SUCCESS (status))
c0d1968a 78 {
fd04c2f0 79 __seterrno_from_nt_status (status);
c0d1968a
CV
80 return -1;
81 }
fd04c2f0
CV
82 status = RtlSetGroupSecurityDescriptor (&sd, group, FALSE);
83 if (!NT_SUCCESS (status))
c0d1968a 84 {
fd04c2f0 85 __seterrno_from_nt_status (status);
c0d1968a
CV
86 return -1;
87 }
88
89 /* Fill access control list. */
4e8f539f 90 PACL acl = (PACL) tp.w_get ();
c0d1968a
CV
91 size_t acl_len = sizeof (ACL);
92 int ace_off = 0;
93
d551169a 94 cygsid sid;
c0d1968a 95 struct passwd *pw;
57196405 96 struct __group32 *gr;
c0d1968a
CV
97 int pos;
98
1754539e 99 RtlCreateAcl (acl, ACL_MAXIMUM_SIZE, ACL_REVISION);
6bcc8fd7
CV
100
101 writable = false;
102
c0d1968a
CV
103 for (int i = 0; i < nentries; ++i)
104 {
62cd433e
CV
105 DWORD allow;
106 /* Owner has more standard rights set. */
107 if ((aclbufp[i].a_type & ~ACL_DEFAULT) == USER_OBJ)
5f9ca0d2
CV
108 allow = STANDARD_RIGHTS_ALL
109 | (pc.fs_is_samba ()
110 ? 0 : (FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES));
62cd433e 111 else
5f9ca0d2
CV
112 allow = STANDARD_RIGHTS_READ
113 | (pc.fs_is_samba () ? 0 : FILE_READ_ATTRIBUTES);
c0d1968a
CV
114 if (aclbufp[i].a_perm & S_IROTH)
115 allow |= FILE_GENERIC_READ;
116 if (aclbufp[i].a_perm & S_IWOTH)
6bcc8fd7 117 {
5f9ca0d2 118 allow |= FILE_GENERIC_WRITE;
6bcc8fd7
CV
119 writable = true;
120 }
c0d1968a 121 if (aclbufp[i].a_perm & S_IXOTH)
5f9ca0d2 122 allow |= FILE_GENERIC_EXECUTE & ~FILE_READ_ATTRIBUTES;
3a157c0d 123 if ((aclbufp[i].a_perm & (S_IWOTH | S_IXOTH)) == (S_IWOTH | S_IXOTH))
1ff9f4b9 124 allow |= FILE_DELETE_CHILD;
c0d1968a
CV
125 /* Set inherit property. */
126 DWORD inheritance = (aclbufp[i].a_type & ACL_DEFAULT)
b42441d3
CV
127 ? (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE
128 | INHERIT_ONLY_ACE)
654bad37 129 : NO_INHERITANCE;
c0d1968a
CV
130 /*
131 * If a specific acl contains a corresponding default entry with
132 * identical permissions, only one Windows ACE with proper
133 * inheritance bits is created.
134 */
135 if (!(aclbufp[i].a_type & ACL_DEFAULT)
ab2dbccc 136 && aclbufp[i].a_type & (USER|GROUP|OTHER_OBJ)
9a751621 137 && (pos = searchace (aclbufp + i + 1, nentries - i - 1,
c0d1968a
CV
138 aclbufp[i].a_type | ACL_DEFAULT,
139 (aclbufp[i].a_type & (USER|GROUP))
62cd433e 140 ? aclbufp[i].a_id : ILLEGAL_UID)) >= 0
bb090650 141 && aclbufp[i].a_perm == aclbufp[i + 1 + pos].a_perm)
c0d1968a 142 {
b42441d3 143 inheritance = CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE;
9a751621 144 /* This invalidates the corresponding default entry. */
bb090650 145 aclbufp[i + 1 + pos].a_type = USER|GROUP|ACL_DEFAULT;
c0d1968a
CV
146 }
147 switch (aclbufp[i].a_type)
148 {
149 case USER_OBJ:
c0d1968a 150 if (!add_access_allowed_ace (acl, ace_off++, allow,
d551169a 151 owner, acl_len, inheritance))
c0d1968a
CV
152 return -1;
153 break;
ab2dbccc 154 case DEF_USER_OBJ:
ab2dbccc
CV
155 if (!add_access_allowed_ace (acl, ace_off++, allow,
156 well_known_creator_owner_sid, acl_len, inheritance))
157 return -1;
158 break;
c0d1968a
CV
159 case USER:
160 case DEF_USER:
d6ffc075 161 if (!(pw = internal_getpwuid (aclbufp[i].a_id))
c1410a8d
CV
162 || !sid.getfrompw (pw))
163 {
164 set_errno (EINVAL);
165 return -1;
166 }
167 if (!add_access_allowed_ace (acl, ace_off++, allow,
168 sid, acl_len, inheritance))
c0d1968a
CV
169 return -1;
170 break;
171 case GROUP_OBJ:
c0d1968a 172 if (!add_access_allowed_ace (acl, ace_off++, allow,
62cd433e 173 group, acl_len, inheritance))
c0d1968a
CV
174 return -1;
175 break;
ab2dbccc
CV
176 case DEF_GROUP_OBJ:
177 if (!add_access_allowed_ace (acl, ace_off++, allow,
178 well_known_creator_group_sid, acl_len, inheritance))
179 return -1;
180 break;
c0d1968a
CV
181 case GROUP:
182 case DEF_GROUP:
d6ffc075 183 if (!(gr = internal_getgrgid (aclbufp[i].a_id))
c1410a8d
CV
184 || !sid.getfromgr (gr))
185 {
186 set_errno (EINVAL);
187 return -1;
188 }
189 if (!add_access_allowed_ace (acl, ace_off++, allow,
190 sid, acl_len, inheritance))
c0d1968a
CV
191 return -1;
192 break;
193 case OTHER_OBJ:
194 case DEF_OTHER_OBJ:
195 if (!add_access_allowed_ace (acl, ace_off++, allow,
2b0a111f
CV
196 well_known_world_sid,
197 acl_len, inheritance))
c0d1968a
CV
198 return -1;
199 break;
200 }
201 }
202 /* Set AclSize to computed value. */
203 acl->AclSize = acl_len;
204 debug_printf ("ACL-Size: %d", acl_len);
205 /* Create DACL for local security descriptor. */
fd04c2f0
CV
206 status = RtlSetDaclSecurityDescriptor (&sd, TRUE, acl, FALSE);
207 if (!NT_SUCCESS (status))
c0d1968a 208 {
fd04c2f0 209 __seterrno_from_nt_status (status);
c0d1968a
CV
210 return -1;
211 }
12069cf3
CV
212 /* Make self relative security descriptor in sd_ret. */
213 DWORD sd_size = 0;
5735d5f6 214 RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size);
c0d1968a
CV
215 if (sd_size <= 0)
216 {
217 __seterrno ();
218 return -1;
219 }
fb69e3ed
CV
220 if (!sd_ret.realloc (sd_size))
221 {
222 set_errno (ENOMEM);
223 return -1;
224 }
5735d5f6
CV
225 status = RtlAbsoluteToSelfRelativeSD (&sd, sd_ret, &sd_size);
226 if (!NT_SUCCESS (status))
c0d1968a 227 {
5735d5f6 228 __seterrno_from_nt_status (status);
c0d1968a
CV
229 return -1;
230 }
12069cf3 231 debug_printf ("Created SD-Size: %d", sd_ret.size ());
2d647173 232 return set_file_sd (handle, pc, sd_ret, false);
c0d1968a
CV
233}
234
19f20901
CV
235/* Temporary access denied bits */
236#define DENY_R 040000
237#define DENY_W 020000
238#define DENY_X 010000
239
c0d1968a 240static void
62cd433e 241getace (__aclent32_t &acl, int type, int id, DWORD win_ace_mask,
9a751621 242 DWORD win_ace_type)
c0d1968a
CV
243{
244 acl.a_type = type;
245 acl.a_id = id;
246
3db69078 247 if ((win_ace_mask & FILE_READ_BITS) && !(acl.a_perm & (S_IROTH | DENY_R)))
7b9e380f
CF
248 {
249 if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
250 acl.a_perm |= S_IROTH;
251 else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
252 acl.a_perm |= DENY_R;
253 }
c0d1968a 254
3db69078 255 if ((win_ace_mask & FILE_WRITE_BITS) && !(acl.a_perm & (S_IWOTH | DENY_W)))
7b9e380f
CF
256 {
257 if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
258 acl.a_perm |= S_IWOTH;
259 else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
260 acl.a_perm |= DENY_W;
261 }
c0d1968a 262
3db69078 263 if ((win_ace_mask & FILE_EXEC_BITS) && !(acl.a_perm & (S_IXOTH | DENY_X)))
7b9e380f
CF
264 {
265 if (win_ace_type == ACCESS_ALLOWED_ACE_TYPE)
266 acl.a_perm |= S_IXOTH;
267 else if (win_ace_type == ACCESS_DENIED_ACE_TYPE)
268 acl.a_perm |= DENY_X;
269 }
c0d1968a
CV
270}
271
e3d1d515 272int
eea4e482 273getacl (HANDLE handle, path_conv &pc, int nentries, __aclent32_t *aclbufp)
c0d1968a 274{
12069cf3 275 security_descriptor sd;
c0d1968a 276
67a93078 277 if (get_file_sd (handle, pc, sd, false))
eea4e482 278 return -1;
c0d1968a 279
62cd433e
CV
280 cygpsid owner_sid;
281 cygpsid group_sid;
1838d97b
CV
282 NTSTATUS status;
283 BOOLEAN dummy;
a8d7ae61 284 __uid32_t uid;
57196405 285 __gid32_t gid;
c0d1968a 286
1838d97b
CV
287 status = RtlGetOwnerSecurityDescriptor (sd, (PSID *) &owner_sid, &dummy);
288 if (!NT_SUCCESS (status))
c0d1968a 289 {
1838d97b 290 __seterrno_from_nt_status (status);
c0d1968a
CV
291 return -1;
292 }
62cd433e 293 uid = owner_sid.get_uid ();
c0d1968a 294
1838d97b
CV
295 status = RtlGetGroupSecurityDescriptor (sd, (PSID *) &group_sid, &dummy);
296 if (!NT_SUCCESS (status))
c0d1968a 297 {
1838d97b 298 __seterrno_from_nt_status (status);
c0d1968a
CV
299 return -1;
300 }
62cd433e 301 gid = group_sid.get_gid ();
c0d1968a 302
62cd433e
CV
303 __aclent32_t lacl[MAX_ACL_ENTRIES];
304 memset (&lacl, 0, MAX_ACL_ENTRIES * sizeof (__aclent32_t));
c0d1968a
CV
305 lacl[0].a_type = USER_OBJ;
306 lacl[0].a_id = uid;
307 lacl[1].a_type = GROUP_OBJ;
308 lacl[1].a_id = gid;
309 lacl[2].a_type = OTHER_OBJ;
19f20901
CV
310 lacl[2].a_id = ILLEGAL_GID;
311 lacl[3].a_type = CLASS_OBJ;
312 lacl[3].a_id = ILLEGAL_GID;
313 lacl[3].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
c0d1968a
CV
314
315 PACL acl;
1838d97b 316 BOOLEAN acl_exists;
c0d1968a 317
1838d97b
CV
318 status = RtlGetDaclSecurityDescriptor (sd, &acl_exists, &acl, &dummy);
319 if (!NT_SUCCESS (status))
c0d1968a 320 {
1838d97b 321 __seterrno_from_nt_status (status);
c0d1968a
CV
322 return -1;
323 }
324
19f20901 325 int pos, i, types_def = 0;
c0d1968a
CV
326
327 if (!acl_exists || !acl)
19f20901
CV
328 for (pos = 0; pos < 3; ++pos) /* Don't change CLASS_OBJ entry */
329 lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
330 else
c0d1968a 331 {
19f20901
CV
332 for (i = 0; i < acl->AceCount; ++i)
333 {
334 ACCESS_ALLOWED_ACE *ace;
6d147411 335
1754539e 336 if (!NT_SUCCESS (RtlGetAce (acl, i, (PVOID *) &ace)))
19f20901 337 continue;
c0d1968a 338
62cd433e 339 cygpsid ace_sid ((PSID) &ace->SidStart);
19f20901
CV
340 int id;
341 int type = 0;
c0d1968a 342
19f20901
CV
343 if (ace_sid == well_known_world_sid)
344 {
345 type = OTHER_OBJ;
346 id = ILLEGAL_GID;
347 }
348 else if (ace_sid == group_sid)
349 {
350 type = GROUP_OBJ;
351 id = gid;
352 }
353 else if (ace_sid == owner_sid)
c0d1968a 354 {
19f20901
CV
355 type = USER_OBJ;
356 id = uid;
357 }
ab2dbccc
CV
358 else if (ace_sid == well_known_creator_group_sid)
359 {
360 type = GROUP_OBJ | ACL_DEFAULT;
e445b7c3 361 types_def |= type;
ab2dbccc
CV
362 id = ILLEGAL_GID;
363 }
364 else if (ace_sid == well_known_creator_owner_sid)
365 {
366 type = USER_OBJ | ACL_DEFAULT;
e445b7c3 367 types_def |= type;
ab2dbccc
CV
368 id = ILLEGAL_GID;
369 }
19f20901 370 else
2e008fb9 371 id = ace_sid.get_id (true, &type);
62cd433e 372
19f20901
CV
373 if (!type)
374 continue;
b42441d3 375 if (!(ace->Header.AceFlags & INHERIT_ONLY_ACE || type & ACL_DEFAULT))
19f20901
CV
376 {
377 if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
378 getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
379 }
b42441d3
CV
380 if ((ace->Header.AceFlags
381 & (CONTAINER_INHERIT_ACE | OBJECT_INHERIT_ACE))
eea4e482 382 && pc.isdir ())
19f20901 383 {
ab2dbccc
CV
384 if (type == USER_OBJ)
385 type = USER;
386 else if (type == GROUP_OBJ)
387 type = GROUP;
19f20901
CV
388 type |= ACL_DEFAULT;
389 types_def |= type;
390 if ((pos = searchace (lacl, MAX_ACL_ENTRIES, type, id)) >= 0)
391 getace (lacl[pos], type, id, ace->Mask, ace->Header.AceType);
392 }
c0d1968a 393 }
e445b7c3 394 if (types_def && (pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) >= 0)
c0d1968a 395 {
e445b7c3
CV
396 /* Ensure that the default acl contains at
397 least DEF_(USER|GROUP|OTHER)_OBJ entries. */
398 if (!(types_def & USER_OBJ))
399 {
400 lacl[pos].a_type = DEF_USER_OBJ;
401 lacl[pos].a_id = uid;
402 lacl[pos].a_perm = lacl[0].a_perm;
403 pos++;
404 }
405 if (!(types_def & GROUP_OBJ) && pos < MAX_ACL_ENTRIES)
406 {
407 lacl[pos].a_type = DEF_GROUP_OBJ;
408 lacl[pos].a_id = gid;
409 lacl[pos].a_perm = lacl[1].a_perm;
410 pos++;
411 }
412 if (!(types_def & OTHER_OBJ) && pos < MAX_ACL_ENTRIES)
413 {
414 lacl[pos].a_type = DEF_OTHER_OBJ;
415 lacl[pos].a_id = ILLEGAL_GID;
416 lacl[pos].a_perm = lacl[2].a_perm;
417 pos++;
418 }
419 /* Include DEF_CLASS_OBJ if any named default ace exists. */
420 if ((types_def & (USER|GROUP)) && pos < MAX_ACL_ENTRIES)
421 {
422 lacl[pos].a_type = DEF_CLASS_OBJ;
423 lacl[pos].a_id = ILLEGAL_GID;
424 lacl[pos].a_perm = S_IROTH | S_IWOTH | S_IXOTH;
425 }
c0d1968a
CV
426 }
427 }
428 if ((pos = searchace (lacl, MAX_ACL_ENTRIES, 0)) < 0)
429 pos = MAX_ACL_ENTRIES;
19f20901 430 if (aclbufp) {
62cd433e 431 if (owner_sid == group_sid)
19f20901
CV
432 lacl[0].a_perm = lacl[1].a_perm;
433 if (pos > nentries)
f1da8a06 434 {
9a751621 435 set_errno (ENOSPC);
f1da8a06
CV
436 return -1;
437 }
62cd433e 438 memcpy (aclbufp, lacl, pos * sizeof (__aclent32_t));
19f20901
CV
439 for (i = 0; i < pos; ++i)
440 aclbufp[i].a_perm &= ~(DENY_R | DENY_W | DENY_X);
62cd433e 441 aclsort32 (pos, 0, aclbufp);
19f20901 442 }
b9aa8149 443 syscall_printf ("%R = getacl(%S)", pos, pc.get_nt_native_path ());
c0d1968a
CV
444 return pos;
445}
446
f7382efe
CV
447extern "C" int
448acl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp)
c0d1968a 449{
e3d1d515 450 int res = -1;
f7382efe
CV
451
452 fhandler_base *fh = build_fh_name (path, PC_SYM_FOLLOW | PC_KEEP_HANDLE,
5a0d1edb 453 stat_suffixes);
60ecc3d6
CV
454 if (!fh || !fh->exists ())
455 set_errno (ENOENT);
456 else if (fh->error ())
c0d1968a 457 {
e3d1d515
CV
458 debug_printf ("got %d error from build_fh_name", fh->error ());
459 set_errno (fh->error ());
c0d1968a 460 }
e3d1d515
CV
461 else
462 res = fh->facl (cmd, nentries, aclbufp);
e84c7766
CV
463
464 delete fh;
b9aa8149 465 syscall_printf ("%R = acl(%s)", res, path);
e3d1d515 466 return res;
c0d1968a
CV
467}
468
c367dfd0 469extern "C" int
62cd433e 470lacl32 (const char *path, int cmd, int nentries, __aclent32_t *aclbufp)
c0d1968a 471{
f7382efe
CV
472 /* This call was an accident. Make it absolutely clear. */
473 set_errno (ENOSYS);
474 return -1;
c0d1968a
CV
475}
476
c367dfd0 477extern "C" int
62cd433e 478facl32 (int fd, int cmd, int nentries, __aclent32_t *aclbufp)
c0d1968a 479{
df63bd49
CF
480 cygheap_fdget cfd (fd);
481 if (cfd < 0)
c0d1968a
CV
482 {
483 syscall_printf ("-1 = facl (%d)", fd);
c0d1968a
CV
484 return -1;
485 }
e3d1d515 486 int res = cfd->facl (cmd, nentries, aclbufp);
b9aa8149 487 syscall_printf ("%R = facl(%s) )", res, cfd->get_name ());
e3d1d515 488 return res;
c0d1968a
CV
489}
490
c367dfd0 491extern "C" int
62cd433e 492aclcheck32 (__aclent32_t *aclbufp, int nentries, int *which)
c0d1968a 493{
2e008fb9
CF
494 bool has_user_obj = false;
495 bool has_group_obj = false;
496 bool has_other_obj = false;
497 bool has_class_obj = false;
498 bool has_ug_objs = false;
499 bool has_def_user_obj = false;
500 bool has_def_group_obj = false;
501 bool has_def_other_obj = false;
502 bool has_def_class_obj = false;
503 bool has_def_ug_objs = false;
c0d1968a
CV
504 int pos2;
505
506 for (int pos = 0; pos < nentries; ++pos)
507 switch (aclbufp[pos].a_type)
508 {
509 case USER_OBJ:
510 if (has_user_obj)
511 {
512 if (which)
513 *which = pos;
514 return USER_ERROR;
515 }
2e008fb9 516 has_user_obj = true;
c0d1968a
CV
517 break;
518 case GROUP_OBJ:
519 if (has_group_obj)
520 {
521 if (which)
522 *which = pos;
523 return GRP_ERROR;
524 }
2e008fb9 525 has_group_obj = true;
c0d1968a
CV
526 break;
527 case OTHER_OBJ:
528 if (has_other_obj)
529 {
530 if (which)
531 *which = pos;
532 return OTHER_ERROR;
533 }
2e008fb9 534 has_other_obj = true;
c0d1968a
CV
535 break;
536 case CLASS_OBJ:
537 if (has_class_obj)
538 {
539 if (which)
540 *which = pos;
541 return CLASS_ERROR;
542 }
2e008fb9 543 has_class_obj = true;
c0d1968a
CV
544 break;
545 case USER:
546 case GROUP:
547 if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
548 aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
549 {
550 if (which)
551 *which = pos2;
552 return DUPLICATE_ERROR;
553 }
2e008fb9 554 has_ug_objs = true;
c0d1968a
CV
555 break;
556 case DEF_USER_OBJ:
557 if (has_def_user_obj)
558 {
559 if (which)
560 *which = pos;
561 return USER_ERROR;
562 }
2e008fb9 563 has_def_user_obj = true;
c0d1968a
CV
564 break;
565 case DEF_GROUP_OBJ:
566 if (has_def_group_obj)
567 {
568 if (which)
569 *which = pos;
570 return GRP_ERROR;
571 }
2e008fb9 572 has_def_group_obj = true;
c0d1968a
CV
573 break;
574 case DEF_OTHER_OBJ:
575 if (has_def_other_obj)
576 {
577 if (which)
578 *which = pos;
579 return OTHER_ERROR;
580 }
2e008fb9 581 has_def_other_obj = true;
c0d1968a
CV
582 break;
583 case DEF_CLASS_OBJ:
584 if (has_def_class_obj)
585 {
586 if (which)
587 *which = pos;
588 return CLASS_ERROR;
589 }
2e008fb9 590 has_def_class_obj = true;
c0d1968a
CV
591 break;
592 case DEF_USER:
593 case DEF_GROUP:
594 if ((pos2 = searchace (aclbufp + pos + 1, nentries - pos - 1,
595 aclbufp[pos].a_type, aclbufp[pos].a_id)) >= 0)
596 {
597 if (which)
598 *which = pos2;
599 return DUPLICATE_ERROR;
600 }
2e008fb9 601 has_def_ug_objs = true;
c0d1968a
CV
602 break;
603 default:
604 return ENTRY_ERROR;
605 }
606 if (!has_user_obj
607 || !has_group_obj
608 || !has_other_obj
609#if 0
610 /* These checks are not ok yet since CLASS_OBJ isn't fully implemented. */
611 || (has_ug_objs && !has_class_obj)
612 || (has_def_ug_objs && !has_def_class_obj)
613#endif
614 )
615 {
616 if (which)
617 *which = -1;
618 return MISS_ERROR;
619 }
620 return 0;
621}
622
c367dfd0
CF
623static int
624acecmp (const void *a1, const void *a2)
c0d1968a 625{
62cd433e 626#define ace(i) ((const __aclent32_t *) a##i)
c90e1cf1 627 int ret = ace (1)->a_type - ace (2)->a_type;
c0d1968a 628 if (!ret)
c90e1cf1 629 ret = ace (1)->a_id - ace (2)->a_id;
c0d1968a
CV
630 return ret;
631#undef ace
632}
633
c367dfd0 634extern "C" int
62cd433e 635aclsort32 (int nentries, int, __aclent32_t *aclbufp)
c0d1968a 636{
62cd433e 637 if (aclcheck32 (aclbufp, nentries, NULL))
c0d1968a
CV
638 return -1;
639 if (!aclbufp || nentries < 1)
640 {
641 set_errno (EINVAL);
642 return -1;
643 }
62cd433e 644 qsort ((void *) aclbufp, nentries, sizeof (__aclent32_t), acecmp);
c0d1968a
CV
645 return 0;
646}
647
c367dfd0 648extern "C" int
62cd433e 649acltomode32 (__aclent32_t *aclbufp, int nentries, mode_t *modep)
c0d1968a
CV
650{
651 int pos;
652
653 if (!aclbufp || nentries < 1 || !modep)
654 {
655 set_errno (EINVAL);
656 return -1;
657 }
658 *modep = 0;
19f20901
CV
659 if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0
660 || !aclbufp[pos].a_type)
c0d1968a
CV
661 {
662 set_errno (EINVAL);
663 return -1;
664 }
19f20901
CV
665 *modep |= (aclbufp[pos].a_perm & S_IRWXO) << 6;
666 if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0
667 || !aclbufp[pos].a_type)
c0d1968a
CV
668 {
669 set_errno (EINVAL);
670 return -1;
671 }
19f20901
CV
672 *modep |= (aclbufp[pos].a_perm & S_IRWXO) << 3;
673 int cpos;
674 if ((cpos = searchace (aclbufp, nentries, CLASS_OBJ)) >= 0
675 && aclbufp[cpos].a_type == CLASS_OBJ)
676 *modep |= ((aclbufp[pos].a_perm & S_IRWXO) & aclbufp[cpos].a_perm) << 3;
677 if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0
678 || !aclbufp[pos].a_type)
c0d1968a
CV
679 {
680 set_errno (EINVAL);
681 return -1;
682 }
19f20901 683 *modep |= aclbufp[pos].a_perm & S_IRWXO;
c0d1968a
CV
684 return 0;
685}
686
c367dfd0 687extern "C" int
62cd433e 688aclfrommode32 (__aclent32_t *aclbufp, int nentries, mode_t *modep)
c0d1968a
CV
689{
690 int pos;
691
692 if (!aclbufp || nentries < 1 || !modep)
693 {
694 set_errno (EINVAL);
695 return -1;
696 }
19f20901
CV
697 if ((pos = searchace (aclbufp, nentries, USER_OBJ)) < 0
698 || !aclbufp[pos].a_type)
c0d1968a
CV
699 {
700 set_errno (EINVAL);
701 return -1;
702 }
19f20901
CV
703 aclbufp[pos].a_perm = (*modep & S_IRWXU) >> 6;
704 if ((pos = searchace (aclbufp, nentries, GROUP_OBJ)) < 0
705 || !aclbufp[pos].a_type)
c0d1968a
CV
706 {
707 set_errno (EINVAL);
708 return -1;
709 }
19f20901
CV
710 aclbufp[pos].a_perm = (*modep & S_IRWXG) >> 3;
711 if ((pos = searchace (aclbufp, nentries, CLASS_OBJ)) >= 0
712 && aclbufp[pos].a_type == CLASS_OBJ)
713 aclbufp[pos].a_perm = (*modep & S_IRWXG) >> 3;
714 if ((pos = searchace (aclbufp, nentries, OTHER_OBJ)) < 0
715 || !aclbufp[pos].a_type)
c0d1968a
CV
716 {
717 set_errno (EINVAL);
718 return -1;
719 }
19f20901 720 aclbufp[pos].a_perm = (*modep & S_IRWXO);
c0d1968a
CV
721 return 0;
722}
723
c367dfd0 724extern "C" int
62cd433e 725acltopbits32 (__aclent32_t *aclbufp, int nentries, mode_t *pbitsp)
c0d1968a 726{
62cd433e 727 return acltomode32 (aclbufp, nentries, pbitsp);
c0d1968a
CV
728}
729
c367dfd0 730extern "C" int
62cd433e 731aclfrompbits32 (__aclent32_t *aclbufp, int nentries, mode_t *pbitsp)
c0d1968a 732{
62cd433e 733 return aclfrommode32 (aclbufp, nentries, pbitsp);
c0d1968a
CV
734}
735
736static char *
737permtostr (mode_t perm)
738{
739 static char pbuf[4];
740
19f20901
CV
741 pbuf[0] = (perm & S_IROTH) ? 'r' : '-';
742 pbuf[1] = (perm & S_IWOTH) ? 'w' : '-';
743 pbuf[2] = (perm & S_IXOTH) ? 'x' : '-';
c0d1968a
CV
744 pbuf[3] = '\0';
745 return pbuf;
746}
747
c367dfd0 748extern "C" char *
62cd433e 749acltotext32 (__aclent32_t *aclbufp, int aclcnt)
c0d1968a
CV
750{
751 if (!aclbufp || aclcnt < 1 || aclcnt > MAX_ACL_ENTRIES
62cd433e 752 || aclcheck32 (aclbufp, aclcnt, NULL))
c0d1968a
CV
753 {
754 set_errno (EINVAL);
755 return NULL;
756 }
757 char buf[32000];
758 buf[0] = '\0';
2e008fb9 759 bool first = true;
c0d1968a
CV
760
761 for (int pos = 0; pos < aclcnt; ++pos)
762 {
763 if (!first)
764 strcat (buf, ",");
2e008fb9 765 first = false;
c0d1968a
CV
766 if (aclbufp[pos].a_type & ACL_DEFAULT)
767 strcat (buf, "default");
62e9d4b9 768 switch (aclbufp[pos].a_type & ~ACL_DEFAULT)
c0d1968a
CV
769 {
770 case USER_OBJ:
771 __small_sprintf (buf + strlen (buf), "user::%s",
772 permtostr (aclbufp[pos].a_perm));
773 break;
774 case USER:
775 __small_sprintf (buf + strlen (buf), "user:%d:%s",
776 aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
777 break;
778 case GROUP_OBJ:
779 __small_sprintf (buf + strlen (buf), "group::%s",
780 permtostr (aclbufp[pos].a_perm));
781 break;
782 case GROUP:
783 __small_sprintf (buf + strlen (buf), "group:%d:%s",
784 aclbufp[pos].a_id, permtostr (aclbufp[pos].a_perm));
785 break;
786 case CLASS_OBJ:
787 __small_sprintf (buf + strlen (buf), "mask::%s",
788 permtostr (aclbufp[pos].a_perm));
789 break;
790 case OTHER_OBJ:
791 __small_sprintf (buf + strlen (buf), "other::%s",
792 permtostr (aclbufp[pos].a_perm));
793 break;
794 default:
795 set_errno (EINVAL);
796 return NULL;
797 }
798 }
799 return strdup (buf);
800}
801
802static mode_t
803permfromstr (char *perm)
804{
805 mode_t mode = 0;
806
807 if (strlen (perm) != 3)
808 return 01000;
809 if (perm[0] == 'r')
19f20901 810 mode |= S_IROTH;
c0d1968a
CV
811 else if (perm[0] != '-')
812 return 01000;
813 if (perm[1] == 'w')
19f20901 814 mode |= S_IWOTH;
c0d1968a
CV
815 else if (perm[1] != '-')
816 return 01000;
817 if (perm[2] == 'x')
19f20901 818 mode |= S_IXOTH;
c0d1968a
CV
819 else if (perm[2] != '-')
820 return 01000;
821 return mode;
822}
823
c367dfd0 824extern "C" __aclent32_t *
62cd433e 825aclfromtext32 (char *acltextp, int *)
c0d1968a
CV
826{
827 if (!acltextp)
828 {
829 set_errno (EINVAL);
830 return NULL;
831 }
832 char buf[strlen (acltextp) + 1];
62cd433e 833 __aclent32_t lacl[MAX_ACL_ENTRIES];
c0d1968a
CV
834 memset (lacl, 0, sizeof lacl);
835 int pos = 0;
836 strcpy (buf, acltextp);
837 char *lasts;
838 for (char *c = strtok_r (buf, ",", &lasts);
839 c;
840 c = strtok_r (NULL, ",", &lasts))
841 {
842 if (!strncmp (c, "default", 7))
843 {
844 lacl[pos].a_type |= ACL_DEFAULT;
845 c += 7;
846 }
847 if (!strncmp (c, "user:", 5))
848 {
849 if (c[5] == ':')
850 lacl[pos].a_type |= USER_OBJ;
851 else
852 {
853 lacl[pos].a_type |= USER;
854 c += 5;
855 if (isalpha (*c))
856 {
d6ffc075 857 struct passwd *pw = internal_getpwnam (c);
c0d1968a
CV
858 if (!pw)
859 {
860 set_errno (EINVAL);
861 return NULL;
862 }
863 lacl[pos].a_id = pw->pw_uid;
f71f133b 864 c = strchrnul (c, ':');
c0d1968a
CV
865 }
866 else if (isdigit (*c))
867 lacl[pos].a_id = strtol (c, &c, 10);
62cd433e 868 if (*c != ':')
c0d1968a
CV
869 {
870 set_errno (EINVAL);
871 return NULL;
872 }
873 }
874 }
875 else if (!strncmp (c, "group:", 6))
876 {
877 if (c[5] == ':')
878 lacl[pos].a_type |= GROUP_OBJ;
879 else
880 {
881 lacl[pos].a_type |= GROUP;
882 c += 5;
883 if (isalpha (*c))
884 {
d6ffc075 885 struct __group32 *gr = internal_getgrnam (c);
c0d1968a
CV
886 if (!gr)
887 {
888 set_errno (EINVAL);
889 return NULL;
890 }
891 lacl[pos].a_id = gr->gr_gid;
f71f133b 892 c = strchrnul (c, ':');
c0d1968a
CV
893 }
894 else if (isdigit (*c))
895 lacl[pos].a_id = strtol (c, &c, 10);
62cd433e 896 if (*c != ':')
c0d1968a
CV
897 {
898 set_errno (EINVAL);
899 return NULL;
900 }
901 }
902 }
903 else if (!strncmp (c, "mask:", 5))
904 {
905 if (c[5] == ':')
906 lacl[pos].a_type |= CLASS_OBJ;
907 else
908 {
909 set_errno (EINVAL);
910 return NULL;
911 }
912 }
913 else if (!strncmp (c, "other:", 6))
914 {
915 if (c[5] == ':')
916 lacl[pos].a_type |= OTHER_OBJ;
917 else
918 {
919 set_errno (EINVAL);
920 return NULL;
921 }
922 }
923 if ((lacl[pos].a_perm = permfromstr (c)) == 01000)
924 {
925 set_errno (EINVAL);
926 return NULL;
927 }
928 ++pos;
929 }
62cd433e 930 __aclent32_t *aclp = (__aclent32_t *) malloc (pos * sizeof (__aclent32_t));
c0d1968a 931 if (aclp)
62cd433e 932 memcpy (aclp, lacl, pos * sizeof (__aclent32_t));
c0d1968a
CV
933 return aclp;
934}
935
62cd433e
CV
936/* __aclent16_t and __aclent32_t have same size and same member offsets */
937static __aclent32_t *
938acl16to32 (__aclent16_t *aclbufp, int nentries)
939{
940 __aclent32_t *aclbufp32 = (__aclent32_t *) aclbufp;
941 if (aclbufp32)
942 for (int i = 0; i < nentries; i++)
943 aclbufp32[i].a_id &= USHRT_MAX;
944 return aclbufp32;
945}
946
c367dfd0 947extern "C" int
62cd433e
CV
948acl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp)
949{
950 return acl32 (path, cmd, nentries, acl16to32 (aclbufp, nentries));
951}
952
c367dfd0 953extern "C" int
62cd433e
CV
954facl (int fd, int cmd, int nentries, __aclent16_t *aclbufp)
955{
956 return facl32 (fd, cmd, nentries, acl16to32 (aclbufp, nentries));
957}
958
c367dfd0 959extern "C" int
62cd433e
CV
960lacl (const char *path, int cmd, int nentries, __aclent16_t *aclbufp)
961{
f7382efe
CV
962 /* This call was an accident. Make it absolutely clear. */
963 set_errno (ENOSYS);
964 return -1;
62cd433e
CV
965}
966
c367dfd0 967extern "C" int
62cd433e
CV
968aclcheck (__aclent16_t *aclbufp, int nentries, int *which)
969{
970 return aclcheck32 (acl16to32 (aclbufp, nentries), nentries, which);
971}
972
c367dfd0 973extern "C" int
62cd433e
CV
974aclsort (int nentries, int i, __aclent16_t *aclbufp)
975{
976 return aclsort32 (nentries, i, acl16to32 (aclbufp, nentries));
977}
978
979
c367dfd0 980extern "C" int
62cd433e
CV
981acltomode (__aclent16_t *aclbufp, int nentries, mode_t *modep)
982{
983 return acltomode32 (acl16to32 (aclbufp, nentries), nentries, modep);
984}
985
c367dfd0 986extern "C" int
62cd433e
CV
987aclfrommode (__aclent16_t *aclbufp, int nentries, mode_t *modep)
988{
989 return aclfrommode32 ((__aclent32_t *)aclbufp, nentries, modep);
990}
991
c367dfd0 992extern "C" int
62cd433e
CV
993acltopbits (__aclent16_t *aclbufp, int nentries, mode_t *pbitsp)
994{
995 return acltopbits32 (acl16to32 (aclbufp, nentries), nentries, pbitsp);
996}
997
c367dfd0 998extern "C" int
62cd433e
CV
999aclfrompbits (__aclent16_t *aclbufp, int nentries, mode_t *pbitsp)
1000{
1001 return aclfrompbits32 ((__aclent32_t *)aclbufp, nentries, pbitsp);
1002}
1003
c367dfd0 1004extern "C" char *
62cd433e
CV
1005acltotext (__aclent16_t *aclbufp, int aclcnt)
1006{
1007 return acltotext32 (acl16to32 (aclbufp, aclcnt), aclcnt);
1008}
1009
c367dfd0 1010extern "C" __aclent16_t *
62cd433e
CV
1011aclfromtext (char *acltextp, int * aclcnt)
1012{
1013 return (__aclent16_t *) aclfromtext32 (acltextp, aclcnt);
1014}
This page took 0.516299 seconds and 5 git commands to generate.