cifs.upcall: the exit code should be 0 when print version
[jlayton/cifs-utils.git] / setcifsacl.c
index ce136384561da0691f5a06a26c8f4cd2935d679f..4b38459df1972d2e94cbe0badcb3e483fcd1484e 100644 (file)
@@ -26,7 +26,6 @@
 
 #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,
@@ -49,6 +47,8 @@ enum setcifsacl_actions {
        ActSet
 };
 
+static void *plugin_handle;
+
 static void
 copy_cifs_sid(struct cifs_sid *dst, const struct cifs_sid *src)
 {
@@ -183,7 +183,7 @@ static int
 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;
 
@@ -193,8 +193,9 @@ ace_set(struct cifs_ntsd *pntsd, struct cifs_ntsd **npntsd, ssize_t *bufsize,
 
        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;
@@ -347,82 +348,36 @@ 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;
-}
 
-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
@@ -518,62 +473,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;
        }
 
@@ -587,8 +541,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;
@@ -611,8 +564,9 @@ build_cmdline_aces(char **arrptr, int numcaces)
                        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;
                }
 
@@ -634,13 +588,13 @@ 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;
@@ -649,7 +603,7 @@ build_cmdline_aces_ret:
 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 *));
@@ -685,13 +639,14 @@ parse_cmdline_aces_err:
 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;
 }
@@ -729,7 +684,7 @@ setacl_action(struct cifs_ntsd *pntsd, struct cifs_ntsd **npntsd,
 }
 
 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",
@@ -768,10 +723,6 @@ main(const int argc, char *const argv[])
        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':
@@ -791,19 +742,19 @@ main(const int argc, char *const argv[])
                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];
@@ -813,6 +764,12 @@ main(const int argc, char *const argv[])
                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);
@@ -825,7 +782,7 @@ main(const int argc, char *const argv[])
 
 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;
        }
@@ -865,10 +822,12 @@ cifsacl:
                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:
@@ -891,5 +850,6 @@ setcifsacl_cmdlineparse_ret:
        free(arrptr);
 
 setcifsacl_numcaces_ret:
+       exit_plugin(plugin_handle);
        return -1;
 }