diff --git a/.gitignore b/.gitignore index 9fdaa78..2bd24ea 100644 --- a/.gitignore +++ b/.gitignore @@ -12,3 +12,4 @@ cifs-utils-4.6.tar.bz2 /cifs-utils-5.5.tar.bz2 /cifs-utils-5.6.tar.bz2 /cifs-utils-5.7.tar.bz2 +/cifs-utils-5.8.tar.bz2 diff --git a/cifs-utils-5.8-pre1.patch b/cifs-utils-5.8-pre1.patch deleted file mode 100644 index 25f62f1..0000000 --- a/cifs-utils-5.8-pre1.patch +++ /dev/null @@ -1,1180 +0,0 @@ -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 - #include - -+#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..c576fc0 100644 ---- a/getcifsacl.c -+++ b/getcifsacl.c -@@ -31,6 +31,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -38,7 +39,7 @@ - #include - #include "cifsacl.h" - --static const char *prog = "getcifsacl"; -+static const char *prog; - - static void - print_each_ace_mask(uint32_t mask) -@@ -171,22 +172,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,36 +211,55 @@ 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 */ -+ uint16_t size; -+ -+ /* make sure we can safely get to "size" */ -+ if (end_of_acl < (char *)pace + offsetof(struct cifs_ace, size) + 1) -+ return; -+ -+ size = le16toh(pace->size); - -+ /* 16 == size of cifs_ace when cifs_sid has no subauths */ - 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("/"); - print_ace_flags(pace->flags, raw); - printf("/"); -- print_ace_mask(pace->access_req, raw); -- -+ print_ace_mask(le32toh(pace->access_req), raw); - - return; - } -@@ -261,14 +296,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 +315,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 +368,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..8891844 100644 ---- a/setcifsacl.c -+++ b/setcifsacl.c -@@ -39,23 +39,42 @@ - #include - #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,22 +105,15 @@ 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; -+ return le16toh(dace->size); - } - - static int -@@ -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; -@@ -350,74 +347,75 @@ get_numfaces(struct cifs_ntsd *pntsd, ssize_t acl_len, - static struct cifs_ace ** - build_fetched_aces(char *daclptr, int numfaces) - { -- int i, j, rc = 0, acl_size; -+ int i, acl_size; - char *acl_base; - struct cifs_ace *pace, **facesptr; - -- facesptr = (struct cifs_ace **)malloc(numfaces * -- sizeof(struct cifs_aces *)); -+ facesptr = calloc(numfaces, sizeof(struct cifs_aces *)); - if (!facesptr) { - printf("%s: Error %d allocating ACE array", - __func__, errno); -- rc = errno; -+ return facesptr; - } - - acl_base = daclptr; - acl_size = sizeof(struct cifs_ctrl_acl); - for (i = 0; i < numfaces; ++i) { - facesptr[i] = malloc(sizeof(struct cifs_ace)); -- if (!facesptr[i]) { -- rc = errno; -- goto build_fetched_aces_ret; -- } -+ if (!facesptr[i]) -+ goto build_fetched_aces_err; - pace = (struct cifs_ace *) (acl_base + acl_size); - memcpy(facesptr[i], pace, sizeof(struct cifs_ace)); - acl_base = (char *)pace; - acl_size = le16toh(pace->size); - } -- --build_fetched_aces_ret: -- if (rc) { -- printf("%s: Invalid fetched ace\n", __func__); -- if (i) { -- for (j = i; j >= 0; --j) -- free(facesptr[j]); -- } -- free(facesptr); -- } - return facesptr; -+ -+build_fetched_aces_err: -+ printf("%s: Invalid fetched ace\n", __func__); -+ for (i = 0; i < numfaces; ++i) -+ free(facesptr[i]); -+ free(facesptr); -+ return NULL; - } - - 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; - } - -@@ -514,62 +512,61 @@ verify_ace_flags(char *flagstr, uint8_t *flagval) - } - - static uint32_t --ace_mask_value(char *maskstr) -+ace_mask_value(char *mask) - { -- int i, len; -- uint32_t maskval = 0x0; -- char *lmask; -+ uint32_t maskval = 0; -+ char cur; - -- if (!strcmp(maskstr, "FULL")) -+ if (!strcmp(mask, "FULL")) - return FULL_CONTROL; -- else if (!strcmp(maskstr, "CHANGE")) -+ if (!strcmp(mask, "CHANGE")) - return CHANGE; -- else if (!strcmp(maskstr, "D")) -- return DELETE; -- else if (!strcmp(maskstr, "READ")) -+ if (!strcmp(mask, "READ")) - return EREAD; -- else { -- len = strlen(maskstr); -- lmask = maskstr; -- for (i = 0; i < len; ++i, ++lmask) { -- if (*lmask == 'R') -- maskval |= EREAD; -- else if (*lmask == 'W') -- maskval |= EWRITE; -- else if (*lmask == 'X') -- maskval |= EXEC; -- else if (*lmask == 'D') -- maskval |= DELETE; -- else if (*lmask == 'P') -- maskval |= WRITE_DAC; -- else if (*lmask == 'O') -- maskval |= WRITE_OWNER; -- else -- return 0; -+ -+ while((cur = *mask++)) { -+ switch(cur) { -+ case 'R': -+ maskval |= EREAD; -+ break; -+ case 'W': -+ maskval |= EWRITE; -+ break; -+ case 'X': -+ maskval |= EXEC; -+ break; -+ case 'D': -+ maskval |= DELETE; -+ break; -+ case 'P': -+ maskval |= WRITE_DAC; -+ break; -+ case 'O': -+ maskval |= WRITE_OWNER; -+ break; -+ default: -+ return 0; - } -- return maskval; - } -- -- return 0; -+ return maskval; - } - - static int - verify_ace_mask(char *maskstr, uint32_t *maskval) - { -- char *invalflag; -+ unsigned long val; -+ char *ep; - -- if (strstr(maskstr, "0x") || !strcmp(maskstr, "DELDHLD")) { -- *maskval = strtol(maskstr, &invalflag, 16); -- if (!invalflag) { -- printf("%s: Invalid mask: %s\n", __func__, maskstr); -- return 1; -- } -- } else -- *maskval = ace_mask_value(maskstr); -+ errno = 0; -+ val = strtoul(maskstr, &ep, 0); -+ if (errno == 0 && *ep == '\0') -+ *maskval = htole32((uint32_t)val); -+ else -+ *maskval = htole32(ace_mask_value(maskstr)); - - if (!*maskval) { -- printf("%s: Invalid mask %s and value: 0x%x\n", -- __func__, maskstr, *maskval); -+ printf("%s: Invalid mask %s (value 0x%x)\n", __func__, -+ maskstr, *maskval); - return 1; - } - -@@ -583,8 +580,7 @@ build_cmdline_aces(char **arrptr, int numcaces) - char *acesid, *acetype, *aceflag, *acemask; - struct cifs_ace **cacesptr; - -- cacesptr = (struct cifs_ace **)malloc(numcaces * -- sizeof(struct cifs_aces *)); -+ cacesptr = calloc(numcaces, sizeof(struct cifs_aces *)); - if (!cacesptr) { - printf("%s: Error %d allocating ACE array", __func__, errno); - return NULL; -@@ -630,105 +626,90 @@ build_cmdline_aces(char **arrptr, int numcaces) - goto build_cmdline_aces_ret; - } - -- cacesptr[i]->size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + -- (cacesptr[i]->sid.num_subauth * 4); -+ cacesptr[i]->size = htole16(1 + 1 + 2 + 4 + 1 + 1 + 6 + -+ cacesptr[i]->sid.num_subauth * 4); - } - return cacesptr; - - build_cmdline_aces_ret: -- for (; i >= 0; --i) -+ for (i = 0; i < numcaces; ++i) - free(cacesptr[i]); - free(cacesptr); - return NULL; - } - - 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; -+ 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; - } -- errno = 0; - 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; -- -- if (!optarg) -- return 0; -+ unsigned int num = 1; -+ const char *current; - -- len = strlen(optarg); -- for (i = 0; i < len; ++i) { -- if (*(optarg + i) == ',') -- ++numcaces; -- } -+ current = aces; -+ while((current = strchr(current, ','))) -+ ++num; - -- 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 +752,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 +841,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 +861,6 @@ cifsacl: - printf("%s: setxattr error: %s\n", __func__, strerror(errno)); - goto setcifsacl_facenum_ret; - --out: - return 0; - - setcifsacl_action_ret: -@@ -890,8 +880,6 @@ setcifsacl_cmdlineverify_ret: - free(cacesptr); - - setcifsacl_cmdlineparse_ret: -- for (i = 0; i < numcaces; ++i) -- free(arrptr[i]); - free(arrptr); - - setcifsacl_numcaces_ret: diff --git a/cifs-utils.spec b/cifs-utils.spec index efe6a1e..3d4996c 100644 --- a/cifs-utils.spec +++ b/cifs-utils.spec @@ -2,8 +2,8 @@ %define pre_release %nil Name: cifs-utils -Version: 5.7 -Release: 3%{pre_release}%{?dist} +Version: 5.8 +Release: 1%{pre_release}%{?dist} Summary: Utilities for mounting and managing CIFS mounts Group: System Environment/Daemons @@ -13,7 +13,6 @@ 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 @@ -27,7 +26,6 @@ file system. %prep %setup -q -n %{name}-%{version}%{pre_release} -%patch1 -p1 %build %configure --prefix=/usr @@ -62,6 +60,9 @@ rm -rf %{buildroot} %config(noreplace) %{_sysconfdir}/request-key.d/cifs.spnego.conf %changelog +* Sun Nov 11 2012 Jeff Layton 5.8-1 +- update to 5.8 + * Wed Nov 07 2012 Jeff Layton 5.7-3 - update to latest patches queued for 5.8. More idmapping and ACL tool fixes. diff --git a/sources b/sources index e0503c5..6535575 100644 --- a/sources +++ b/sources @@ -1 +1 @@ -4215f12be8663f65d2c21dbbbafbc7f8 cifs-utils-5.7.tar.bz2 +6aa9c4347780872fefe5823ac06a8ff3 cifs-utils-5.8.tar.bz2