Skip to content

Commit

Permalink
[CIFS] CIFS ACL support part 3
Browse files Browse the repository at this point in the history
Signed-off-by: Shirish Pargaonkar <shirishp@us.ibm.com>
Signed-off-by: Steve French <sfrench@us.ibm.com>
  • Loading branch information
Steve French committed Oct 12, 2007
1 parent a013689 commit 297647c
Show file tree
Hide file tree
Showing 7 changed files with 141 additions and 22 deletions.
5 changes: 4 additions & 1 deletion fs/cifs/CHANGES
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,10 @@ which support the current POSIX Extensions to provide better semantics
(e.g. delete for open files opened with posix open). Take into
account umask on posix mkdir not just older style mkdir. Add
ability to mount to IPC$ share (which allows CIFS named pipes to be
opened, read and written as if they were files).
opened, read and written as if they were files). When 1st tree
connect fails (e.g. due to signing negotiation failure) fix
leak that causes cifsd not to stop and rmmod to fail to cleanup
cifs_request_buffers pool.

Version 1.50
------------
Expand Down
120 changes: 110 additions & 10 deletions fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -28,40 +28,134 @@
#include "cifsproto.h"
#include "cifs_debug.h"


#ifdef CONFIG_CIFS_EXPERIMENTAL

struct cifs_wksid wksidarr[NUM_WK_SIDS] = {
{{1, 0, {0, 0, 0, 0, 0, 0}, {0, 0, 0, 0, 0} }, "null user"},
{{1, 1, {0, 0, 0, 0, 0, 1}, {0, 0, 0, 0, 0} }, "nobody"},
{{1, 1, {0, 0, 0, 0, 0, 5}, {11, 0, 0, 0, 0} }, "net-users"},
{{1, 1, {0, 0, 0, 0, 0, 5}, {18, 0, 0, 0, 0} }, "sys"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {32, 544, 0, 0, 0} }, "root"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {32, 545, 0, 0, 0} }, "users"},
{{1, 2, {0, 0, 0, 0, 0, 5}, {32, 546, 0, 0, 0} }, "guest"}
};


/* security id for everyone */
static const struct cifs_sid sid_everyone =
{1, 1, {0, 0, 0, 0, 0, 0}, {} };
/* group users */
static const struct cifs_sid sid_user =
{1, 2 , {0, 0, 0, 0, 0, 5}, {} };


int match_sid(struct cifs_sid *ctsid)
{
int i, j;
int num_subauth, num_sat, num_saw;
struct cifs_sid *cwsid;

if (!ctsid)
return (-1);

for (i = 0; i < NUM_WK_SIDS; ++i) {
cwsid = &(wksidarr[i].cifssid);

/* compare the revision */
if (ctsid->revision != cwsid->revision)
continue;

/* compare all of the six auth values */
for (j = 0; j < 6; ++j) {
if (ctsid->authority[j] != cwsid->authority[j])
break;
}
if (j < 6)
continue; /* all of the auth values did not match */

/* compare all of the subauth values if any */
num_sat = cpu_to_le32(ctsid->num_subauth);
num_saw = cpu_to_le32(cwsid->num_subauth);
num_subauth = num_sat < num_saw ? num_sat : num_saw;
if (num_subauth) {
for (j = 0; j < num_subauth; ++j) {
if (ctsid->sub_auth[j] != cwsid->sub_auth[j])
break;
}
if (j < num_subauth)
continue; /* all sub_auth values do not match */
}

cFYI(1, ("matching sid: %s\n", wksidarr[i].sidname));
return (0); /* sids compare/match */
}

cFYI(1, ("No matching sid"));
return (-1);
}


int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
{
int i;
int num_subauth, num_sat, num_saw;

if ((!ctsid) || (!cwsid))
return (-1);

/* compare the revision */
if (ctsid->revision != cwsid->revision)
return (-1);

/* compare all of the six auth values */
for (i = 0; i < 6; ++i) {
if (ctsid->authority[i] != cwsid->authority[i])
return (-1);
}

/* compare all of the subauth values if any */
num_sat = cpu_to_le32(ctsid->num_subauth);
num_saw = cpu_to_le32(cwsid->num_subauth);
num_subauth = num_sat < num_saw ? num_sat : num_saw;
if (num_subauth) {
for (i = 0; i < num_subauth; ++i) {
if (ctsid->sub_auth[i] != cwsid->sub_auth[i])
return (-1);
}
}

return (0); /* sids compare/match */
}


static void parse_ace(struct cifs_ace *pace, char *end_of_acl)
{
int i;
int num_subauth;
__u32 *psub_auth;

/* validate that we do not go past end of acl */

/* XXX this if statement can be removed
if (end_of_acl < (char *)pace + sizeof(struct cifs_ace)) {
cERROR(1, ("ACL too small to parse ACE"));
return;
}
} */

num_subauth = cpu_to_le32(pace->num_subauth);
if (num_subauth) {
psub_auth = (__u32 *)((char *)pace + sizeof(struct cifs_ace));
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("ACE revision %d num_subauth %d",
pace->revision, pace->num_subauth));
for (i = 0; i < num_subauth; ++i) {
cFYI(1, ("ACE sub_auth[%d]: 0x%x", i,
le32_to_cpu(psub_auth[i])));
le32_to_cpu(pace->sub_auth[i])));
}

/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */

cFYI(1, ("RID %d", le32_to_cpu(psub_auth[num_subauth-1])));
cFYI(1, ("RID %d", le32_to_cpu(pace->sub_auth[num_subauth-1])));
#endif
}

Expand Down Expand Up @@ -132,7 +226,13 @@ static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl)
sizeof(struct cifs_ntace));

parse_ntace(ppntace[i], end_of_acl);
parse_ace(ppace[i], end_of_acl);
if (end_of_acl < ((char *)ppace[i] +
(ppntace[i]->size -
sizeof(struct cifs_ntace)))) {
cERROR(1, ("ACL too small to parse ACE"));
break;
} else
parse_ace(ppace[i], end_of_acl);

/* memcpy((void *)(&(cifscred->ntaces[i])),
(void *)ppntace[i],
Expand All @@ -157,7 +257,6 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
{
int i;
int num_subauth;
__u32 *psub_auth;

/* BB need to add parm so we can store the SID BB */

Expand All @@ -169,20 +268,19 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)

num_subauth = cpu_to_le32(psid->num_subauth);
if (num_subauth) {
psub_auth = (__u32 *)((char *)psid + sizeof(struct cifs_sid));
#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("SID revision %d num_auth %d First subauth 0x%x",
psid->revision, psid->num_subauth, psid->sub_auth[0]));

for (i = 0; i < num_subauth; ++i) {
cFYI(1, ("SID sub_auth[%d]: 0x%x ", i,
le32_to_cpu(psub_auth[i])));
le32_to_cpu(psid->sub_auth[i])));
}

/* BB add length check to make sure that we do not have huge
num auths and therefore go off the end */
cFYI(1, ("RID 0x%x",
le32_to_cpu(psid->sub_auth[psid->num_subauth])));
le32_to_cpu(psid->sub_auth[num_subauth-1])));
#endif
}

Expand Down Expand Up @@ -228,5 +326,7 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
sizeof (struct cifs_sid)); */


return (0);
}
#endif /* CONFIG_CIFS_EXPERIMENTAL */
24 changes: 18 additions & 6 deletions fs/cifs/cifsacl.h
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
#ifndef _CIFSACL_H
#define _CIFSACL_H


#define NUM_WK_SIDS 7 /* number of well known sids */
#define SIDNAMELENGTH 20 /* long enough for the ones we care about */

struct cifs_ntsd {
__u16 revision; /* revision level */
__u16 type;
Expand All @@ -35,7 +39,7 @@ struct cifs_sid {
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[6];
__u32 sub_auth[0]; /* sub_auth[num_subauth] */
__u32 sub_auth[5]; /* sub_auth[num_subauth] */
} __attribute__((packed));

struct cifs_acl {
Expand All @@ -55,12 +59,20 @@ struct cifs_ace { /* last part of ACE which includes user info */
__u8 revision; /* revision level */
__u8 num_subauth;
__u8 authority[6];
__u32 sub_auth[0];
__u32 sub_auth[5];
} __attribute__((packed));

struct cifs_wksid {
struct cifs_sid cifssid;
char sidname[SIDNAMELENGTH];
} __attribute__((packed));

/* everyone */
/* extern const struct cifs_sid sid_everyone;*/
/* group users */
/* extern const struct cifs_sid sid_user;*/
#ifdef CONFIG_CIFS_EXPERIMENTAL

extern struct cifs_wksid wksidarr[NUM_WK_SIDS];
extern int match_sid(struct cifs_sid *);
extern int compare_sids(struct cifs_sid *, struct cifs_sid *);

#endif /* CONFIG_CIFS_EXPERIMENTAL */

#endif /* _CIFSACL_H */
4 changes: 0 additions & 4 deletions fs/cifs/cifsfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -49,10 +49,6 @@
static struct quotactl_ops cifs_quotactl_ops;
#endif /* QUOTA */

#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */

int cifsFYI = 0;
int cifsERROR = 1;
int traceSMB = 0;
Expand Down
7 changes: 6 additions & 1 deletion fs/cifs/cifsfs.h
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/*
* fs/cifs/cifsfs.h
*
* Copyright (c) International Business Machines Corp., 2002, 2005
* Copyright (c) International Business Machines Corp., 2002, 2007
* Author(s): Steve French (sfrench@us.ibm.com)
*
* This library is free software; you can redistribute it and/or modify
Expand Down Expand Up @@ -101,5 +101,10 @@ extern ssize_t cifs_getxattr(struct dentry *, const char *, void *, size_t);
extern ssize_t cifs_listxattr(struct dentry *, char *, size_t);
extern int cifs_ioctl(struct inode *inode, struct file *filep,
unsigned int command, unsigned long arg);

#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct export_operations cifs_export_ops;
#endif /* EXPERIMENTAL */

#define CIFS_VERSION "1.51"
#endif /* _CIFSFS_H */
2 changes: 2 additions & 0 deletions fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -3058,6 +3058,7 @@ CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,

#endif /* CONFIG_POSIX */

#ifdef CONFIG_CIFS_EXPERIMENTAL
/* Get Security Descriptor (by handle) from remote server for a file or dir */
int
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
Expand Down Expand Up @@ -3129,6 +3130,7 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
/* cifs_small_buf_release(pSMB); */ /* Freed earlier now in SendReceive2 */
return rc;
}
#endif /* CONFIG_CIFS_EXPERIMENTAL */

/* Legacy Query Path Information call for lookup to old servers such
as Win9x/WinME */
Expand Down
1 change: 1 addition & 0 deletions fs/cifs/export.c
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@
#include <linux/exportfs.h>
#include "cifsglob.h"
#include "cifs_debug.h"
#include "cifsfs.h"

#ifdef CONFIG_CIFS_EXPERIMENTAL
static struct dentry *cifs_get_parent(struct dentry *dentry)
Expand Down

0 comments on commit 297647c

Please sign in to comment.