]> git.sur5r.net Git - bacula/bacula/blob - bacula/src/filed/bacl_linux.c
Update ACL/XATTR code and define new ACL/XATTR API for Plugins.
[bacula/bacula] / bacula / src / filed / bacl_linux.c
1 /*
2    Bacula(R) - The Network Backup Solution
3
4    Copyright (C) 2000-2016 Kern Sibbald
5
6    The original author of Bacula is Kern Sibbald, with contributions
7    from many others, a complete list can be found in the file AUTHORS.
8
9    You may use this file and others of this release according to the
10    license defined in the LICENSE file, which includes the Affero General
11    Public License, v3.0 ("AGPLv3") and some additional permissions and
12    terms pursuant to its AGPLv3 Section 7.
13
14    This notice must be preserved when any source code is
15    conveyed and/or propagated.
16
17    Bacula(R) is a registered trademark of Kern Sibbald.
18  */
19 /**
20  * Major refactoring of ACL code written by:
21  *
22  *  RadosÅ‚aw Korzeniewski, MMXVI
23  *  radoslaw@korzeniewski.net, radekk@inteos.pl
24  *  Inteos Sp. z o.o. http://www.inteos.pl/
25  *
26  */
27
28 #include "bacula.h"
29 #include "filed.h"
30 #include "bacl_linux.h"
31
32 #if defined(HAVE_LINUX_OS)
33
34 /* check if ACL support is enabled */
35 #if defined(HAVE_ACL)
36
37 /*
38  * Define the supported ACL streams for this OS
39  */
40 static const int os_acl_streams[] = {
41    STREAM_XACL_LINUX_ACCESS,
42    0
43 };
44
45 static const int os_default_acl_streams[] = {
46    STREAM_XACL_LINUX_DEFAULT,
47    0
48 };
49
50 /*
51  * OS specific constructor
52  */
53 BACL_Linux::BACL_Linux(){
54    set_acl_streams(os_acl_streams, os_default_acl_streams);
55 };
56
57 /*
58  * Translates Bacula internal acl representation into
59  * acl type
60  *
61  * in:
62  *    bacltype - internal Bacula acl type (BACL_type)
63  * out:
64  *    acl_type_t - os dependent acl type
65  *    when failed - ACL_TYPE_NONE is returned
66  */
67 acl_type_t BACL_Linux::get_acltype(BACL_type bacltype){
68
69    acl_type_t acltype;
70
71    switch (bacltype){
72       case BACL_TYPE_ACCESS:
73          acltype = ACL_TYPE_ACCESS;
74          break;
75       case BACL_TYPE_DEFAULT:
76          acltype = ACL_TYPE_DEFAULT;
77          break;
78       default:
79          /*
80           * sanity check for acl's not supported by OS
81           */
82          acltype = (acl_type_t)ACL_TYPE_NONE;
83          break;
84    }
85    return acltype;
86 };
87
88 /*
89  * Counts a number of acl entries
90  *
91  * in:
92  *    acl - acl object
93  * out:
94  *    int - number of entries in acl object
95  *    when no acl entry available or any error then return zero '0'
96  */
97 int BACL_Linux::acl_nrentries(acl_t acl){
98
99    int nr = 0;
100    acl_entry_t aclentry;
101    int rc;
102
103    rc = acl_get_entry(acl, ACL_FIRST_ENTRY, &aclentry);
104    while (rc == 1){
105       nr++;
106       rc = acl_get_entry(acl, ACL_NEXT_ENTRY, &aclentry);
107    }
108
109    return nr;
110 };
111
112 /*
113  * Checks if acl is simple.
114  *
115  * acl is simple if it has only the following entries:
116  * "user::",
117  * "group::",
118  * "other::"
119  *
120  * in:
121  *    acl - acl object
122  * out:
123  *    true - when acl object is simple
124  *    false - when acl object is not simple
125  */
126 bool BACL_Linux::acl_issimple(acl_t acl){
127
128    acl_entry_t aclentry;
129    acl_tag_t acltag;
130    int rc;
131
132    rc = acl_get_entry(acl, ACL_FIRST_ENTRY, &aclentry);
133    while (rc == 1){
134       if (acl_get_tag_type(aclentry, &acltag) < 0){
135          return true;
136       }
137       /*
138        * Check for ACL_USER_OBJ, ACL_GROUP_OBJ or ACL_OTHER to find out.
139        */
140       if (acltag != ACL_USER_OBJ &&
141           acltag != ACL_GROUP_OBJ &&
142           acltag != ACL_OTHER){
143          return false;
144       }
145       rc = acl_get_entry(acl, ACL_NEXT_ENTRY, &aclentry);
146    }
147    return true;
148 };
149
150 /*
151  * Perform OS specific ACL backup
152  *
153  * in/out - check API at bacl.h
154  */
155 bRC_BACL BACL_Linux::os_backup_acl (JCR *jcr, FF_PKT *ff_pkt){
156    return generic_backup_acl(jcr, ff_pkt);
157 };
158
159 /*
160  * Perform OS specific ACL restore
161  *
162  * in/out - check API at bacl.h
163  */
164 bRC_BACL BACL_Linux::os_restore_acl (JCR *jcr, int stream, char *content, uint32_t length){
165    return generic_restore_acl(jcr, stream);
166 };
167
168 /*
169  * Low level OS specific runtime to get ACL data from file. The ACL data is set in internal content buffer.
170  *
171  * in/out - check API at bacl.h
172  */
173 bRC_BACL BACL_Linux::os_get_acl(JCR *jcr, BACL_type bacltype){
174
175    acl_t acl;
176    acl_type_t acltype;
177    char *acltext;
178    bRC_BACL rc = bRC_BACL_ok;
179
180    /* check input data */
181    if (jcr == NULL){
182       return bRC_BACL_inval;
183    }
184
185    acltype = get_acltype(bacltype);
186    acl = acl_get_file(jcr->last_fname, acltype);
187
188    if (acl){
189       Dmsg1(400, "OS_ACL read from file: %s\n",jcr->last_fname);
190       if (acl_nrentries(acl) == 0){
191          goto bail_out;
192       }
193
194       /* check for simple ACL which correspond to standard permissions only */
195       if (bacltype == BACL_TYPE_ACCESS && acl_issimple(acl)){
196          goto bail_out;
197       }
198
199       if ((acltext = acl_to_text(acl, NULL)) != NULL){
200          set_content(acltext);
201          acl_free(acl);
202          acl_free(acltext);
203          return bRC_BACL_ok;
204       }
205
206       berrno be;
207
208       Mmsg2(jcr->errmsg, _("acl_to_text error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
209       Dmsg2(100, "acl_to_text error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
210
211       rc = bRC_BACL_error;
212    } else {
213       berrno be;
214
215       switch (errno){
216       case EOPNOTSUPP:
217          /* fs does not support acl, skip it */
218          Dmsg0(400, "Wow, ACL is not supported on this filesystem\n");
219          clear_flag(BACL_FLAG_NATIVE);
220          break;
221       case ENOENT:
222          break;
223       default:
224          /* Some real error */
225          Mmsg2(jcr->errmsg, _("acl_get_file error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
226          Dmsg2(100, "acl_get_file error file=%s ERR=%s\n", jcr->last_fname, be.bstrerror());
227          rc = bRC_BACL_error;
228          break;
229       }
230    }
231
232 bail_out:
233    if (acl){
234       acl_free(acl);
235    }
236    /*
237     * it is a bit of hardcore to clear a poolmemory with a NULL pointer,
238     * but it is working, hehe :)
239     * you may ask why it is working? it is simple, a pm_strcpy function is handling
240     * a null pointer with a substitiution of empty string.
241     */
242    set_content(NULL);
243    return rc;
244 };
245
246 /*
247  * Low level OS specific runtime to set ACL data on file
248  *
249  * in/out - check API at bacl.h
250  */
251 bRC_BACL BACL_Linux::os_set_acl(JCR *jcr, BACL_type bacltype, char *content, uint32_t length){
252
253    acl_t acl;
254    acl_type_t acltype;
255
256    /* check input data */
257    if (jcr == NULL || content == NULL){
258       return bRC_BACL_inval;
259    }
260
261    acl = acl_from_text(content);
262    if (acl == NULL){
263       berrno be;
264
265       Mmsg2(jcr->errmsg, _("acl_from_text error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
266       Dmsg3(100, "acl_from_text error acl=%s file=%s ERR=%s\n", content, jcr->last_fname, be.bstrerror());
267       return bRC_BACL_error;
268    }
269
270    if (acl_valid(acl) != 0){
271       berrno be;
272
273       Mmsg2(jcr->errmsg, _("acl_valid error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
274       Dmsg3(100, "acl_valid error acl=%s file=%s ERR=%s\n", content, jcr->last_fname, be.bstrerror());
275       acl_free(acl);
276       return bRC_BACL_error;
277    }
278
279    /* handle different acl types for Linux */
280    acltype = get_acltype(bacltype);
281    if (acltype == ACL_TYPE_DEFAULT && length == 0){
282       /* delete ACl from file when no acl data available for default acl's */
283       if (acl_delete_def_file(jcr->last_fname) == 0){
284          return bRC_BACL_ok;
285       }
286
287       berrno be;
288       switch (errno){
289          case ENOENT:
290             return bRC_BACL_ok;
291          case ENOTSUP:
292             /*
293              * If the filesystem reports it doesn't support acl's we clear the
294              * BACL_FLAG_NATIVE flag so we skip ACL restores on all other files
295              * on the same filesystem. The BACL_FLAG_NATIVE flag gets set again
296              * when we change from one filesystem to an other.
297              */
298             clear_flag(BACL_FLAG_NATIVE);
299             Mmsg(jcr->errmsg, _("acl_delete_def_file error on file \"%s\": filesystem doesn't support ACLs\n"), jcr->last_fname);
300             return bRC_BACL_error;
301          default:
302             Mmsg2(jcr->errmsg, _("acl_delete_def_file error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
303             return bRC_BACL_error;
304       }
305    }
306
307    /*
308     * Restore the ACLs, but don't complain about links which really should
309     * not have attributes, and the file it is linked to may not yet be restored.
310     * This is only true for the old acl streams as in the new implementation we
311     * don't save acls of symlinks (which cannot have acls anyhow)
312     */
313    if (acl_set_file(jcr->last_fname, acltype, acl) != 0 && jcr->last_type != FT_LNK){
314       berrno be;
315       switch (errno){
316       case ENOENT:
317          acl_free(acl);
318          return bRC_BACL_ok;
319       case ENOTSUP:
320          /*
321           * If the filesystem reports it doesn't support ACLs we clear the
322           * BACL_FLAG_NATIVE flag so we skip ACL restores on all other files
323           * on the same filesystem. The BACL_FLAG_NATIVE flag gets set again
324           * when we change from one filesystem to an other.
325           */
326          clear_flag(BACL_FLAG_NATIVE);
327          Mmsg(jcr->errmsg, _("acl_set_file error on file \"%s\": filesystem doesn't support ACLs\n"), jcr->last_fname);
328          Dmsg2(100, "acl_set_file error acl=%s file=%s filesystem doesn't support ACLs\n", content, jcr->last_fname);
329          acl_free(acl);
330          return bRC_BACL_error;
331       default:
332          Mmsg2(jcr->errmsg, _("acl_set_file error on file \"%s\": ERR=%s\n"), jcr->last_fname, be.bstrerror());
333          Dmsg3(100, "acl_set_file error acl=%s file=%s ERR=%s\n", content, jcr->last_fname, be.bstrerror());
334          acl_free(acl);
335          return bRC_BACL_error;
336       }
337    }
338    acl_free(acl);
339    return bRC_BACL_ok;
340 };
341
342 #endif /* HAVE_ACL */
343
344 #endif /* HAVE_LINUX_OS */