]> git.wh0rd.org - dump.git/blobdiff - restore/xattr.c
Don't attempt to extract EA in 'restore -N' mode.
[dump.git] / restore / xattr.c
index 1182d8558317e91ad66f717c958bd9d990b53338..ccc01c14c21e74177ce4b4af95cdf4f227b79991 100644 (file)
@@ -29,7 +29,7 @@
 
 #ifndef lint
 static const char rcsid[] =
-       "$Id: xattr.c,v 1.2 2005/06/08 09:34:40 stelian Exp $";
+       "$Id: xattr.c,v 1.6 2010/03/08 10:40:52 stelian Exp $";
 #endif /* not lint */
 
 #include <config.h>
@@ -43,6 +43,9 @@ static const char rcsid[] =
 #include <errno.h>
 #include <bsdcompat.h>
 #include <protocols/dumprestore.h>
+#ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
+# include <selinux/selinux.h>
+#endif
 #include "restore.h"
 #include "extern.h"
 #include "pathnames.h"
@@ -195,12 +198,12 @@ struct ext2_xattr_entry {
 static int lsetxattr __P((const char *, const char *, void *, size_t, int));
 static ssize_t lgetxattr __P((const char *, const char *, void *, size_t));
 static ssize_t llistxattr __P((const char *, char *, size_t));
-static int xattr_cb_list __P((char *, char *, int, void *));
-static int xattr_cb_set __P((char *, char *, int, void *));
-static int xattr_cb_compare __P((char *, char *, int, void *));
+static int xattr_cb_list __P((char *, char *, int, int, void *));
+static int xattr_cb_set __P((char *, char *, int, int, void *));
+static int xattr_cb_compare __P((char *, char *, int, int, void *));
 static int xattr_verify __P((char *));
 static int xattr_count __P((char *, int *));
-static int xattr_walk __P((char *, int (*)(char *, char *, int, void *), void *));
+static int xattr_walk __P((char *, int (*)(char *, char *, int, int, void *), void *));
 
 static int
 lsetxattr(const char *path, const char *name, void *value, size_t size, int flags)
@@ -308,15 +311,17 @@ posix_acl_to_xattr(const struct posix_acl *acl, void *buffer, size_t size) {
        }
 
        ext_acl->a_version = POSIX_ACL_XATTR_VERSION;
-       if (Bcvt) 
-               swabst("1i", (u_char *)ext_acl);
+#if BYTE_ORDER == BIG_ENDIAN
+       swabst("1i", (u_char *)ext_acl);
+#endif
 
        for (n=0; n < acl->a_count; n++, ext_entry++) {
                ext_entry->e_tag  = acl->a_entries[n].e_tag;
                ext_entry->e_perm = acl->a_entries[n].e_perm;
                ext_entry->e_id   = acl->a_entries[n].e_id;
-               if (Bcvt)
-                       swabst("2s1i", (u_char *)ext_entry);
+#if BYTE_ORDER == BIG_ENDIAN
+               swabst("2s1i", (u_char *)ext_entry);
+#endif
        }
        return real_size;
 }
@@ -334,8 +339,9 @@ ext3_acl_from_disk(const void *value, size_t size)
                fprintf(stderr, "ACL size too little\n");
                return NULL;
        }
-       if (Bcvt) 
-               swabst("1i", (u_char *)value);
+#if BYTE_ORDER == BIG_ENDIAN
+       swabst("1i", (u_char *)value);
+#endif
        if (((ext3_acl_header *)value)->a_version != EXT3_ACL_VERSION) {
                fprintf(stderr, "ACL version unknown\n");
                return NULL;
@@ -356,9 +362,10 @@ ext3_acl_from_disk(const void *value, size_t size)
        acl->a_count = count;
 
        for (n=0; n < count; n++) {
-               if (Bcvt)
-                       swabst("2s1i", (u_char *)value);
                ext3_acl_entry *entry = (ext3_acl_entry *)value;
+#if BYTE_ORDER == BIG_ENDIAN
+               swabst("2s", (u_char *)entry);
+#endif
                if ((char *)value + sizeof(ext3_acl_entry_short) > end)
                        goto fail;
                acl->a_entries[n].e_tag  = entry->e_tag;
@@ -374,6 +381,9 @@ ext3_acl_from_disk(const void *value, size_t size)
 
                case ACL_USER:
                case ACL_GROUP:
+#if BYTE_ORDER == BIG_ENDIAN
+                       swabst("4b1i", (u_char *)entry);
+#endif
                        value = (char *)value + sizeof(ext3_acl_entry);
                        if ((char *)value > end)
                                goto fail;
@@ -399,8 +409,9 @@ fail:
  */
 
 static int
-xattr_cb_list(char *name, char *value, int valuelen, void *private)
+xattr_cb_list(char *name, char *value, int valuelen, int isSELinux, void *private)
 {
+       isSELinux;
        value[valuelen] = '\0';
        printf("EA: %s:%s\n", name, value);
 
@@ -408,37 +419,67 @@ xattr_cb_list(char *name, char *value, int valuelen, void *private)
 }
 
 static int
-xattr_cb_set(char *name, char *value, int valuelen, void *private)
+xattr_cb_set(char *name, char *value, int valuelen, int isSELinux, void *private)
 {
        char *path = (char *)private;
+       int err;
+
+       if (Nflag)
+               return GOOD;
 
-       if (lsetxattr(path, name, value, valuelen, 0) < 0) {
-               warn("lsetxattr %s failed", path);
+       isSELinux;
+#ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
+       if (isSELinux)
+               err = lsetfilecon(path, value);
+       else
+#endif
+               err = lsetxattr(path, name, value, valuelen, 0);
+       
+       if (err) {
+               warn("%s: EA set %s:%s failed", path, name, value);
                return FAIL;
        }
+       
        return GOOD;
 }
 
 static int
-xattr_cb_compare(char *name, char *value, int valuelen, void *private)
+xattr_cb_compare(char *name, char *value, int valuelen, int isSELinux, void *private)
 {
        char *path = (char *)private;
        char valuef[XATTR_MAXSIZE];
        int valuesz;
-
-       valuesz = lgetxattr(path, name, valuef, XATTR_MAXSIZE);
-       if (valuesz < 0) {
-               warn("%s: lgetxattr failed\n", path);
-               return FAIL;
+       
+       isSELinux;
+#ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
+       if (isSELinux)
+       {
+               security_context_t con = NULL;
+               
+               if (lgetfilecon(path, &con) < 0) {
+                       warn("%s: EA compare lgetfilecon failed\n", path);
+                       return FAIL;
+               }
+               
+               valuesz = strlen(con) + 1;
+               valuef[0] = 0;
+               strncat(valuef, con, sizeof valuef);
+               freecon(con);
        }
-
-       if (valuesz != valuelen) {
-               fprintf(stderr, "%s: EA %s value changed\n", path, value);
-               return FAIL;
+       else {
+#endif
+               valuesz = lgetxattr(path, name, valuef, XATTR_MAXSIZE);
+               if (valuesz < 0) {
+                       warn("%s: EA compare lgetxattr failed\n", path);
+                       return FAIL;
+               }
+#ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
        }
-
-       if (memcmp(value, valuef, valuelen)) {
-               fprintf(stderr, "%s: EA %s value changed\n", path, value);
+#endif
+       
+       if (valuesz != valuelen || memcmp(value, valuef, valuelen)) {
+               /* GAN24May06: show name and new value for user to compare */
+               fprintf(stderr, "%s: EA %s:%s value changed to %s\n", path, name, value, valuef);
                return FAIL;
        }
 
@@ -453,8 +494,9 @@ xattr_verify(char *buffer)
 
        end = buffer + XATTR_MAXSIZE;
 
-       if (Bcvt)
-               swabst("4i", (u_char *)buffer);
+#if BYTE_ORDER == BIG_ENDIAN
+       swabst("4i", (u_char *)buffer);
+#endif
 
        if (HDR(buffer)->h_magic != EXT2_XATTR_MAGIC &&
            HDR(buffer)->h_magic != EXT2_XATTR_MAGIC2) {
@@ -466,8 +508,9 @@ xattr_verify(char *buffer)
 
        /* check the on-disk data structure */
        entry = FIRST_ENTRY(buffer);
-       if (Bcvt) 
-               swabst("2b1s3i", (u_char *)entry);
+#if BYTE_ORDER == BIG_ENDIAN
+       swabst("2b1s3i", (u_char *)entry);
+#endif
        while (!IS_LAST_ENTRY(entry)) {
                struct ext2_xattr_entry *next = EXT2_XATTR_NEXT(entry);
 
@@ -476,8 +519,9 @@ xattr_verify(char *buffer)
                        return FAIL;
                }
                entry = next;
-               if (Bcvt) 
-                       swabst("2b1s3i", (u_char *)entry);
+#if BYTE_ORDER == BIG_ENDIAN
+               swabst("2b1s3i", (u_char *)entry);
+#endif
        }
        return GOOD;
 }
@@ -498,7 +542,7 @@ xattr_count(char *buffer, int *count)
 }
 
 static int
-xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *private)
+xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, int, void *), void *private)
 {
        struct ext2_xattr_entry *entry;
 
@@ -506,8 +550,10 @@ xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *pri
        for (entry = FIRST_ENTRY(buffer); !IS_LAST_ENTRY(entry);
             entry = EXT2_XATTR_NEXT(entry)) {
                char name[XATTR_MAXSIZE], value[XATTR_MAXSIZE];
+               int size;
                int off;
                int convertacl = 0;
+               int convertcon = 0;
 
                switch (entry->e_name_index) {
                case EXT2_XATTR_INDEX_USER:
@@ -529,6 +575,9 @@ xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *pri
                        break;
                case EXT2_XATTR_INDEX_SECURITY:
                        strcpy(name, "security.");
+#ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
+                       convertcon = transselinuxflag;
+#endif
                        break;
                default:
                        fprintf(stderr, "Unknown EA index\n");
@@ -538,24 +587,51 @@ xattr_walk(char *buffer, int (*xattr_cb)(char *, char *, int, void *), void *pri
                off = strlen(name);
                memcpy(name + off, entry->e_name, entry->e_name_len);
                name[off + entry->e_name_len] = '\0';
+               size = entry->e_value_size;
 
-               memcpy(value, buffer + VALUE_OFFSET(buffer, entry), entry->e_value_size);
+               memcpy(value, buffer + VALUE_OFFSET(buffer, entry), size);
 
                if (convertacl) {
                        struct posix_acl *acl;
-                       int size;
 
-                       acl = ext3_acl_from_disk(value, entry->e_value_size);
+                       acl = ext3_acl_from_disk(value, size);
                        if (!acl)
                                return FAIL;
                        size = posix_acl_to_xattr(acl, value, XATTR_MAXSIZE);
                        if (size < 0)
                                return FAIL;
-                       entry->e_value_size = size;
                        free(acl);
                }
+               
+#ifdef TRANSSELINUX                    /*GAN6May06 SELinux MLS */
+               if (convertcon  &&  strcmp(name, "security.selinux"))
+                       convertcon = 0; /*GAN24May06 only for selinux */
+               
+               if (convertcon)
+               {
+                       security_context_t con = NULL;
+                       int err;
+                       
+                       if (!transselinuxarg)
+                               err = security_canonicalize_context(value, &con);
+                       else {
+                               strncat(value, transselinuxarg, sizeof value);
+                               err = security_canonicalize_context_raw(value, &con);
+                       }
+                       
+                       if (err < 0) {
+                               warn("%s: EA canonicalize failed\n", value);
+                               return FAIL;
+                       }
+
+                       size = strlen(con) + 1;
+                       value[0] = 0;
+                       strncat(value, con, sizeof value);
+                       freecon(con);
+               }
+#endif
 
-               if (xattr_cb(name, value, entry->e_value_size, private) != GOOD)
+               if (xattr_cb(name, value, size, convertcon, private) != GOOD)
                        return FAIL;
        }