#include <string.h>
#include <getopt.h>
-#include <syslog.h>
#include <stdint.h>
#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <errno.h>
#include <limits.h>
-#include <wbclient.h>
#include <ctype.h>
#include <sys/xattr.h>
-#include "cifsacl.h"
-static const char *prog;
+#include "cifsacl.h"
+#include "idmap_plugin.h"
enum setcifsacl_actions {
ActUnknown = -1,
ActSet
};
+static void *plugin_handle;
+
static void
copy_cifs_sid(struct cifs_sid *dst, const struct cifs_sid *src)
{
ace_set(struct cifs_ntsd *pntsd, struct cifs_ntsd **npntsd, ssize_t *bufsize,
struct cifs_ace **cacesptr, int numcaces)
{
- int i, rc, acessize = 0;
+ int i, rc, size = 0, acessize = 0;
size_t acesoffset;
char *acesptr;
acesptr = (char *)*npntsd + acesoffset;
for (i = 0; i < numcaces; ++i) {
- acessize += copy_ace((struct cifs_ace *)acesptr, cacesptr[i]);
- acesptr += sizeof(struct cifs_ace);
+ size = copy_ace((struct cifs_ace *)acesptr, cacesptr[i]);
+ acessize += size;
+ acesptr += size;
}
copy_sec_desc(pntsd, *npntsd, numcaces, acessize);
acesptr = (char *)*npntsd + acesoffset;
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;
-}
-static int
-verify_ace_sid(char *sidstr, struct cifs_sid *sid)
-{
- 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;
+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
}
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;
}
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;
goto build_cmdline_aces_ret;
}
- if (verify_ace_sid(acesid, &cacesptr[i]->sid)) {
- printf("%s: Invalid SID: %s\n", __func__, arrptr[i]);
+ if (str_to_sid(plugin_handle, acesid, &cacesptr[i]->sid)) {
+ printf("%s: Invalid SID (%s): %s\n", __func__, arrptr[i],
+ plugin_errmsg);
goto build_cmdline_aces_ret;
}
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 *acelist, int numcaces)
{
- int i = 0, len;
+ int i = 0;
char *acestr, *vacestr, **arrptr = NULL;
arrptr = (char **)malloc(numcaces * sizeof(char *));
static unsigned int
get_numcaces(const char *aces)
{
- int i, len;
unsigned int num = 1;
const char *current;
current = aces;
- while((current = strchr(current, ',')))
+ while((current = strchr(current, ','))) {
+ ++current;
++num;
+ }
return num;
}
}
static void
-setcifsacl_usage(void)
+setcifsacl_usage(const char *prog)
{
fprintf(stderr,
"%s: Alter CIFS/NTFS ACL in a security descriptor of a file object\n",
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, "hvD:M:a:S:");
switch (c) {
case 'D':
ace_list = optarg;
break;
case 'h':
- setcifsacl_usage();
+ setcifsacl_usage(basename(argv[0]));
return 0;
case 'v':
printf("Version: %s\n", VERSION);
return 0;
default:
- setcifsacl_usage();
+ setcifsacl_usage(basename(argv[0]));
return -1;
}
/* We expect 1 argument in addition to the option */
if (argc != 4) {
- setcifsacl_usage();
+ setcifsacl_usage(basename(argv[0]));
return -1;
}
filename = argv[3];
return -1;
}
+ if (init_plugin(&plugin_handle)) {
+ printf("ERROR: unable to initialize idmapping plugin: %s\n",
+ plugin_errmsg);
+ return -1;
+ }
+
numcaces = get_numcaces(ace_list);
arrptr = parse_cmdline_aces(ace_list, numcaces);
cifsacl:
if (bufsize >= XATTR_SIZE_MAX) {
- printf("%s: Buffer size %ld exceeds max size of %d\n",
+ printf("%s: Buffer size %zd exceeds max size of %d\n",
__func__, bufsize, XATTR_SIZE_MAX);
goto setcifsacl_cmdlineverify_ret;
}
goto setcifsacl_action_ret;
attrlen = setxattr(filename, ATTRNAME, ntsdptr, bufsize, 0);
- if (attrlen == -1)
+ if (attrlen == -1) {
printf("%s: setxattr error: %s\n", __func__, strerror(errno));
- goto setcifsacl_facenum_ret;
+ goto setcifsacl_facenum_ret;
+ }
+ exit_plugin(plugin_handle);
return 0;
setcifsacl_action_ret:
free(arrptr);
setcifsacl_numcaces_ret:
+ exit_plugin(plugin_handle);
return -1;
}