Update to 5.8-pre1
This commit is contained in:
parent
47f345086c
commit
a9cb2f0ecc
973
cifs-utils-5.8-pre1.patch
Normal file
973
cifs-utils-5.8-pre1.patch
Normal file
@ -0,0 +1,973 @@
|
||||
diff --git a/cifs.idmap.8.in b/cifs.idmap.8.in
|
||||
index efec7b6..c022402 100644
|
||||
--- a/cifs.idmap.8.in
|
||||
+++ b/cifs.idmap.8.in
|
||||
@@ -22,7 +22,7 @@
|
||||
cifs.idmap \- Userspace helper for mapping ids for Common Internet File System (CIFS)
|
||||
.SH "SYNOPSIS"
|
||||
.HP \w'\ 'u
|
||||
-cifs\&.idmap [\-\-version|\-v] {keyid}
|
||||
+cifs.idmap [--help|-h] [--timeout|-t] [--version|-v] {keyid}
|
||||
.SH "DESCRIPTION"
|
||||
.PP
|
||||
This tool is part of the cifs-utils suite\&.
|
||||
@@ -46,6 +46,16 @@ cifs\&.idmap works in conjuction with winbind facility of Samba suite to map own
|
||||
In case winbind and cifs.idmap facilities are unavailable, file objects in a mounted share are assigned uid and gid of the credentials of the process that mounted the share\&. So it is strongly recomemended to use mount options of uid and gid to specify a default uid and gid to map owner SIDs and group SIDs respectively in case services of winbind and cifs.idmap facility are unavailable\&.
|
||||
.SH "OPTIONS"
|
||||
.PP
|
||||
+--help|-h
|
||||
+.RS
|
||||
+Print the usage message and exit.
|
||||
+.RE
|
||||
+.PP
|
||||
+--timeout|-t
|
||||
+.RS 4
|
||||
+Set the expiration timer, in seconds on the key. The default is 600 seconds (10 minutes). Setting this to 0 will cause the key to never expire.
|
||||
+.RE
|
||||
+.PP
|
||||
\-\-version|\-v
|
||||
.RS 4
|
||||
Print version number and exit\&.
|
||||
diff --git a/cifs.idmap.c b/cifs.idmap.c
|
||||
index 80802d7..4109ca0 100644
|
||||
--- a/cifs.idmap.c
|
||||
+++ b/cifs.idmap.c
|
||||
@@ -42,35 +42,76 @@
|
||||
#include <limits.h>
|
||||
#include <wbclient.h>
|
||||
|
||||
+#include "cifsacl.h"
|
||||
+
|
||||
static const char *prog = "cifs.idmap";
|
||||
|
||||
+static const struct option long_options[] = {
|
||||
+ {"help", 0, NULL, 'h'},
|
||||
+ {"timeout", 1, NULL, 't'},
|
||||
+ {"version", 0, NULL, 'v'},
|
||||
+ {NULL, 0, NULL, 0}
|
||||
+};
|
||||
+
|
||||
static void usage(void)
|
||||
{
|
||||
- fprintf(stderr, "Usage: %s key_serial\n", prog);
|
||||
+ fprintf(stderr, "Usage: %s [-h] [-v] [-t timeout] key_serial\n", prog);
|
||||
}
|
||||
|
||||
-char *strget(const char *str, char *substr)
|
||||
+char *strget(const char *str, const char *substr)
|
||||
{
|
||||
int len, sublen, retlen;
|
||||
- char *retstr, *substrptr;
|
||||
+ char *substrptr;
|
||||
|
||||
- sublen = strlen(substr);
|
||||
+ /* find the prefix */
|
||||
substrptr = strstr(str, substr);
|
||||
- if (substrptr) {
|
||||
- len = strlen(substrptr);
|
||||
- substrptr += sublen;
|
||||
-
|
||||
- retlen = len - sublen;
|
||||
- if (retlen > 0) {
|
||||
- retstr = malloc(retlen + 1);
|
||||
- if (retstr) {
|
||||
- strncpy(retstr, substrptr, retlen);
|
||||
- return retstr;
|
||||
- }
|
||||
- }
|
||||
- }
|
||||
+ if (!substrptr)
|
||||
+ return substrptr;
|
||||
+
|
||||
+ /* skip over it */
|
||||
+ sublen = strlen(substr);
|
||||
+ substrptr += sublen;
|
||||
+
|
||||
+ /* if there's nothing after the prefix, return NULL */
|
||||
+ if (*substrptr == '\0')
|
||||
+ return NULL;
|
||||
|
||||
- return NULL;
|
||||
+ return substrptr;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Convert a string representation of unsigned int into a numeric one. Also
|
||||
+ * check for incomplete string conversion and overflow.
|
||||
+ */
|
||||
+static int
|
||||
+str_to_uint(const char *src, unsigned int *dst)
|
||||
+{
|
||||
+ unsigned long tmp;
|
||||
+ char *end;
|
||||
+
|
||||
+ errno = 0;
|
||||
+ tmp = strtoul(src, &end, 0);
|
||||
+
|
||||
+ if (*end != '\0')
|
||||
+ return EINVAL;
|
||||
+ if (tmp > UINT_MAX)
|
||||
+ return EOVERFLOW;
|
||||
+
|
||||
+ *dst = (unsigned int)tmp;
|
||||
+ return 0;
|
||||
+}
|
||||
+
|
||||
+/*
|
||||
+ * Winbind keeps wbcDomainSid fields in host-endian. So, we must convert it
|
||||
+ * to little endian since the kernel will expect that.
|
||||
+ */
|
||||
+static void
|
||||
+convert_sid_endianness(struct cifs_sid *sid)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < sid->num_subauth; i++)
|
||||
+ sid->sub_auth[i] = htole32(sid->sub_auth[i]);
|
||||
}
|
||||
|
||||
static int
|
||||
@@ -136,12 +177,20 @@ cifs_idmap(const key_serial_t key, const char *key_descr)
|
||||
|
||||
sidstr = strget(key_descr, "oi:");
|
||||
if (sidstr) {
|
||||
- uid = atoi(sidstr);
|
||||
- syslog(LOG_DEBUG, "SID: %s, uid: %d", sidstr, uid);
|
||||
+ rc = str_to_uint(sidstr, (unsigned int *)&uid);
|
||||
+ if (rc) {
|
||||
+ syslog(LOG_ERR, "Unable to convert %s to uid: %s",
|
||||
+ sidstr, strerror(rc));
|
||||
+ goto cifs_idmap_ret;
|
||||
+ }
|
||||
+
|
||||
+ syslog(LOG_DEBUG, "SID: %s, uid: %u", sidstr, uid);
|
||||
rc = wbcUidToSid(uid, &sid);
|
||||
if (rc)
|
||||
- syslog(LOG_DEBUG, "uid %d to SID error: %d", uid, rc);
|
||||
- if (!rc) { /* SID has been mapped to a uid */
|
||||
+ syslog(LOG_DEBUG, "uid %u to SID error: %d", uid, rc);
|
||||
+ if (!rc) {
|
||||
+ /* SID has been mapped to a uid */
|
||||
+ convert_sid_endianness((struct cifs_sid *)&sid);
|
||||
rc = keyctl_instantiate(key, &sid,
|
||||
sizeof(struct wbcDomainSid), 0);
|
||||
if (rc)
|
||||
@@ -154,12 +203,20 @@ cifs_idmap(const key_serial_t key, const char *key_descr)
|
||||
|
||||
sidstr = strget(key_descr, "gi:");
|
||||
if (sidstr) {
|
||||
- gid = atoi(sidstr);
|
||||
- syslog(LOG_DEBUG, "SID: %s, gid: %d", sidstr, gid);
|
||||
+ rc = str_to_uint(sidstr, (unsigned int *)&gid);
|
||||
+ if (rc) {
|
||||
+ syslog(LOG_ERR, "Unable to convert %s to gid: %s",
|
||||
+ sidstr, strerror(rc));
|
||||
+ goto cifs_idmap_ret;
|
||||
+ }
|
||||
+
|
||||
+ syslog(LOG_DEBUG, "SID: %s, gid: %u", sidstr, gid);
|
||||
rc = wbcGidToSid(gid, &sid);
|
||||
if (rc)
|
||||
- syslog(LOG_DEBUG, "gid %d to SID error: %d", gid, rc);
|
||||
- if (!rc) { /* SID has been mapped to a gid */
|
||||
+ syslog(LOG_DEBUG, "gid %u to SID error: %d", gid, rc);
|
||||
+ if (!rc) {
|
||||
+ /* SID has been mapped to a gid */
|
||||
+ convert_sid_endianness((struct cifs_sid *)&sid);
|
||||
rc = keyctl_instantiate(key, &sid,
|
||||
sizeof(struct wbcDomainSid), 0);
|
||||
if (rc)
|
||||
@@ -174,32 +231,46 @@ cifs_idmap(const key_serial_t key, const char *key_descr)
|
||||
syslog(LOG_DEBUG, "Invalid key: %s", key_descr);
|
||||
|
||||
cifs_idmap_ret:
|
||||
- if (sidstr)
|
||||
- free(sidstr);
|
||||
-
|
||||
return rc;
|
||||
}
|
||||
|
||||
int main(const int argc, char *const argv[])
|
||||
{
|
||||
int c;
|
||||
- long rc = 1;
|
||||
+ long rc;
|
||||
key_serial_t key = 0;
|
||||
char *buf;
|
||||
+ unsigned int timeout = 600; /* default idmap cache timeout */
|
||||
|
||||
openlog(prog, 0, LOG_DAEMON);
|
||||
|
||||
- while ((c = getopt_long(argc, argv, "v", NULL, NULL)) != -1) {
|
||||
+ while ((c = getopt_long(argc, argv, "ht:v",
|
||||
+ long_options, NULL)) != -1) {
|
||||
switch (c) {
|
||||
+ case 'h':
|
||||
+ rc = 0;
|
||||
+ usage();
|
||||
+ goto out;
|
||||
+ case 't':
|
||||
+ rc = str_to_uint(optarg, &timeout);
|
||||
+ if (rc) {
|
||||
+ syslog(LOG_ERR, "bad timeout value %s: %s",
|
||||
+ optarg, strerror(rc));
|
||||
+ goto out;
|
||||
+ }
|
||||
+ break;
|
||||
case 'v':
|
||||
+ rc = 0;
|
||||
printf("version: %s\n", VERSION);
|
||||
goto out;
|
||||
default:
|
||||
+ rc = EINVAL;
|
||||
syslog(LOG_ERR, "unknown option: %c", c);
|
||||
goto out;
|
||||
}
|
||||
}
|
||||
|
||||
+ rc = 1;
|
||||
/* is there a key? */
|
||||
if (argc <= optind) {
|
||||
usage();
|
||||
@@ -215,6 +286,14 @@ int main(const int argc, char *const argv[])
|
||||
goto out;
|
||||
}
|
||||
|
||||
+ /* set timeout on key */
|
||||
+ rc = keyctl_set_timeout(key, timeout);
|
||||
+ if (rc == -1) {
|
||||
+ syslog(LOG_ERR, "unable to set key timeout: %s",
|
||||
+ strerror(errno));
|
||||
+ goto out;
|
||||
+ }
|
||||
+
|
||||
rc = keyctl_describe_alloc(key, &buf);
|
||||
if (rc == -1) {
|
||||
syslog(LOG_ERR, "keyctl_describe_alloc failed: %s",
|
||||
@@ -225,8 +304,7 @@ int main(const int argc, char *const argv[])
|
||||
|
||||
syslog(LOG_DEBUG, "key description: %s", buf);
|
||||
|
||||
- if ((strncmp(buf, "cifs.idmap", sizeof("cifs.idmap") - 1) == 0))
|
||||
- rc = cifs_idmap(key, buf);
|
||||
+ rc = cifs_idmap(key, buf);
|
||||
out:
|
||||
return rc;
|
||||
}
|
||||
diff --git a/cifsacl.h b/cifsacl.h
|
||||
index 4ea7fd4..68fe0fd 100644
|
||||
--- a/cifsacl.h
|
||||
+++ b/cifsacl.h
|
||||
@@ -83,7 +83,7 @@
|
||||
#define NO_PROPAGATE_INHERIT_FLAG 0x04 /* NP */
|
||||
#define INHERIT_ONLY_FLAG 0x08 /* IO */
|
||||
#define INHERITED_ACE_FLAG 0x10 /* I */
|
||||
-#define VFLAGS 0x1f
|
||||
+#define VFLAGS (OBJECT_INHERIT_FLAG|CONTAINER_INHERIT_FLAG|NO_PROPAGATE_INHERIT_FLAG|INHERIT_ONLY_FLAG|INHERITED_ACE_FLAG)
|
||||
|
||||
#define ACCESS_ALLOWED 0 /* ALLOWED */
|
||||
#define ACCESS_DENIED 1 /* DENIED */
|
||||
@@ -94,15 +94,17 @@
|
||||
#define COMPTYPE 0x2
|
||||
#define COMPFLAG 0x4
|
||||
#define COMPMASK 0x8
|
||||
-#define COMPALL 0xf /* COMPSID | COMPTYPE | COMPFLAG | COMPMASK */
|
||||
+#define COMPALL (COMPSID|COMPTYPE|COMPFLAG|COMPMASK)
|
||||
|
||||
-enum ace_action {
|
||||
- acedelete = 0,
|
||||
- acemodify,
|
||||
- aceadd,
|
||||
- aceset
|
||||
-};
|
||||
+#define NUM_AUTHS (6) /* number of authority fields */
|
||||
+#define SID_MAX_SUB_AUTHORITIES (15) /* max number of sub authority fields */
|
||||
|
||||
+/*
|
||||
+ * While not indicated here, the structs below represent on-the-wire data
|
||||
+ * structures. Any multi-byte values are expected to be little-endian!
|
||||
+ *
|
||||
+ * FIXME: should we change these to use endianness annotations?
|
||||
+ */
|
||||
struct cifs_ntsd {
|
||||
uint16_t revision; /* revision level */
|
||||
uint16_t type;
|
||||
@@ -110,20 +112,20 @@ struct cifs_ntsd {
|
||||
uint32_t gsidoffset;
|
||||
uint32_t sacloffset;
|
||||
uint32_t dacloffset;
|
||||
-};
|
||||
+} __attribute__((packed));
|
||||
|
||||
struct cifs_sid {
|
||||
uint8_t revision; /* revision level */
|
||||
uint8_t num_subauth;
|
||||
- uint8_t authority[6];
|
||||
- uint32_t sub_auth[5]; /* sub_auth[num_subauth] */
|
||||
-};
|
||||
+ uint8_t authority[NUM_AUTHS];
|
||||
+ uint32_t sub_auth[SID_MAX_SUB_AUTHORITIES];
|
||||
+} __attribute__((packed));
|
||||
|
||||
struct cifs_ctrl_acl {
|
||||
uint16_t revision; /* revision level */
|
||||
uint16_t size;
|
||||
uint32_t num_aces;
|
||||
-};
|
||||
+} __attribute__((packed));
|
||||
|
||||
struct cifs_ace {
|
||||
uint8_t type;
|
||||
@@ -131,6 +133,6 @@ struct cifs_ace {
|
||||
uint16_t size;
|
||||
uint32_t access_req;
|
||||
struct cifs_sid sid; /* ie UUID of user or group who gets these perms */
|
||||
-};
|
||||
+} __attribute__((packed));
|
||||
|
||||
#endif /* CIFSACL_H */
|
||||
diff --git a/configure.ac b/configure.ac
|
||||
index f969b37..07df3be 100644
|
||||
--- a/configure.ac
|
||||
+++ b/configure.ac
|
||||
@@ -1,7 +1,7 @@
|
||||
# -*- Autoconf -*-
|
||||
# Process this file with autoconf to produce a configure script.
|
||||
|
||||
-AC_INIT([cifs-utils], [5.7], [linux-cifs@vger.kernel.org], [cifs-utils], [https://wiki.samba.org/index.php/LinuxCIFS_utils])
|
||||
+AC_INIT([cifs-utils], [5.7.1], [linux-cifs@vger.kernel.org], [cifs-utils], [https://wiki.samba.org/index.php/LinuxCIFS_utils])
|
||||
AC_CONFIG_SRCDIR([replace.h])
|
||||
AC_CONFIG_HEADERS([config.h])
|
||||
AC_CONFIG_FILES([Makefile contrib/Makefile contrib/request-key.d/Makefile])
|
||||
diff --git a/getcifsacl.c b/getcifsacl.c
|
||||
index 8cbdb1d..b832c50 100644
|
||||
--- a/getcifsacl.c
|
||||
+++ b/getcifsacl.c
|
||||
@@ -38,7 +38,7 @@
|
||||
#include <sys/xattr.h>
|
||||
#include "cifsacl.h"
|
||||
|
||||
-static const char *prog = "getcifsacl";
|
||||
+static const char *prog;
|
||||
|
||||
static void
|
||||
print_each_ace_mask(uint32_t mask)
|
||||
@@ -171,22 +171,37 @@ print_ace_type(uint8_t acetype, int raw)
|
||||
}
|
||||
}
|
||||
|
||||
+/*
|
||||
+ * Winbind keeps wbcDomainSid fields in host-endian. So, we must convert from
|
||||
+ * little endian here so that winbind will understand correctly.
|
||||
+ */
|
||||
+static void
|
||||
+convert_sid_endianness(struct cifs_sid *sid)
|
||||
+{
|
||||
+ int i;
|
||||
+
|
||||
+ for (i = 0; i < sid->num_subauth; i++)
|
||||
+ sid->sub_auth[i] = le32toh(sid->sub_auth[i]);
|
||||
+}
|
||||
+
|
||||
static void
|
||||
-print_sid(struct wbcDomainSid *sidptr, int raw)
|
||||
+print_sid(struct cifs_sid *sidptr, int raw)
|
||||
{
|
||||
int i;
|
||||
- int num_auths;
|
||||
- int num_auth = MAX_NUM_AUTHS;
|
||||
wbcErr rc;
|
||||
char *domain_name = NULL;
|
||||
char *sidname = NULL;
|
||||
enum wbcSidType sntype;
|
||||
+ unsigned long long id_auth_val;
|
||||
+
|
||||
+ convert_sid_endianness(sidptr);
|
||||
|
||||
if (raw)
|
||||
goto print_sid_raw;
|
||||
|
||||
- rc = wbcLookupSid(sidptr, &domain_name, &sidname, &sntype);
|
||||
- if (!rc) {
|
||||
+ rc = wbcLookupSid((struct wbcDomainSid *)sidptr, &domain_name,
|
||||
+ &sidname, &sntype);
|
||||
+ if (WBC_ERROR_IS_OK(rc)) {
|
||||
printf("%s", domain_name);
|
||||
if (strlen(domain_name))
|
||||
printf("%c", '\\');
|
||||
@@ -195,29 +210,41 @@ print_sid(struct wbcDomainSid *sidptr, int raw)
|
||||
}
|
||||
|
||||
print_sid_raw:
|
||||
- num_auths = sidptr->num_auths;
|
||||
- printf("S");
|
||||
- printf("-%d", sidptr->sid_rev_num);
|
||||
- for (i = 0; i < num_auth; ++i)
|
||||
- if (sidptr->id_auth[i])
|
||||
- printf("-%d", sidptr->id_auth[i]);
|
||||
- for (i = 0; i < num_auths; i++)
|
||||
- printf("-%u", le32toh(sidptr->sub_auths[i]));
|
||||
+ printf("S-%hhu", sidptr->revision);
|
||||
+
|
||||
+ id_auth_val = (unsigned long long)sidptr->authority[5];
|
||||
+ id_auth_val += (unsigned long long)sidptr->authority[4] << 8;
|
||||
+ id_auth_val += (unsigned long long)sidptr->authority[3] << 16;
|
||||
+ id_auth_val += (unsigned long long)sidptr->authority[2] << 24;
|
||||
+ id_auth_val += (unsigned long long)sidptr->authority[1] << 32;
|
||||
+ id_auth_val += (unsigned long long)sidptr->authority[0] << 48;
|
||||
+
|
||||
+ /*
|
||||
+ * MS-DTYP states that if the authority is >= 2^32, then it should be
|
||||
+ * expressed as a hex value.
|
||||
+ */
|
||||
+ if (id_auth_val <= UINT_MAX)
|
||||
+ printf("-%llu", id_auth_val);
|
||||
+ else
|
||||
+ printf("-0x%llx", id_auth_val);
|
||||
+
|
||||
+ for (i = 0; i < sidptr->num_subauth; i++)
|
||||
+ printf("-%u", sidptr->sub_auth[i]);
|
||||
}
|
||||
|
||||
static void
|
||||
print_ace(struct cifs_ace *pace, char *end_of_acl, int raw)
|
||||
{
|
||||
- /* validate that we do not go past end of acl */
|
||||
-
|
||||
+ /* 16 == size of cifs_ace sans the cifs_sid */
|
||||
if (le16toh(pace->size) < 16)
|
||||
return;
|
||||
|
||||
+ /* validate that we do not go past end of acl */
|
||||
if (end_of_acl < (char *)pace + le16toh(pace->size))
|
||||
return;
|
||||
|
||||
printf("ACL:");
|
||||
- print_sid((struct wbcDomainSid *)&pace->sid, raw);
|
||||
+ print_sid((struct cifs_sid *)&pace->sid, raw);
|
||||
printf(":");
|
||||
print_ace_type(pace->type, raw);
|
||||
printf("/");
|
||||
@@ -261,14 +288,14 @@ parse_dacl(struct cifs_ctrl_acl *pdacl, char *end_of_acl, int raw)
|
||||
}
|
||||
|
||||
static int
|
||||
-parse_sid(struct wbcDomainSid *psid, char *end_of_acl, char *title, int raw)
|
||||
+parse_sid(struct cifs_sid *psid, char *end_of_acl, char *title, int raw)
|
||||
{
|
||||
if (end_of_acl < (char *)psid + 8)
|
||||
return -EINVAL;
|
||||
|
||||
if (title)
|
||||
printf("%s:", title);
|
||||
- print_sid((struct wbcDomainSid *)psid, raw);
|
||||
+ print_sid((struct cifs_sid *)psid, raw);
|
||||
printf("\n");
|
||||
|
||||
return 0;
|
||||
@@ -280,15 +307,15 @@ parse_sec_desc(struct cifs_ntsd *pntsd, ssize_t acl_len, int raw)
|
||||
int rc;
|
||||
uint32_t dacloffset;
|
||||
char *end_of_acl = ((char *)pntsd) + acl_len;
|
||||
- struct wbcDomainSid *owner_sid_ptr, *group_sid_ptr;
|
||||
+ struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
||||
struct cifs_ctrl_acl *dacl_ptr; /* no need for SACL ptr */
|
||||
|
||||
if (pntsd == NULL)
|
||||
return -EIO;
|
||||
|
||||
- owner_sid_ptr = (struct wbcDomainSid *)((char *)pntsd +
|
||||
+ owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
||||
le32toh(pntsd->osidoffset));
|
||||
- group_sid_ptr = (struct wbcDomainSid *)((char *)pntsd +
|
||||
+ group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
|
||||
le32toh(pntsd->gsidoffset));
|
||||
dacloffset = le32toh(pntsd->dacloffset);
|
||||
dacl_ptr = (struct cifs_ctrl_acl *)((char *)pntsd + dacloffset);
|
||||
@@ -333,6 +360,7 @@ main(const int argc, char *const argv[])
|
||||
size_t bufsize = BUFSIZE;
|
||||
char *filename, *attrval;
|
||||
|
||||
+ prog = basename(argv[0]);
|
||||
openlog(prog, 0, LOG_DAEMON);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "r:v", NULL, NULL)) != -1) {
|
||||
diff --git a/mount.cifs.c b/mount.cifs.c
|
||||
index 756fce2..9cf58a5 100644
|
||||
--- a/mount.cifs.c
|
||||
+++ b/mount.cifs.c
|
||||
@@ -1335,6 +1335,7 @@ static int parse_unc(const char *unc_name, struct parsed_mount_info *parsed_info
|
||||
}
|
||||
|
||||
/* Set up "host" and "share" pointers based on UNC format. */
|
||||
+ /* TODO: Remove support for NFS syntax as of cifs-utils-6.0. */
|
||||
if (strncmp(unc_name, "//", 2) && strncmp(unc_name, "\\\\", 2)) {
|
||||
/*
|
||||
* check for nfs syntax (server:/share/prepath)
|
||||
@@ -1351,6 +1352,9 @@ static int parse_unc(const char *unc_name, struct parsed_mount_info *parsed_info
|
||||
share++;
|
||||
if (*share == '/')
|
||||
++share;
|
||||
+ fprintf(stderr, "WARNING: using NFS syntax for mounting CIFS "
|
||||
+ "shares is deprecated and will be removed in cifs-utils"
|
||||
+ "-6.0. Please migrate to UNC syntax.\n");
|
||||
} else {
|
||||
host = unc_name + 2;
|
||||
hostlen = strcspn(host, "/\\");
|
||||
diff --git a/setcifsacl.1 b/setcifsacl.1
|
||||
index 550d23d..3dd755c 100644
|
||||
--- a/setcifsacl.1
|
||||
+++ b/setcifsacl.1
|
||||
@@ -30,6 +30,10 @@ This tool is part of the cifs-utils suite\&.
|
||||
setcifsacl is a userspace helper program for the Linux CIFS client file system. It is intended to alter an ACL of a security descriptor for a file system object. It is best utilized when an option of cifsacl is specified when mounting a cifs share in conjunction with winbind facility of Samba suite. Whether a security descriptor to be set is applied or not is determined by the CIFS/SMB server.
|
||||
.SH "OPTIONS"
|
||||
.PP
|
||||
+-h
|
||||
+.RS 4
|
||||
+Print usage message and exit.
|
||||
+.RE
|
||||
\-v
|
||||
.RS 4
|
||||
Print version number and exit\&.
|
||||
diff --git a/setcifsacl.c b/setcifsacl.c
|
||||
index 29b7b93..5016264 100644
|
||||
--- a/setcifsacl.c
|
||||
+++ b/setcifsacl.c
|
||||
@@ -39,23 +39,42 @@
|
||||
#include <sys/xattr.h>
|
||||
#include "cifsacl.h"
|
||||
|
||||
-static const char *prog = "setcifsacl";
|
||||
+static const char *prog;
|
||||
+
|
||||
+enum setcifsacl_actions {
|
||||
+ ActUnknown = -1,
|
||||
+ ActDelete,
|
||||
+ ActModify,
|
||||
+ ActAdd,
|
||||
+ ActSet
|
||||
+};
|
||||
|
||||
static void
|
||||
-copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
- int numaces, int acessize)
|
||||
+copy_cifs_sid(struct cifs_sid *dst, const struct cifs_sid *src)
|
||||
{
|
||||
int i;
|
||||
|
||||
+ dst->revision = src->revision;
|
||||
+ dst->num_subauth = src->num_subauth;
|
||||
+ for (i = 0; i < NUM_AUTHS; i++)
|
||||
+ dst->authority[i] = src->authority[i];
|
||||
+ for (i = 0; i < src->num_subauth; i++)
|
||||
+ dst->sub_auth[i] = src->sub_auth[i];
|
||||
+}
|
||||
+
|
||||
+static void
|
||||
+copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
+ int numaces, int acessize)
|
||||
+{
|
||||
int osidsoffset, gsidsoffset, dacloffset;
|
||||
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
|
||||
struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
|
||||
struct cifs_ctrl_acl *dacl_ptr, *ndacl_ptr;
|
||||
|
||||
/* copy security descriptor control portion */
|
||||
- osidsoffset = htole32(pntsd->osidoffset);
|
||||
- gsidsoffset = htole32(pntsd->gsidoffset);
|
||||
- dacloffset = htole32(pntsd->dacloffset);
|
||||
+ osidsoffset = le32toh(pntsd->osidoffset);
|
||||
+ gsidsoffset = le32toh(pntsd->gsidoffset);
|
||||
+ dacloffset = le32toh(pntsd->dacloffset);
|
||||
|
||||
pnntsd->revision = pntsd->revision;
|
||||
pnntsd->type = pntsd->type;
|
||||
@@ -73,24 +92,12 @@ copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
/* copy owner sid */
|
||||
owner_sid_ptr = (struct cifs_sid *)((char *)pntsd + osidsoffset);
|
||||
nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + osidsoffset);
|
||||
-
|
||||
- nowner_sid_ptr->revision = owner_sid_ptr->revision;
|
||||
- nowner_sid_ptr->num_subauth = owner_sid_ptr->num_subauth;
|
||||
- for (i = 0; i < 6; i++)
|
||||
- nowner_sid_ptr->authority[i] = owner_sid_ptr->authority[i];
|
||||
- for (i = 0; i < 5; i++)
|
||||
- nowner_sid_ptr->sub_auth[i] = owner_sid_ptr->sub_auth[i];
|
||||
+ copy_cifs_sid(nowner_sid_ptr, owner_sid_ptr);
|
||||
|
||||
/* copy group sid */
|
||||
group_sid_ptr = (struct cifs_sid *)((char *)pntsd + gsidsoffset);
|
||||
ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + gsidsoffset);
|
||||
-
|
||||
- ngroup_sid_ptr->revision = group_sid_ptr->revision;
|
||||
- ngroup_sid_ptr->num_subauth = group_sid_ptr->num_subauth;
|
||||
- for (i = 0; i < 6; i++)
|
||||
- ngroup_sid_ptr->authority[i] = group_sid_ptr->authority[i];
|
||||
- for (i = 0; i < 5; i++)
|
||||
- ngroup_sid_ptr->sub_auth[i] = group_sid_ptr->sub_auth[i];
|
||||
+ copy_cifs_sid(ngroup_sid_ptr, group_sid_ptr);
|
||||
|
||||
return;
|
||||
}
|
||||
@@ -98,20 +105,13 @@ copy_sec_desc(const struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
|
||||
static int
|
||||
copy_ace(struct cifs_ace *dace, struct cifs_ace *sace)
|
||||
{
|
||||
- int i;
|
||||
-
|
||||
dace->type = sace->type;
|
||||
dace->flags = sace->flags;
|
||||
- dace->access_req = htole32(sace->access_req);
|
||||
+ dace->access_req = sace->access_req;
|
||||
|
||||
- dace->sid.revision = sace->sid.revision;
|
||||
- dace->sid.num_subauth = sace->sid.num_subauth;
|
||||
- for (i = 0; i < 6; i++)
|
||||
- dace->sid.authority[i] = sace->sid.authority[i];
|
||||
- for (i = 0; i < sace->sid.num_subauth; i++)
|
||||
- dace->sid.sub_auth[i] = sace->sid.sub_auth[i];
|
||||
+ copy_cifs_sid(&dace->sid, &sace->sid);
|
||||
|
||||
- dace->size = htole16(sace->size);
|
||||
+ dace->size = sace->size;
|
||||
|
||||
return dace->size;
|
||||
}
|
||||
@@ -126,7 +126,7 @@ compare_aces(struct cifs_ace *sace, struct cifs_ace *dace, int compflags)
|
||||
return 0;
|
||||
if (dace->sid.num_subauth != sace->sid.num_subauth)
|
||||
return 0;
|
||||
- for (i = 0; i < 6; i++) {
|
||||
+ for (i = 0; i < NUM_AUTHS; i++) {
|
||||
if (dace->sid.authority[i] != sace->sid.authority[i])
|
||||
return 0;
|
||||
}
|
||||
@@ -147,7 +147,7 @@ compare_aces(struct cifs_ace *sace, struct cifs_ace *dace, int compflags)
|
||||
}
|
||||
|
||||
if (compflags & COMPMASK) {
|
||||
- if (dace->access_req != htole32(sace->access_req))
|
||||
+ if (dace->access_req != sace->access_req)
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -329,19 +329,16 @@ get_numfaces(struct cifs_ntsd *pntsd, ssize_t acl_len,
|
||||
struct cifs_ctrl_acl *ldaclptr;
|
||||
char *end_of_acl = ((char *)pntsd) + acl_len;
|
||||
|
||||
- if (pntsd == NULL)
|
||||
- return 0;
|
||||
-
|
||||
dacloffset = le32toh(pntsd->dacloffset);
|
||||
if (!dacloffset)
|
||||
return 0;
|
||||
- else {
|
||||
- ldaclptr = (struct cifs_ctrl_acl *)((char *)pntsd + dacloffset);
|
||||
- /* validate that we do not go past end of acl */
|
||||
- if (end_of_acl >= (char *)ldaclptr + le16toh(ldaclptr->size)) {
|
||||
- numfaces = le32toh(ldaclptr->num_aces);
|
||||
- *daclptr = ldaclptr;
|
||||
- }
|
||||
+
|
||||
+ ldaclptr = (struct cifs_ctrl_acl *)((char *)pntsd + dacloffset);
|
||||
+
|
||||
+ /* validate that we do not go past end of acl */
|
||||
+ if (end_of_acl >= (char *)ldaclptr + le16toh(ldaclptr->size)) {
|
||||
+ numfaces = le32toh(ldaclptr->num_aces);
|
||||
+ *daclptr = ldaclptr;
|
||||
}
|
||||
|
||||
return numfaces;
|
||||
@@ -391,33 +388,40 @@ build_fetched_aces_ret:
|
||||
static int
|
||||
verify_ace_sid(char *sidstr, struct cifs_sid *sid)
|
||||
{
|
||||
- int rc;
|
||||
- char *lstr;
|
||||
- struct passwd *winpswdptr;
|
||||
-
|
||||
- lstr = strstr(sidstr, "\\"); /* everything before | */
|
||||
- if (lstr)
|
||||
- ++lstr;
|
||||
- else
|
||||
- lstr = sidstr;
|
||||
-
|
||||
- /* Check if it is a (raw) SID (string) */
|
||||
- rc = wbcStringToSid(lstr, (struct wbcDomainSid *)sid);
|
||||
- if (!rc)
|
||||
- return rc;
|
||||
-
|
||||
- /* Check if it a name (string) which can be resolved to a SID*/
|
||||
- rc = wbcGetpwnam(lstr, &winpswdptr);
|
||||
- if (rc) {
|
||||
- printf("%s: Invalid user name: %s\n", __func__, sidstr);
|
||||
- return rc;
|
||||
- }
|
||||
- rc = wbcUidToSid(winpswdptr->pw_uid, (struct wbcDomainSid *)sid);
|
||||
- if (rc) {
|
||||
- printf("%s: Invalid user: %s\n", __func__, sidstr);
|
||||
+ int i;
|
||||
+ wbcErr rc;
|
||||
+ char *name, *domain;
|
||||
+ enum wbcSidType type;
|
||||
+
|
||||
+ name = strchr(sidstr, '\\');
|
||||
+ if (!name) {
|
||||
+ /* might be a raw string representation of SID */
|
||||
+ rc = wbcStringToSid(sidstr, (struct wbcDomainSid *)sid);
|
||||
+ if (WBC_ERROR_IS_OK(rc))
|
||||
+ goto fix_endianness;
|
||||
+
|
||||
+ domain = "";
|
||||
+ name = sidstr;
|
||||
+ } else {
|
||||
+ domain = sidstr;
|
||||
+ *name = '\0';
|
||||
+ ++name;
|
||||
+ }
|
||||
+
|
||||
+ rc = wbcLookupName(domain, name, (struct wbcDomainSid *)sid, &type);
|
||||
+ if (!WBC_ERROR_IS_OK(rc)) {
|
||||
+ printf("%s: Error converting %s\\%s to SID: %s\n",
|
||||
+ __func__, domain, name, wbcErrorString(rc));
|
||||
return rc;
|
||||
}
|
||||
|
||||
+fix_endianness:
|
||||
+ /*
|
||||
+ * Winbind keeps wbcDomainSid fields in host-endian. So, we must
|
||||
+ * convert that to little endian since the server will expect that.
|
||||
+ */
|
||||
+ for (i = 0; i < sid->num_subauth; i++)
|
||||
+ sid->sub_auth[i] = htole32(sid->sub_auth[i]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -643,92 +647,77 @@ build_cmdline_aces_ret:
|
||||
}
|
||||
|
||||
static char **
|
||||
-parse_cmdline_aces(char *optarg, int numcaces)
|
||||
+parse_cmdline_aces(char *acelist, int numcaces)
|
||||
{
|
||||
int i = 0, len;
|
||||
char *acestr, *vacestr, **arrptr = NULL;
|
||||
|
||||
- errno = EINVAL;
|
||||
arrptr = (char **)malloc(numcaces * sizeof(char *));
|
||||
if (!arrptr) {
|
||||
- printf("%s: Error %d allocating char array\n", __func__, errno);
|
||||
+ printf("%s: Unable to allocate char array\n", __func__);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
while (i < numcaces) {
|
||||
- acestr = strtok(optarg, ","); /* everything before , */
|
||||
- if (acestr) {
|
||||
- vacestr = strstr(acestr, "ACL:"); /* ace as ACL:*" */
|
||||
- if (vacestr) {
|
||||
- vacestr = strchr(vacestr, ':');
|
||||
- if (vacestr)
|
||||
- ++vacestr; /* go past : */
|
||||
- if (vacestr) {
|
||||
- len = strlen(vacestr);
|
||||
- arrptr[i] = malloc(len + 1);
|
||||
- if (!arrptr[i])
|
||||
- goto parse_cmdline_aces_ret;
|
||||
- strcpy(arrptr[i], vacestr);
|
||||
- ++i;
|
||||
- } else
|
||||
- goto parse_cmdline_aces_ret;
|
||||
- } else
|
||||
- goto parse_cmdline_aces_ret;
|
||||
- } else
|
||||
- goto parse_cmdline_aces_ret;
|
||||
- optarg = NULL;
|
||||
- }
|
||||
- errno = 0;
|
||||
+ acestr = strtok(acelist, ","); /* everything before , */
|
||||
+ if (!acestr)
|
||||
+ goto parse_cmdline_aces_err;
|
||||
+
|
||||
+ vacestr = strstr(acestr, "ACL:"); /* ace as ACL:*" */
|
||||
+ if (!vacestr)
|
||||
+ goto parse_cmdline_aces_err;
|
||||
+ vacestr += 4; /* skip past "ACL:" */
|
||||
+ if (*vacestr) {
|
||||
+ arrptr[i] = vacestr;
|
||||
+ ++i;
|
||||
+ }
|
||||
+ acelist = NULL;
|
||||
+ }
|
||||
return arrptr;
|
||||
|
||||
-parse_cmdline_aces_ret:
|
||||
- printf("%s: Error %d parsing ACEs\n", __func__, errno);
|
||||
- for (; i >= 0; --i)
|
||||
- free(arrptr[i]);
|
||||
+parse_cmdline_aces_err:
|
||||
+ printf("%s: Error parsing ACEs\n", __func__);
|
||||
free(arrptr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
+/* How many aces were provided on the command-line? Count the commas. */
|
||||
static unsigned int
|
||||
-get_numcaces(const char *optarg)
|
||||
+get_numcaces(const char *aces)
|
||||
{
|
||||
int i, len;
|
||||
- unsigned int numcaces = 1;
|
||||
+ unsigned int num = 1;
|
||||
+ const char *current;
|
||||
|
||||
- if (!optarg)
|
||||
- return 0;
|
||||
+ current = aces;
|
||||
+ while((current = strchr(current, ',')))
|
||||
+ ++num;
|
||||
|
||||
- len = strlen(optarg);
|
||||
- for (i = 0; i < len; ++i) {
|
||||
- if (*(optarg + i) == ',')
|
||||
- ++numcaces;
|
||||
- }
|
||||
-
|
||||
- return numcaces;
|
||||
+ return num;
|
||||
}
|
||||
|
||||
static int
|
||||
setacl_action(struct cifs_ntsd *pntsd, struct cifs_ntsd **npntsd,
|
||||
ssize_t *bufsize, struct cifs_ace **facesptr, int numfaces,
|
||||
struct cifs_ace **cacesptr, int numcaces,
|
||||
- int maction)
|
||||
+ enum setcifsacl_actions maction)
|
||||
{
|
||||
int rc = 1;
|
||||
|
||||
switch (maction) {
|
||||
- case 0:
|
||||
+ case ActDelete:
|
||||
rc = ace_delete(pntsd, npntsd, bufsize, facesptr,
|
||||
numfaces, cacesptr, numcaces);
|
||||
break;
|
||||
- case 1:
|
||||
+ case ActModify:
|
||||
rc = ace_modify(pntsd, npntsd, bufsize, facesptr,
|
||||
numfaces, cacesptr, numcaces);
|
||||
break;
|
||||
- case 2:
|
||||
+ case ActAdd:
|
||||
rc = ace_add(pntsd, npntsd, bufsize, facesptr,
|
||||
numfaces, cacesptr, numcaces);
|
||||
break;
|
||||
- case 3:
|
||||
+ case ActSet:
|
||||
rc = ace_set(pntsd, npntsd, bufsize, cacesptr, numcaces);
|
||||
break;
|
||||
default:
|
||||
@@ -771,52 +760,62 @@ setcifsacl_usage(void)
|
||||
int
|
||||
main(const int argc, char *const argv[])
|
||||
{
|
||||
- int i, rc, c, numcaces, numfaces, maction = -1;
|
||||
+ int i, rc, c, numcaces, numfaces;
|
||||
+ enum setcifsacl_actions maction = ActUnknown;
|
||||
ssize_t attrlen, bufsize = BUFSIZE;
|
||||
- char *filename, *attrval, **arrptr = NULL;
|
||||
+ char *ace_list, *filename, *attrval, **arrptr = NULL;
|
||||
struct cifs_ctrl_acl *daclptr = NULL;
|
||||
struct cifs_ace **cacesptr = NULL, **facesptr = NULL;
|
||||
struct cifs_ntsd *ntsdptr = NULL;
|
||||
|
||||
+ prog = basename(argv[0]);
|
||||
+
|
||||
openlog(prog, 0, LOG_DAEMON);
|
||||
|
||||
- c = getopt(argc, argv, "v:D:M:a:S:?");
|
||||
+ c = getopt(argc, argv, "hvD:M:a:S:");
|
||||
switch (c) {
|
||||
- case 'v':
|
||||
- printf("Version: %s\n", VERSION);
|
||||
- goto out;
|
||||
case 'D':
|
||||
- maction = 0;
|
||||
+ maction = ActDelete;
|
||||
+ ace_list = optarg;
|
||||
break;
|
||||
case 'M':
|
||||
- maction = 1;
|
||||
+ maction = ActModify;
|
||||
+ ace_list = optarg;
|
||||
break;
|
||||
case 'a':
|
||||
- maction = 2;
|
||||
+ maction = ActAdd;
|
||||
+ ace_list = optarg;
|
||||
break;
|
||||
case 'S':
|
||||
- maction = 3;
|
||||
+ maction = ActSet;
|
||||
+ ace_list = optarg;
|
||||
break;
|
||||
- case '?':
|
||||
+ case 'h':
|
||||
setcifsacl_usage();
|
||||
return 0;
|
||||
+ case 'v':
|
||||
+ printf("Version: %s\n", VERSION);
|
||||
+ return 0;
|
||||
default:
|
||||
- break;
|
||||
+ setcifsacl_usage();
|
||||
+ return -1;
|
||||
}
|
||||
|
||||
+ /* We expect 1 argument in addition to the option */
|
||||
if (argc != 4) {
|
||||
setcifsacl_usage();
|
||||
return -1;
|
||||
}
|
||||
filename = argv[3];
|
||||
|
||||
- numcaces = get_numcaces(optarg);
|
||||
- if (!numcaces) {
|
||||
+ if (!ace_list) {
|
||||
printf("%s: No valid ACEs specified\n", __func__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
- arrptr = parse_cmdline_aces(optarg, numcaces);
|
||||
+ numcaces = get_numcaces(ace_list);
|
||||
+
|
||||
+ arrptr = parse_cmdline_aces(ace_list, numcaces);
|
||||
if (!arrptr)
|
||||
goto setcifsacl_numcaces_ret;
|
||||
|
||||
@@ -850,7 +849,7 @@ cifsacl:
|
||||
}
|
||||
|
||||
numfaces = get_numfaces((struct cifs_ntsd *)attrval, attrlen, &daclptr);
|
||||
- if (!numfaces && maction != 2) { /* if we are not adding aces */
|
||||
+ if (!numfaces && maction != ActAdd) { /* if we are not adding aces */
|
||||
printf("%s: Empty DACL\n", __func__);
|
||||
goto setcifsacl_facenum_ret;
|
||||
}
|
||||
@@ -870,7 +869,6 @@ cifsacl:
|
||||
printf("%s: setxattr error: %s\n", __func__, strerror(errno));
|
||||
goto setcifsacl_facenum_ret;
|
||||
|
||||
-out:
|
||||
return 0;
|
||||
|
||||
setcifsacl_action_ret:
|
||||
@@ -890,8 +888,6 @@ setcifsacl_cmdlineverify_ret:
|
||||
free(cacesptr);
|
||||
|
||||
setcifsacl_cmdlineparse_ret:
|
||||
- for (i = 0; i < numcaces; ++i)
|
||||
- free(arrptr[i]);
|
||||
free(arrptr);
|
||||
|
||||
setcifsacl_numcaces_ret:
|
@ -3,7 +3,7 @@
|
||||
|
||||
Name: cifs-utils
|
||||
Version: 5.7
|
||||
Release: 1%{pre_release}%{?dist}
|
||||
Release: 2%{pre_release}%{?dist}
|
||||
Summary: Utilities for mounting and managing CIFS mounts
|
||||
|
||||
Group: System Environment/Daemons
|
||||
@ -13,6 +13,7 @@ BuildRoot: %{_tmppath}/%{name}-%{version}%{pre_release}-%{release}-root-%(%
|
||||
|
||||
Source0: ftp://ftp.samba.org/pub/linux-cifs/cifs-utils/%{name}-%{version}%{pre_release}.tar.bz2
|
||||
|
||||
Patch1: cifs-utils-5.8-pre1.patch
|
||||
BuildRequires: libcap-ng-devel libtalloc-devel krb5-devel keyutils-libs-devel autoconf automake libwbclient-devel
|
||||
Requires: keyutils
|
||||
|
||||
@ -26,6 +27,7 @@ file system.
|
||||
|
||||
%prep
|
||||
%setup -q -n %{name}-%{version}%{pre_release}
|
||||
%patch1 -p1
|
||||
|
||||
%build
|
||||
%configure --prefix=/usr
|
||||
@ -60,6 +62,9 @@ rm -rf %{buildroot}
|
||||
%config(noreplace) %{_sysconfdir}/request-key.d/cifs.spnego.conf
|
||||
|
||||
%changelog
|
||||
* Sun Nov 04 2012 Jeff Layton <jlayton@redhat.com> 5.7-2
|
||||
- update to latest patches queued for 5.8. Mostly idmapping and ACL tool fixes.
|
||||
|
||||
* Tue Oct 09 2012 Jeff Layton <jlayton@redhat.com> 5.7-1
|
||||
- update to 5.7
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user