summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--setcifsacl.c92
1 files changed, 87 insertions, 5 deletions
diff --git a/setcifsacl.c b/setcifsacl.c
index 4b38459..ce708eb 100644
--- a/setcifsacl.c
+++ b/setcifsacl.c
@@ -48,6 +48,7 @@ enum setcifsacl_actions {
};
static void *plugin_handle;
+static bool plugin_loaded;
static void
copy_cifs_sid(struct cifs_sid *dst, const struct cifs_sid *src)
@@ -534,6 +535,83 @@ verify_ace_mask(char *maskstr, uint32_t *maskval)
return 0;
}
+#define AUTHORITY_MASK (~(0xffffffffffffULL))
+
+static int
+raw_str_to_sid(const char *str, struct cifs_sid *csid)
+{
+ const char *p;
+ char *q;
+ unsigned long long x;
+
+ /* Sanity check for either "S-" or "s-" */
+ if ((str[0] != 'S' && str[0] != 's') || (str[1]!='-')) {
+ plugin_errmsg = "SID string does not start with \"S-\"";
+ return -EINVAL;
+ }
+
+ /* Get the SID revision number */
+ p = str + 2;
+ x = strtoull(p, &q, 10);
+ if (x == 0 || x > UCHAR_MAX || !q || *q != '-') {
+ plugin_errmsg = "Invalid SID revision number";
+ return -EINVAL;
+ }
+ csid->revision = (uint8_t)x;
+
+ /*
+ * Next the Identifier Authority. This is stored in big-endian in a
+ * 6 byte array. If the authority value is > UINT_MAX, then it should
+ * be expressed as a hex value.
+ */
+ p = q + 1;
+ x = strtoull(p, &q, 0);
+ if ((x & AUTHORITY_MASK) || !q || *q !='-') {
+ plugin_errmsg = "Invalid SID authority";
+ return -EINVAL;
+ }
+ csid->authority[5] = (x & 0x0000000000ffULL);
+ csid->authority[4] = (x & 0x00000000ff00ULL) >> 8;
+ csid->authority[3] = (x & 0x000000ff0000ULL) >> 16;
+ csid->authority[2] = (x & 0x0000ff000000ULL) >> 24;
+ csid->authority[1] = (x & 0x00ff00000000ULL) >> 32;
+ csid->authority[0] = (x & 0xff0000000000ULL) >> 48;
+
+ /* now read the the subauthorities and store as __le32 vals */
+ p = q + 1;
+ csid->num_subauth = 0;
+ while (csid->num_subauth < SID_MAX_SUB_AUTHORITIES) {
+ x = strtoul(p, &q, 10);
+ if (p == q)
+ break;
+ if (x > UINT_MAX) {
+ plugin_errmsg = "Invalid sub authority value";
+ return -EINVAL;
+ }
+ csid->sub_auth[csid->num_subauth++] = htole32((uint32_t)x);
+
+ if (*q != '-')
+ break;
+ p = q + 1;
+ }
+
+ /* IF we ended early, then the SID could not be converted */
+ if (q && *q != '\0') {
+ plugin_errmsg = "Invalid sub authority value";
+ return -EINVAL;
+ }
+
+ return 0;
+}
+
+static int
+setcifsacl_str_to_sid(const char *str, struct cifs_sid *sid)
+{
+ if (plugin_loaded)
+ return str_to_sid(plugin_handle, str, sid);
+ return raw_str_to_sid(str, sid);
+}
+
static struct cifs_ace **
build_cmdline_aces(char **arrptr, int numcaces)
{
@@ -564,7 +642,7 @@ build_cmdline_aces(char **arrptr, int numcaces)
goto build_cmdline_aces_ret;
}
- if (str_to_sid(plugin_handle, acesid, &cacesptr[i]->sid)) {
+ if (setcifsacl_str_to_sid(acesid, &cacesptr[i]->sid)) {
printf("%s: Invalid SID (%s): %s\n", __func__, arrptr[i],
plugin_errmsg);
goto build_cmdline_aces_ret;
@@ -765,9 +843,12 @@ main(const int argc, char *const argv[])
}
if (init_plugin(&plugin_handle)) {
- printf("ERROR: unable to initialize idmapping plugin: %s\n",
- plugin_errmsg);
- return -1;
+ fprintf(stderr, "WARNING: unable to initialize idmapping "
+ "plugin. Only \"raw\" SID strings will be "
+ "accepted: %s\n", plugin_errmsg);
+ plugin_loaded = false;
+ } else {
+ plugin_loaded = true;
}
numcaces = get_numcaces(ace_list);
@@ -827,7 +908,8 @@ cifsacl:
goto setcifsacl_facenum_ret;
}
- exit_plugin(plugin_handle);
+ if (plugin_loaded)
+ exit_plugin(plugin_handle);
return 0;
setcifsacl_action_ret: