#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.5 2008/06/09 13:25:40 stelian Exp $";
#endif /* not lint */
#include <config.h>
#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"
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)
}
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;
}
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;
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;
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;
*/
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);
}
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;
-
- if (lsetxattr(path, name, value, valuelen, 0) < 0) {
- warn("lsetxattr %s failed", path);
+ int err;
+
+ 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;
}
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) {
/* 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);
return FAIL;
}
entry = next;
- if (Bcvt)
- swabst("2b1s3i", (u_char *)entry);
+#if BYTE_ORDER == BIG_ENDIAN
+ swabst("2b1s3i", (u_char *)entry);
+#endif
}
return GOOD;
}
}
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;
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:
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");
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;
}