@@ -23,6 +23,9 @@
#include <linux/fs.h>
#include <linux/slab.h>
+#include <linux/string.h>
+#include <keys/user-type.h>
+#include <linux/key-type.h>
#include "cifspdu.h"
#include "cifsglob.h"
#include "cifsacl.h"
@@ -52,6 +55,102 @@ static const struct cifs_sid sid_authusers = {
/* group users */
static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
+static int
+cifs_acl_key_instantiate(struct key *key, const void *data, size_t datalen)
+{
+ char *payload;
+
+ payload = kmalloc(datalen, GFP_KERNEL);
+ if (!payload)
+ return -ENOMEM;
+
+ memcpy(payload, data, datalen);
+ key->payload.data = payload;
+ return 0;
+}
+
+static void
+cifs_acl_key_destroy(struct key *key)
+{
+ kfree(key->payload.data);
+}
+
+struct key_type cifs_acl_key_type = {
+ .name = "cifs.cifs_acl",
+ .instantiate = cifs_acl_key_instantiate,
+ .destroy = cifs_acl_key_destroy,
+ .describe = user_describe,
+ .match = user_match,
+};
+
+static void
+sid_to_str(struct cifs_sid *sidptr, char *sidstr)
+{
+ int i;
+ unsigned long saval;
+ char *strptr;
+
+ strptr = sidstr;
+
+ sprintf(strptr, "%s", "S");
+ strptr = sidstr + strlen(sidstr);
+
+ sprintf(strptr, "-%d", sidptr->revision);
+ strptr = sidstr + strlen(sidstr);
+
+ for (i = 0; i < 6; ++i) {
+ if (sidptr->authority[i]) {
+ sprintf(strptr, "-%d", sidptr->authority[i]);
+ strptr = sidstr + strlen(sidstr);
+ }
+ }
+
+ for (i = 0; i < sidptr->num_subauth; ++i) {
+ saval = le32_to_cpu(sidptr->sub_auth[i]);
+ sprintf(strptr, "-%ld", saval);
+ strptr = sidstr + strlen(sidstr);
+ }
+}
+
+static int
+sid_to_id(struct cifs_sid *psid, struct cifs_fattr *fattr, uint sidtype)
+{
+ int rc = 0;
+ char *sidstr, *strptr;
+ struct key *idkey;
+
+ sidstr = kzalloc(SIDLEN, GFP_KERNEL);
+ if (!sidstr)
+ return -ENOMEM;
+ strptr = sidstr;
+
+ if (sidtype == SIDOWNER)
+ sprintf(strptr, "%s", "os:");
+ else if (sidtype == SIDGROUP)
+ sprintf(strptr, "%s", "gs:");
+ else {
+ rc = -EINVAL;
+ goto idresolve_err;
+ }
+ strptr = sidstr + strlen(sidstr);
+
+ sid_to_str(psid, strptr);
+
+ idkey = request_key(&cifs_acl_key_type, sidstr, "");
+ if (IS_ERR(idkey))
+ cFYI(1, "%s: idkey error: %d\n", __func__, -ENOKEY);
+ else {
+ if (sidtype == SIDOWNER)
+ fattr->cf_uid = *(unsigned long *)idkey->payload.value;
+ else if (sidtype == SIDGROUP)
+ fattr->cf_gid = *(unsigned long *)idkey->payload.value;
+ key_put(idkey);
+ }
+
+idresolve_err:
+ kfree(sidstr);
+ return rc;
+}
int match_sid(struct cifs_sid *ctsid)
{
@@ -438,7 +537,6 @@ static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
return 0;
}
-
static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
{
/* BB need to add parm so we can store the SID BB */
@@ -476,7 +574,7 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
struct cifs_fattr *fattr)
{
- int rc;
+ int rc = 0;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
char *end_of_acl = ((char *)pntsd) + acl_len;
@@ -500,10 +598,16 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
rc = parse_sid(owner_sid_ptr, end_of_acl);
if (rc)
return rc;
+ rc = sid_to_id(owner_sid_ptr, fattr, SIDOWNER);
+ if (rc)
+ cFYI(1, "Can't resolve SID to an uid");
rc = parse_sid(group_sid_ptr, end_of_acl);
if (rc)
return rc;
+ rc = sid_to_id(group_sid_ptr, fattr, SIDGROUP);
+ if (rc)
+ cFYI(1, "Can't resolve SID to a gid");
if (dacloffset)
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
@@ -511,14 +615,7 @@ static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
else
cFYI(1, "no ACL"); /* BB grant all or default perms? */
-/* cifscred->uid = owner_sid_ptr->rid;
- cifscred->gid = group_sid_ptr->rid;
- memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
- sizeof(struct cifs_sid));
- memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
- sizeof(struct cifs_sid)); */
-
- return 0;
+ return rc;
}
@@ -39,6 +39,10 @@
#define ACCESS_ALLOWED 0
#define ACCESS_DENIED 1
+#define SIDOWNER 1
+#define SIDGROUP 2
+#define SIDLEN 150 /* S- 1 revision- 6 authorities- max 5 sub authorities */
+
struct cifs_ntsd {
__le16 revision; /* revision level */
__le16 type;
@@ -76,6 +80,10 @@ struct cifs_wksid {
#ifdef CONFIG_CIFS_EXPERIMENTAL
+#ifdef __KERNEL__
+extern struct key_type cifs_acl_key_type;
+#endif /* KERNEL */
+
extern int match_sid(struct cifs_sid *);
extern int compare_sids(const struct cifs_sid *, const struct cifs_sid *);
@@ -46,6 +46,7 @@
#include <linux/mm.h>
#include <linux/key-type.h>
#include "cifs_spnego.h"
+#include "cifsacl.h"
#include "fscache.h"
#define CIFS_MAGIC_NUMBER 0xFF534D42 /* the first four bytes of SMB PDUs */
@@ -973,11 +974,16 @@ init_cifs(void)
rc = register_key_type(&cifs_spnego_key_type);
if (rc)
goto out_unregister_filesystem;
+ rc = register_key_type(&cifs_acl_key_type);
+ if (rc)
+ goto out_unregister_keytype;
#endif
return 0;
#ifdef CONFIG_CIFS_UPCALL
+out_unregister_keytype:
+ unregister_key_type(&cifs_spnego_key_type);
out_unregister_filesystem:
unregister_filesystem(&cifs_fs_type);
#endif
@@ -1004,6 +1010,7 @@ exit_cifs(void)
cifs_dfs_release_automount_timer();
#endif
#ifdef CONFIG_CIFS_UPCALL
+ unregister_key_type(&cifs_acl_key_type);
unregister_key_type(&cifs_spnego_key_type);
#endif
unregister_filesystem(&cifs_fs_type);