Improved push_dir() error reporting.
[rsync/rsync.git] / acls.c
CommitLineData
1c3344a1
WD
1/*
2 * Handle passing Access Control Lists between systems.
3 *
4 * Copyright (C) 1996 Andrew Tridgell
5 * Copyright (C) 1996 Paul Mackerras
6 * Copyright (C) 2006 Wayne Davison
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street - Fifth Floor, Boston, MA 02110-1301, USA.
21 */
22
23#include "rsync.h"
24#include "lib/sysacls.h"
25
26#ifdef SUPPORT_ACLS
27
28extern int dry_run;
29extern int am_root;
30extern int read_only;
31extern int list_only;
32extern int orig_umask;
33extern int protocol_version;
34extern int numeric_ids;
35extern int inc_recurse;
36
37#define XMIT_USER_OBJ (1<<0)
38#define XMIT_USER_LIST (1<<1)
39#define XMIT_GROUP_OBJ (1<<2)
40#define XMIT_GROUP_LIST (1<<3)
41#define XMIT_MASK_OBJ (1<<4)
42#define XMIT_OTHER_OBJ (1<<5)
43
44/* === ACL structures === */
45
46typedef struct {
47 id_t id;
48 uchar access;
49} id_access;
50
51typedef struct {
52 id_access *idas;
53 int count;
54} ida_entries;
55
56typedef struct {
57 char *name;
58 uchar len;
59} idname;
60
61#define NO_ENTRY ((uchar)0x80)
62typedef struct rsync_acl {
63 ida_entries users;
64 ida_entries groups;
65 /* These will be NO_ENTRY if there's no such entry. */
66 uchar user_obj;
67 uchar group_obj;
68 uchar mask_obj;
69 uchar other_obj;
70} rsync_acl;
71
72typedef struct {
73 rsync_acl racl;
74 SMB_ACL_T sacl;
75} acl_duo;
76
77static const rsync_acl empty_rsync_acl = {
78 {NULL, 0}, {NULL, 0}, NO_ENTRY, NO_ENTRY, NO_ENTRY, NO_ENTRY
79};
80
81static item_list access_acl_list = EMPTY_ITEM_LIST;
82static item_list default_acl_list = EMPTY_ITEM_LIST;
83
84/* === Calculations on ACL types === */
85
86static const char *str_acl_type(SMB_ACL_TYPE_T type)
87{
88 return type == SMB_ACL_TYPE_ACCESS ? "SMB_ACL_TYPE_ACCESS"
89 : type == SMB_ACL_TYPE_DEFAULT ? "SMB_ACL_TYPE_DEFAULT"
90 : "unknown SMB_ACL_TYPE_T";
91}
92
93static int calc_sacl_entries(const rsync_acl *racl)
94{
95 /* A System ACL always gets user/group/other permission entries. */
96 return racl->users.count + racl->groups.count
97#ifdef ACLS_NEED_MASK
98 + 4;
99#else
100 + (racl->mask_obj != NO_ENTRY) + 3;
101#endif
102}
103
104/* Extracts and returns the permission bits from the ACL. This cannot be
105 * called on an rsync_acl that has NO_ENTRY in any spot but the mask. */
106static int rsync_acl_get_perms(const rsync_acl *racl)
107{
108 return (racl->user_obj << 6)
109 + ((racl->mask_obj != NO_ENTRY ? racl->mask_obj : racl->group_obj) << 3)
110 + racl->other_obj;
111}
112
113/* Removes the permission-bit entries from the ACL because these
114 * can be reconstructed from the file's mode. */
115static void rsync_acl_strip_perms(rsync_acl *racl)
116{
117 racl->user_obj = NO_ENTRY;
118 if (racl->mask_obj == NO_ENTRY)
119 racl->group_obj = NO_ENTRY;
120 else {
121 if (racl->group_obj == racl->mask_obj)
122 racl->group_obj = NO_ENTRY;
123 racl->mask_obj = NO_ENTRY;
124 }
125 racl->other_obj = NO_ENTRY;
126}
127
128/* Given an empty rsync_acl, fake up the permission bits. */
129static void rsync_acl_fake_perms(rsync_acl *racl, mode_t mode)
130{
131 racl->user_obj = (mode >> 6) & 7;
132 racl->group_obj = (mode >> 3) & 7;
133 racl->other_obj = mode & 7;
134}
135
136/* === Rsync ACL functions === */
137
138static rsync_acl *create_racl(void)
139{
140 rsync_acl *racl = new(rsync_acl);
141
142 if (!racl)
143 out_of_memory("create_racl");
144 *racl = empty_rsync_acl;
145
146 return racl;
147}
148
149static BOOL ida_entries_equal(const ida_entries *ial1, const ida_entries *ial2)
150{
151 id_access *ida1, *ida2;
152 int count = ial1->count;
153 if (count != ial2->count)
154 return False;
155 ida1 = ial1->idas;
156 ida2 = ial2->idas;
157 for (; count--; ida1++, ida2++) {
158 if (ida1->access != ida2->access || ida1->id != ida2->id)
159 return False;
160 }
161 return True;
162}
163
164static BOOL rsync_acl_equal(const rsync_acl *racl1, const rsync_acl *racl2)
165{
166 return racl1->user_obj == racl2->user_obj
167 && racl1->group_obj == racl2->group_obj
168 && racl1->mask_obj == racl2->mask_obj
169 && racl1->other_obj == racl2->other_obj
170 && ida_entries_equal(&racl1->users, &racl2->users)
171 && ida_entries_equal(&racl1->groups, &racl2->groups);
172}
173
174/* Are the extended (non-permission-bit) entries equal? If so, the rest of
175 * the ACL will be handled by the normal mode-preservation code. This is
176 * only meaningful for access ACLs! Note: the 1st arg is a fully-populated
177 * rsync_acl, but the 2nd parameter can be a condensed rsync_acl, which means
178 * that it might have several of its permission objects set to NO_ENTRY. */
179static BOOL rsync_acl_equal_enough(const rsync_acl *racl1,
180 const rsync_acl *racl2, mode_t m)
181{
182 if ((racl1->mask_obj ^ racl2->mask_obj) & NO_ENTRY)
183 return False; /* One has a mask and the other doesn't */
184
185 /* When there's a mask, the group_obj becomes an extended entry. */
186 if (racl1->mask_obj != NO_ENTRY) {
187 /* A condensed rsync_acl with a mask can only have no
188 * group_obj when it was identical to the mask. This
189 * means that it was also identical to the group attrs
190 * from the mode. */
191 if (racl2->group_obj == NO_ENTRY) {
192 if (racl1->group_obj != ((m >> 3) & 7))
193 return False;
194 } else if (racl1->group_obj != racl2->group_obj)
195 return False;
196 }
197 return ida_entries_equal(&racl1->users, &racl2->users)
198 && ida_entries_equal(&racl1->groups, &racl2->groups);
199}
200
201static void rsync_acl_free(rsync_acl *racl)
202{
203 if (racl->users.idas)
204 free(racl->users.idas);
205 if (racl->groups.idas)
206 free(racl->groups.idas);
207 *racl = empty_rsync_acl;
208}
209
210void free_acl(statx *sxp)
211{
212 if (sxp->acc_acl) {
213 rsync_acl_free(sxp->acc_acl);
214 free(sxp->acc_acl);
215 sxp->acc_acl = NULL;
216 }
217 if (sxp->def_acl) {
218 rsync_acl_free(sxp->def_acl);
219 free(sxp->def_acl);
220 sxp->def_acl = NULL;
221 }
222}
223
224static int id_access_sorter(const void *r1, const void *r2)
225{
226 id_access *ida1 = (id_access *)r1;
227 id_access *ida2 = (id_access *)r2;
228 id_t rid1 = ida1->id, rid2 = ida2->id;
229 return rid1 == rid2 ? 0 : rid1 < rid2 ? -1 : 1;
230}
231
232static void sort_ida_entries(ida_entries *idal)
233{
234 if (!idal->count)
235 return;
236 qsort(idal->idas, idal->count, sizeof idal->idas[0], id_access_sorter);
237}
238
239/* === System ACLs === */
240
241/* Transfer the count id_access items out of the temp_ida_list into either
242 * the users or groups ida_entries list in racl. */
243static void save_idas(rsync_acl *racl, SMB_ACL_TAG_T type, item_list *temp_ida_list)
244{
245 id_access *idas;
246 ida_entries *ent;
247
248 if (temp_ida_list->count) {
249 int cnt = temp_ida_list->count;
250 id_access *temp_idas = temp_ida_list->items;
251 if (!(idas = new_array(id_access, cnt)))
252 out_of_memory("save_idas");
253 memcpy(idas, temp_idas, cnt * sizeof *temp_idas);
254 } else
255 idas = NULL;
256
257 ent = type == SMB_ACL_USER ? &racl->users : &racl->groups;
258
259 if (ent->count) {
260 rprintf(FERROR, "save_idas: disjoint list found for type %d\n", type);
261 exit_cleanup(RERR_UNSUPPORTED);
262 }
263 ent->count = temp_ida_list->count;
264 ent->idas = idas;
265
266 /* Truncate the temporary list now that its idas have been saved. */
267 temp_ida_list->count = 0;
268}
269
270/* Unpack system ACL -> rsync ACL verbatim. Return whether we succeeded. */
271static BOOL unpack_smb_acl(SMB_ACL_T sacl, rsync_acl *racl)
272{
273 static item_list temp_ida_list = EMPTY_ITEM_LIST;
274 SMB_ACL_TAG_T prior_list_type = 0;
275 SMB_ACL_ENTRY_T entry;
276 const char *errfun;
277 int rc;
278
279 errfun = "sys_acl_get_entry";
280 for (rc = sys_acl_get_entry(sacl, SMB_ACL_FIRST_ENTRY, &entry);
281 rc == 1;
282 rc = sys_acl_get_entry(sacl, SMB_ACL_NEXT_ENTRY, &entry)) {
283 SMB_ACL_TAG_T tag_type;
284 SMB_ACL_PERMSET_T permset;
285 uchar access;
286 void *qualifier;
287 id_access *ida;
288 if ((rc = sys_acl_get_tag_type(entry, &tag_type))) {
289 errfun = "sys_acl_get_tag_type";
290 break;
291 }
292 if ((rc = sys_acl_get_permset(entry, &permset))) {
293 errfun = "sys_acl_get_tag_type";
294 break;
295 }
296 access = (sys_acl_get_perm(permset, SMB_ACL_READ) ? 4 : 0)
297 | (sys_acl_get_perm(permset, SMB_ACL_WRITE) ? 2 : 0)
298 | (sys_acl_get_perm(permset, SMB_ACL_EXECUTE) ? 1 : 0);
299 /* continue == done with entry; break == store in temporary ida list */
300 switch (tag_type) {
301 case SMB_ACL_USER_OBJ:
302 if (racl->user_obj == NO_ENTRY)
303 racl->user_obj = access;
304 else
305 rprintf(FINFO, "unpack_smb_acl: warning: duplicate USER_OBJ entry ignored\n");
306 continue;
307 case SMB_ACL_USER:
308 break;
309 case SMB_ACL_GROUP_OBJ:
310 if (racl->group_obj == NO_ENTRY)
311 racl->group_obj = access;
312 else
313 rprintf(FINFO, "unpack_smb_acl: warning: duplicate GROUP_OBJ entry ignored\n");
314 continue;
315 case SMB_ACL_GROUP:
316 break;
317 case SMB_ACL_MASK:
318 if (racl->mask_obj == NO_ENTRY)
319 racl->mask_obj = access;
320 else
321 rprintf(FINFO, "unpack_smb_acl: warning: duplicate MASK entry ignored\n");
322 continue;
323 case SMB_ACL_OTHER:
324 if (racl->other_obj == NO_ENTRY)
325 racl->other_obj = access;
326 else
327 rprintf(FINFO, "unpack_smb_acl: warning: duplicate OTHER entry ignored\n");
328 continue;
329 default:
330 rprintf(FINFO, "unpack_smb_acl: warning: entry with unrecognized tag type ignored\n");
331 continue;
332 }
333 if (!(qualifier = sys_acl_get_qualifier(entry))) {
334 errfun = "sys_acl_get_tag_type";
335 rc = EINVAL;
336 break;
337 }
338 if (tag_type != prior_list_type) {
339 if (prior_list_type)
340 save_idas(racl, prior_list_type, &temp_ida_list);
341 prior_list_type = tag_type;
342 }
343 ida = EXPAND_ITEM_LIST(&temp_ida_list, id_access, -10);
344 ida->id = *((id_t *)qualifier);
345 ida->access = access;
346 sys_acl_free_qualifier(qualifier, tag_type);
347 }
348 if (rc) {
349 rsyserr(FERROR, errno, "unpack_smb_acl: %s()", errfun);
350 rsync_acl_free(racl);
351 return False;
352 }
353 if (prior_list_type)
354 save_idas(racl, prior_list_type, &temp_ida_list);
355
356 sort_ida_entries(&racl->users);
357 sort_ida_entries(&racl->groups);
358
359#ifdef ACLS_NEED_MASK
360 if (!racl->users.count && !racl->groups.count && racl->mask_obj != NO_ENTRY) {
361 /* Throw away a superfluous mask, but mask off the
362 * group perms with it first. */
363 racl->group_obj &= racl->mask_obj;
364 racl->mask_obj = NO_ENTRY;
365 }
366#endif
367
368 return True;
369}
370
371/* Synactic sugar for system calls */
372
373#define CALL_OR_ERROR(func,args,str) \
374 do { \
375 if (func args) { \
376 errfun = str; \
377 goto error_exit; \
378 } \
379 } while (0)
380
381#define COE(func,args) CALL_OR_ERROR(func,args,#func)
382#define COE2(func,args) CALL_OR_ERROR(func,args,NULL)
383
384/* Store the permissions in the system ACL entry. */
385static int store_access_in_entry(uchar access, SMB_ACL_ENTRY_T entry)
386{
387 const char *errfun = NULL;
388 SMB_ACL_PERMSET_T permset;
389
390 COE( sys_acl_get_permset,(entry, &permset) );
391 COE( sys_acl_clear_perms,(permset) );
392 if (access & 4)
393 COE( sys_acl_add_perm,(permset, SMB_ACL_READ) );
394 if (access & 2)
395 COE( sys_acl_add_perm,(permset, SMB_ACL_WRITE) );
396 if (access & 1)
397 COE( sys_acl_add_perm,(permset, SMB_ACL_EXECUTE) );
398 COE( sys_acl_set_permset,(entry, permset) );
399
400 return 0;
401
402 error_exit:
403 rsyserr(FERROR, errno, "store_access_in_entry %s()", errfun);
404 return -1;
405}
406
407/* Pack rsync ACL -> system ACL verbatim. Return whether we succeeded. */
408static BOOL pack_smb_acl(SMB_ACL_T *smb_acl, const rsync_acl *racl)
409{
410#ifdef ACLS_NEED_MASK
411 uchar mask_bits;
412#endif
413 size_t count;
414 id_access *ida;
415 const char *errfun = NULL;
416 SMB_ACL_ENTRY_T entry;
417
418 if (!(*smb_acl = sys_acl_init(calc_sacl_entries(racl)))) {
419 rsyserr(FERROR, errno, "pack_smb_acl: sys_acl_init()");
420 return False;
421 }
422
423 COE( sys_acl_create_entry,(smb_acl, &entry) );
424 COE( sys_acl_set_tag_type,(entry, SMB_ACL_USER_OBJ) );
425 COE2( store_access_in_entry,(racl->user_obj & 7, entry) );
426
427 for (ida = racl->users.idas, count = racl->users.count; count--; ida++) {
428 COE( sys_acl_create_entry,(smb_acl, &entry) );
429 COE( sys_acl_set_tag_type,(entry, SMB_ACL_USER) );
430 COE( sys_acl_set_qualifier,(entry, (void*)&ida->id) );
431 COE2( store_access_in_entry,(ida->access, entry) );
432 }
433
434 COE( sys_acl_create_entry,(smb_acl, &entry) );
435 COE( sys_acl_set_tag_type,(entry, SMB_ACL_GROUP_OBJ) );
436 COE2( store_access_in_entry,(racl->group_obj & 7, entry) );
437
438 for (ida = racl->groups.idas, count = racl->groups.count; count--; ida++) {
439 COE( sys_acl_create_entry,(smb_acl, &entry) );
440 COE( sys_acl_set_tag_type,(entry, SMB_ACL_GROUP) );
441 COE( sys_acl_set_qualifier,(entry, (void*)&ida->id) );
442 COE2( store_access_in_entry,(ida->access, entry) );
443 }
444
445#ifdef ACLS_NEED_MASK
446 mask_bits = racl->mask_obj == NO_ENTRY ? racl->group_obj & 7 : racl->mask_obj;
447 COE( sys_acl_create_entry,(smb_acl, &entry) );
448 COE( sys_acl_set_tag_type,(entry, SMB_ACL_MASK) );
449 COE2( store_access_in_entry,(mask_bits, entry) );
450#else
451 if (racl->mask_obj != NO_ENTRY) {
452 COE( sys_acl_create_entry,(smb_acl, &entry) );
453 COE( sys_acl_set_tag_type,(entry, SMB_ACL_MASK) );
454 COE2( store_access_in_entry,(racl->mask_obj, entry) );
455 }
456#endif
457
458 COE( sys_acl_create_entry,(smb_acl, &entry) );
459 COE( sys_acl_set_tag_type,(entry, SMB_ACL_OTHER) );
460 COE2( store_access_in_entry,(racl->other_obj & 7, entry) );
461
462#ifdef DEBUG
463 if (sys_acl_valid(*smb_acl) < 0)
464 rprintf(FERROR, "pack_smb_acl: warning: system says the ACL I packed is invalid\n");
465#endif
466
467 return True;
468
469 error_exit:
470 if (errfun) {
471 rsyserr(FERROR, errno, "pack_smb_acl %s()", errfun);
472 }
473 sys_acl_free_acl(*smb_acl);
474 return False;
475}
476
477static int find_matching_rsync_acl(const rsync_acl *racl, SMB_ACL_TYPE_T type,
478 const item_list *racl_list)
479{
480 static int access_match = -1, default_match = -1;
481 int *match = type == SMB_ACL_TYPE_ACCESS ? &access_match : &default_match;
482 size_t count = racl_list->count;
483
484 /* If this is the first time through or we didn't match the last
485 * time, then start at the end of the list, which should be the
486 * best place to start hunting. */
487 if (*match == -1)
488 *match = racl_list->count - 1;
489 while (count--) {
490 rsync_acl *base = racl_list->items;
491 if (rsync_acl_equal(base + *match, racl))
492 return *match;
493 if (!(*match)--)
494 *match = racl_list->count - 1;
495 }
496
497 *match = -1;
498 return *match;
499}
500
501static int get_rsync_acl(const char *fname, rsync_acl *racl,
502 SMB_ACL_TYPE_T type, mode_t mode)
503{
504 SMB_ACL_T sacl = sys_acl_get_file(fname, type);
505
506 if (sacl) {
507 BOOL ok = unpack_smb_acl(sacl, racl);
508
509 sys_acl_free_acl(sacl);
510 if (!ok) {
511 return -1;
512 }
d4a013ed 513 } else if (no_acl_syscall_error(errno)) {
1c3344a1
WD
514 /* ACLs are not supported, so pretend we have a basic ACL. */
515 if (type == SMB_ACL_TYPE_ACCESS)
516 rsync_acl_fake_perms(racl, mode);
517 } else {
518 rsyserr(FERROR, errno, "get_acl: sys_acl_get_file(%s, %s)",
519 fname, str_acl_type(type));
520 return -1;
521 }
522
523 return 0;
524}
525
526/* Return the Access Control List for the given filename. */
527int get_acl(const char *fname, statx *sxp)
528{
529 sxp->acc_acl = create_racl();
530 if (get_rsync_acl(fname, sxp->acc_acl, SMB_ACL_TYPE_ACCESS,
531 sxp->st.st_mode) < 0) {
532 free_acl(sxp);
533 return -1;
534 }
535
536 if (S_ISDIR(sxp->st.st_mode)) {
537 sxp->def_acl = create_racl();
538 if (get_rsync_acl(fname, sxp->def_acl, SMB_ACL_TYPE_DEFAULT,
539 sxp->st.st_mode) < 0) {
540 free_acl(sxp);
541 return -1;
542 }
543 }
544
545 return 0;
546}
547
548/* === Send functions === */
549
550/* The general strategy with the tag_type <-> character mapping is that
551 * lowercase implies that no qualifier follows, where uppercase does.
552 * A similar idiom for the ACL type (access or default) itself, but
553 * lowercase in this instance means there's no ACL following, so the
554 * ACL is a repeat, so the receiver should reuse the last of the same
555 * type ACL. */
556
557/* Send the ida list over the file descriptor. */
558static void send_ida_entries(const ida_entries *idal, int user_names, int f)
559{
560 id_access *ida;
561 size_t count = idal->count;
562
563 write_abbrevint(f, idal->count);
564
565 for (ida = idal->idas; count--; ida++) {
566 char *name = user_names ? add_uid(ida->id) : add_gid(ida->id);
567 write_abbrevint(f, ida->id);
568 if (inc_recurse && name) {
569 int len = strlen(name);
570 write_byte(f, ida->access | (uchar)0x80);
571 write_byte(f, len);
572 write_buf(f, name, len);
573 } else
574 write_byte(f, ida->access);
575 }
576}
577
578static void send_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type,
579 item_list *racl_list, int f)
580{
581 int ndx = find_matching_rsync_acl(racl, type, racl_list);
582
583 /* Send 0 (-1 + 1) to indicate that literal ACL data follows. */
584 write_abbrevint(f, ndx + 1);
585
586 if (ndx < 0) {
587 rsync_acl *new_racl = EXPAND_ITEM_LIST(racl_list, rsync_acl, 1000);
588 uchar flags = 0;
589
590 if (racl->user_obj != NO_ENTRY)
591 flags |= XMIT_USER_OBJ;
592 if (racl->users.count)
593 flags |= XMIT_USER_LIST;
594
595 if (racl->group_obj != NO_ENTRY)
596 flags |= XMIT_GROUP_OBJ;
597 if (racl->groups.count)
598 flags |= XMIT_GROUP_LIST;
599
600 if (racl->mask_obj != NO_ENTRY)
601 flags |= XMIT_MASK_OBJ;
602
603 if (racl->other_obj != NO_ENTRY)
604 flags |= XMIT_OTHER_OBJ;
605
606 write_byte(f, flags);
607
608 if (flags & XMIT_USER_OBJ)
609 write_byte(f, racl->user_obj);
610 if (flags & XMIT_USER_LIST)
611 send_ida_entries(&racl->users, 1, f);
612
613 if (flags & XMIT_GROUP_OBJ)
614 write_byte(f, racl->group_obj);
615 if (flags & XMIT_GROUP_LIST)
616 send_ida_entries(&racl->groups, 0, f);
617
618 if (flags & XMIT_MASK_OBJ)
619 write_byte(f, racl->mask_obj);
620
621 if (flags & XMIT_OTHER_OBJ)
622 write_byte(f, racl->other_obj);
623
624 /* Give the allocated data to the new list object. */
625 *new_racl = *racl;
626 *racl = empty_rsync_acl;
627 }
628}
629
630/* Send the ACL from the statx structure down the indicated file descriptor.
631 * This also frees the ACL data. */
632void send_acl(statx *sxp, int f)
633{
1c3344a1
WD
634 if (!sxp->acc_acl) {
635 sxp->acc_acl = create_racl();
636 rsync_acl_fake_perms(sxp->acc_acl, sxp->st.st_mode);
637 }
638 /* Avoid sending values that can be inferred from other data. */
639 rsync_acl_strip_perms(sxp->acc_acl);
640
641 send_rsync_acl(sxp->acc_acl, SMB_ACL_TYPE_ACCESS, &access_acl_list, f);
642
643 if (S_ISDIR(sxp->st.st_mode)) {
644 if (!sxp->def_acl)
645 sxp->def_acl = create_racl();
646
647 send_rsync_acl(sxp->def_acl, SMB_ACL_TYPE_DEFAULT, &default_acl_list, f);
648 }
649}
650
651/* === Receive functions === */
652
653static uchar recv_acl_access(uchar *name_follows_val, int f)
654{
655 uchar access = read_byte(f);
656
657 if (name_follows_val) {
658 if (access & (uchar)0x80) {
659 access &= ~(uchar)0x80;
660 *name_follows_val = 1;
661 } else
662 *name_follows_val = 0;
663 }
664
665 if (access & ~(4 | 2 | 1)) {
666 rprintf(FERROR, "recv_acl_access: bogus permset %o\n", access);
667 exit_cleanup(RERR_STREAMIO);
668 }
669
670 return access;
671}
672
673static uchar recv_ida_entries(ida_entries *ent, int user_names, int f)
674{
675 uchar computed_mask_bits = 0;
676 uchar has_name;
677 int i, count = read_abbrevint(f);
678
679 if (count) {
680 if (!(ent->idas = new_array(id_access, ent->count)))
681 out_of_memory("recv_ida_entries");
682 } else
683 ent->idas = NULL;
684
685 ent->count = count;
686
687 for (i = 0; i < count; i++) {
688 id_t id = read_abbrevint(f);
689 int access = recv_acl_access(&has_name, f);
690
691 if (has_name) {
692 if (user_names)
693 id = recv_user_name(f, id);
694 else
695 id = recv_group_name(f, id);
696 } else if (user_names) {
697 if (inc_recurse && am_root && !numeric_ids)
698 id = match_uid(id);
699 } else {
700 if (inc_recurse && (!am_root || !numeric_ids))
701 id = match_gid(id);
702 }
703
704 ent->idas[i].id = id;
705 ent->idas[i].access = access;
706 computed_mask_bits |= access;
707 }
708
709 return computed_mask_bits;
710}
711
712static int recv_rsync_acl(item_list *racl_list, SMB_ACL_TYPE_T type, int f)
713{
714 uchar computed_mask_bits = 0;
715 acl_duo *duo_item;
716 uchar flags;
717 int ndx = read_abbrevint(f);
718
719 if (ndx < 0 || (size_t)ndx > racl_list->count) {
720 rprintf(FERROR, "recv_acl_index: %s ACL index %d > %d\n",
e5abce8e 721 str_acl_type(type), ndx, (int)racl_list->count);
1c3344a1
WD
722 exit_cleanup(RERR_STREAMIO);
723 }
724
725 if (ndx != 0)
726 return ndx - 1;
727
728 ndx = racl_list->count;
729 duo_item = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
730 duo_item->racl = empty_rsync_acl;
731
732 flags = read_byte(f);
733
734 if (flags & XMIT_USER_OBJ)
735 duo_item->racl.user_obj = recv_acl_access(NULL, f);
736
737 if (flags & XMIT_USER_LIST)
738 computed_mask_bits |= recv_ida_entries(&duo_item->racl.users, 1, f);
739
740 if (flags & XMIT_GROUP_OBJ)
741 duo_item->racl.group_obj = recv_acl_access(NULL, f);
742
743 if (flags & XMIT_GROUP_LIST)
744 computed_mask_bits |= recv_ida_entries(&duo_item->racl.groups, 0, f);
745
746 if (flags & XMIT_MASK_OBJ)
747 duo_item->racl.mask_obj = recv_acl_access(NULL, f);
748
749 if (flags & XMIT_OTHER_OBJ)
750 duo_item->racl.other_obj = recv_acl_access(NULL, f);
751
752 if (!duo_item->racl.users.count && !duo_item->racl.groups.count) {
753 /* If we received a superfluous mask, throw it away. */
754 if (duo_item->racl.mask_obj != NO_ENTRY) {
755 /* Mask off the group perms with it first. */
756 duo_item->racl.group_obj &= duo_item->racl.mask_obj | NO_ENTRY;
757 duo_item->racl.mask_obj = NO_ENTRY;
758 }
759 } else if (duo_item->racl.mask_obj == NO_ENTRY) /* Must be non-empty with lists. */
760 duo_item->racl.mask_obj = computed_mask_bits | (duo_item->racl.group_obj & 7);
761
762 duo_item->sacl = NULL;
763
764 return ndx;
765}
766
767/* Receive the ACL info the sender has included for this file-list entry. */
768void receive_acl(struct file_struct *file, int f)
769{
770 F_ACL(file) = recv_rsync_acl(&access_acl_list, SMB_ACL_TYPE_ACCESS, f);
771
772 if (S_ISDIR(file->mode))
773 F_DEF_ACL(file) = recv_rsync_acl(&default_acl_list, SMB_ACL_TYPE_DEFAULT, f);
774}
775
776static int cache_rsync_acl(rsync_acl *racl, SMB_ACL_TYPE_T type, item_list *racl_list)
777{
778 int ndx;
779
780 if (!racl)
781 ndx = -1;
782 else if ((ndx = find_matching_rsync_acl(racl, type, racl_list)) == -1) {
783 acl_duo *new_duo;
784 ndx = racl_list->count;
785 new_duo = EXPAND_ITEM_LIST(racl_list, acl_duo, 1000);
786 new_duo->racl = *racl;
787 new_duo->sacl = NULL;
788 *racl = empty_rsync_acl;
789 }
790
791 return ndx;
792}
793
794/* Turn the ACL data in statx into cached ACL data, setting the index
795 * values in the file struct. */
796void cache_acl(struct file_struct *file, statx *sxp)
797{
798 F_ACL(file) = cache_rsync_acl(sxp->acc_acl,
799 SMB_ACL_TYPE_ACCESS, &access_acl_list);
800
801 if (S_ISDIR(sxp->st.st_mode)) {
802 F_DEF_ACL(file) = cache_rsync_acl(sxp->def_acl,
803 SMB_ACL_TYPE_DEFAULT, &default_acl_list);
804 }
805}
806
807static mode_t change_sacl_perms(SMB_ACL_T sacl, rsync_acl *racl, mode_t old_mode, mode_t mode)
808{
809 SMB_ACL_ENTRY_T entry;
810 const char *errfun;
811 int rc;
812
813 if (S_ISDIR(mode)) {
814 /* If the sticky bit is going on, it's not safe to allow all
815 * the new ACL to go into effect before it gets set. */
816#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
817 if (mode & S_ISVTX)
818 mode &= ~0077;
819#else
820 if (mode & S_ISVTX && !(old_mode & S_ISVTX))
821 mode &= ~0077;
822 } else {
823 /* If setuid or setgid is going off, it's not safe to allow all
824 * the new ACL to go into effect before they get cleared. */
825 if ((old_mode & S_ISUID && !(mode & S_ISUID))
826 || (old_mode & S_ISGID && !(mode & S_ISGID)))
827 mode &= ~0077;
828#endif
829 }
830
831 errfun = "sys_acl_get_entry";
832 for (rc = sys_acl_get_entry(sacl, SMB_ACL_FIRST_ENTRY, &entry);
833 rc == 1;
834 rc = sys_acl_get_entry(sacl, SMB_ACL_NEXT_ENTRY, &entry)) {
835 SMB_ACL_TAG_T tag_type;
836 if ((rc = sys_acl_get_tag_type(entry, &tag_type))) {
837 errfun = "sys_acl_get_tag_type";
838 break;
839 }
840 switch (tag_type) {
841 case SMB_ACL_USER_OBJ:
842 COE2( store_access_in_entry,((mode >> 6) & 7, entry) );
843 break;
844 case SMB_ACL_GROUP_OBJ:
845 /* group is only empty when identical to group perms. */
846 if (racl->group_obj != NO_ENTRY)
847 break;
848 COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
849 break;
850 case SMB_ACL_MASK:
851#ifndef ACLS_NEED_MASK
852 /* mask is only empty when we don't need it. */
853 if (racl->mask_obj == NO_ENTRY)
854 break;
855#endif
856 COE2( store_access_in_entry,((mode >> 3) & 7, entry) );
857 break;
858 case SMB_ACL_OTHER:
859 COE2( store_access_in_entry,(mode & 7, entry) );
860 break;
861 }
862 }
863 if (rc) {
864 error_exit:
865 if (errfun) {
866 rsyserr(FERROR, errno, "change_sacl_perms: %s()",
867 errfun);
868 }
869 return (mode_t)~0;
870 }
871
872#ifdef SMB_ACL_LOSES_SPECIAL_MODE_BITS
873 /* Ensure that chmod() will be called to restore any lost setid bits. */
874 if (old_mode & (S_ISUID | S_ISGID | S_ISVTX)
875 && BITS_EQUAL(old_mode, mode, CHMOD_BITS))
876 old_mode &= ~(S_ISUID | S_ISGID | S_ISVTX);
877#endif
878
879 /* Return the mode of the file on disk, as we will set them. */
880 return (old_mode & ~ACCESSPERMS) | (mode & ACCESSPERMS);
881}
882
883static int set_rsync_acl(const char *fname, acl_duo *duo_item,
884 SMB_ACL_TYPE_T type, statx *sxp, mode_t mode)
885{
886 if (type == SMB_ACL_TYPE_DEFAULT
887 && duo_item->racl.user_obj == NO_ENTRY) {
888 if (sys_acl_delete_def_file(fname) < 0) {
889 rsyserr(FERROR, errno, "set_acl: sys_acl_delete_def_file(%s)",
890 fname);
891 return -1;
892 }
893 } else {
894 mode_t cur_mode = sxp->st.st_mode;
895 if (!duo_item->sacl
896 && !pack_smb_acl(&duo_item->sacl, &duo_item->racl))
897 return -1;
898 if (type == SMB_ACL_TYPE_ACCESS) {
899 cur_mode = change_sacl_perms(duo_item->sacl, &duo_item->racl,
900 cur_mode, mode);
901 if (cur_mode == (mode_t)~0)
902 return 0;
903 }
904 if (sys_acl_set_file(fname, type, duo_item->sacl) < 0) {
905 rsyserr(FERROR, errno, "set_acl: sys_acl_set_file(%s, %s)",
906 fname, str_acl_type(type));
907 return -1;
908 }
909 if (type == SMB_ACL_TYPE_ACCESS)
910 sxp->st.st_mode = cur_mode;
911 }
912
913 return 0;
914}
915
916/* Set ACL on indicated filename.
917 *
918 * This sets extended access ACL entries and default ACL. If convenient,
919 * it sets permission bits along with the access ACL and signals having
920 * done so by modifying sxp->st.st_mode.
921 *
922 * Returns 1 for unchanged, 0 for changed, -1 for failed. Call this
923 * with fname set to NULL to just check if the ACL is unchanged. */
924int set_acl(const char *fname, const struct file_struct *file, statx *sxp)
925{
926 int unchanged = 1;
927 int32 ndx;
928 BOOL eq;
929
930 if (!dry_run && (read_only || list_only)) {
931 errno = EROFS;
932 return -1;
933 }
934
935 ndx = F_ACL(file);
936 if (ndx >= 0 && (size_t)ndx < access_acl_list.count) {
937 acl_duo *duo_item = access_acl_list.items;
938 duo_item += ndx;
939 eq = sxp->acc_acl
940 && rsync_acl_equal_enough(sxp->acc_acl, &duo_item->racl, file->mode);
941 if (!eq) {
942 unchanged = 0;
943 if (!dry_run && fname
944 && set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_ACCESS,
945 sxp, file->mode) < 0)
946 unchanged = -1;
947 }
948 }
949
950 if (!S_ISDIR(sxp->st.st_mode))
951 return unchanged;
952
953 ndx = F_DEF_ACL(file);
954 if (ndx >= 0 && (size_t)ndx < default_acl_list.count) {
955 acl_duo *duo_item = default_acl_list.items;
956 duo_item += ndx;
957 eq = sxp->def_acl && rsync_acl_equal(sxp->def_acl, &duo_item->racl);
958 if (!eq) {
959 if (unchanged > 0)
960 unchanged = 0;
961 if (!dry_run && fname
962 && set_rsync_acl(fname, duo_item, SMB_ACL_TYPE_DEFAULT,
963 sxp, file->mode) < 0)
964 unchanged = -1;
965 }
966 }
967
968 return unchanged;
969}
970
971/* === Enumeration functions for uid mapping === */
972
973/* Context -- one and only one. Should be cycled through once on uid
974 * mapping and once on gid mapping. */
975static item_list *_enum_racl_lists[] = {
976 &access_acl_list, &default_acl_list, NULL
977};
978
979static item_list **enum_racl_list = &_enum_racl_lists[0];
980static int enum_ida_index = 0;
981static size_t enum_racl_index = 0;
982
983/* This returns the next tag_type id from the given ACL for the next entry,
984 * or it returns 0 if there are no more tag_type ids in the acl. */
985static id_t *next_ace_id(SMB_ACL_TAG_T tag_type, const rsync_acl *racl)
986{
987 const ida_entries *idal = tag_type == SMB_ACL_USER ? &racl->users : &racl->groups;
988 if (enum_ida_index < idal->count) {
989 id_access *ida = &idal->idas[enum_ida_index++];
990 return &ida->id;
991 }
992 enum_ida_index = 0;
993 return NULL;
994}
995
996static id_t *next_acl_id(SMB_ACL_TAG_T tag_type, const item_list *racl_list)
997{
998 for (; enum_racl_index < racl_list->count; enum_racl_index++) {
999 id_t *id;
1000 acl_duo *duo_item = racl_list->items;
1001 duo_item += enum_racl_index;
1002 if ((id = next_ace_id(tag_type, &duo_item->racl)) != NULL)
1003 return id;
1004 }
1005 enum_racl_index = 0;
1006 return NULL;
1007}
1008
1009static id_t *next_acl_list_id(SMB_ACL_TAG_T tag_type)
1010{
1011 for (; *enum_racl_list; enum_racl_list++) {
1012 id_t *id = next_acl_id(tag_type, *enum_racl_list);
1013 if (id)
1014 return id;
1015 }
1016 enum_racl_list = &_enum_racl_lists[0];
1017 return NULL;
1018}
1019
1020id_t *next_acl_uid()
1021{
1022 return next_acl_list_id(SMB_ACL_USER);
1023}
1024
1025id_t *next_acl_gid()
1026{
1027 return next_acl_list_id(SMB_ACL_GROUP);
1028}
1029
1030/* This is used by dest_mode(). */
1031int default_perms_for_dir(const char *dir)
1032{
1033 rsync_acl racl;
1034 SMB_ACL_T sacl;
1035 BOOL ok;
1036 int perms;
1037
1038 if (dir == NULL)
1039 dir = ".";
1040 perms = ACCESSPERMS & ~orig_umask;
1041 /* Read the directory's default ACL. If it has none, this will successfully return an empty ACL. */
1042 sacl = sys_acl_get_file(dir, SMB_ACL_TYPE_DEFAULT);
1043 if (sacl == NULL) {
1044 /* Couldn't get an ACL. Darn. */
1045 switch (errno) {
d4a013ed 1046#ifdef ENOTSUP
1c3344a1 1047 case ENOTSUP:
d4a013ed 1048#endif
1c3344a1
WD
1049 case ENOSYS:
1050 /* No ACLs are available. */
1051 break;
1052 case ENOENT:
1053 if (dry_run) {
1054 /* We're doing a dry run, so the containing directory
1055 * wasn't actually created. Don't worry about it. */
1056 break;
1057 }
1058 /* Otherwise fall through. */
1059 default:
1060 rprintf(FERROR, "default_perms_for_dir: sys_acl_get_file(%s, %s): %s, falling back on umask\n",
1061 dir, str_acl_type(SMB_ACL_TYPE_DEFAULT), strerror(errno));
1062 }
1063 return perms;
1064 }
1065
1066 /* Convert it. */
1067 racl = empty_rsync_acl;
1068 ok = unpack_smb_acl(sacl, &racl);
1069 sys_acl_free_acl(sacl);
1070 if (!ok) {
1071 rprintf(FERROR, "default_perms_for_dir: unpack_smb_acl failed, falling back on umask\n");
1072 return perms;
1073 }
1074
1075 /* Apply the permission-bit entries of the default ACL, if any. */
1076 if (racl.user_obj != NO_ENTRY) {
1077 perms = rsync_acl_get_perms(&racl);
1078 if (verbose > 2)
1079 rprintf(FINFO, "got ACL-based default perms %o for directory %s\n", perms, dir);
1080 }
1081
1082 rsync_acl_free(&racl);
1083 return perms;
1084}
1085
1086#endif /* SUPPORT_ACLS */