diff --git a/cifs-utils-5.8-pre1.patch b/cifs-utils-5.8-pre1.patch new file mode 100644 index 0000000..113345b --- /dev/null +++ b/cifs-utils-5.8-pre1.patch @@ -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 + #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..b832c50 100644 +--- a/getcifsacl.c ++++ b/getcifsacl.c +@@ -38,7 +38,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 +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 + #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: diff --git a/cifs-utils.spec b/cifs-utils.spec index 5350087..8bebab1 100644 --- a/cifs-utils.spec +++ b/cifs-utils.spec @@ -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 5.7-2 +- update to latest patches queued for 5.8. Mostly idmapping and ACL tool fixes. + * Tue Oct 09 2012 Jeff Layton 5.7-1 - update to 5.7