Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 73493
b: refs/heads/master
c: 630f3f0
h: refs/heads/master
i:
  73491: 4f9ab7e
v: v3
  • Loading branch information
Steve French committed Oct 25, 2007
1 parent 3da4d81 commit 3bd96ca
Show file tree
Hide file tree
Showing 11 changed files with 170 additions and 61 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 44093ca2fef3c52dc7d186116862d74f9a676e0f
refs/heads/master: 630f3f0c45a80ab907d216191ef4a205c249fa1b
91 changes: 71 additions & 20 deletions trunk/fs/cifs/cifsacl.c
Original file line number Diff line number Diff line change
Expand Up @@ -97,7 +97,7 @@ int match_sid(struct cifs_sid *ctsid)

/* if the two SIDs (roughly equivalent to a UUID for a user or group) are
the same returns 1, if they do not match returns 0 */
int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
int compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
{
int i;
int num_subauth, num_sat, num_saw;
Expand Down Expand Up @@ -129,28 +129,77 @@ int compare_sids(struct cifs_sid *ctsid, struct cifs_sid *cwsid)
return (1); /* sids compare/match */
}

void get_mode_from_acl(struct inode * inode, const char * path)
/*
change posix mode to reflect permissions
pmode is the existing mode (we only want to overwrite part of this
bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
*/
static void access_flags_to_mode(__u32 access_flags, umode_t * pmode,
umode_t bits_to_set)
{

#ifdef CONFIG_CIFS_DEBUG2
cFYI(1, ("access flags 0x%x mode now 0x%x", access_flags, *pmode);
#endif

return;
}

/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */

void acl_to_uid_mode(struct inode *inode, const char *path)
{
struct cifsFileInfo *open_file;
int unlock_file = FALSE;
int xid;
int rc = -EIO;
__u16 fid;
struct super_block *sb;
struct cifs_sb_info *cifs_sb;

cFYI(1, ("get mode from ACL for %s", path));

if (inode == NULL)
return;

/* find an open readable handle
if handle found
lock handle
else open file
if no open file can not hurt to check if path is null
GetCIFSACL
for all ACEs in ACL {
if U or G or O
inode->i_mode = parse_ace(file_type, UG or O, ace->perms, inode->i_mode)
else continue
}
if handle open close it
else unlock handle */
xid = GetXid();
open_file = find_readable_file(CIFS_I(inode));
if (open_file) {
unlock_file = TRUE;
fid = open_file->netfid;
} else {
int oplock = FALSE;
/* open file */
sb = inode->i_sb;
if (sb == NULL) {
FreeXid(xid);
return;
}
cifs_sb = CIFS_SB(sb);
rc = CIFSSMBOpen(xid, cifs_sb->tcon, path, FILE_OPEN,
GENERIC_READ, 0, &fid, &oplock, NULL,
cifs_sb->local_nls, cifs_sb->mnt_cifs_flags &
CIFS_MOUNT_MAP_SPECIAL_CHR);
if (rc != 0) {
cERROR(1, ("Unable to open file to get ACL"));
FreeXid(xid);
return;
}
}

/* rc = CIFSSMBGetCIFSACL(xid, cifs_sb->tcon, fid, pntsd, acllen,
ACL_TYPE_ACCESS); */

if (unlock_file == TRUE)
atomic_dec(&open_file->wrtPending);
else
CIFSSMBClose(xid, cifs_sb->tcon, fid);

/* parse ACEs e.g.
rc = parse_sec_desc(pntsd, acllen, inode);
*/

FreeXid(xid);
return;
}

Expand Down Expand Up @@ -193,7 +242,8 @@ static void parse_ace(struct cifs_ace *pace, char *end_of_acl)


static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid)
struct cifs_sid *pownersid, struct cifs_sid *pgrpsid
struct inode *inode)
{
int i;
int num_aces = 0;
Expand Down Expand Up @@ -281,7 +331,8 @@ static int parse_sid(struct cifs_sid *psid, char *end_of_acl)


/* Convert CIFS ACL to POSIX form */
int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
static int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len,
struct inode *inode)
{
int rc;
struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
Expand Down Expand Up @@ -310,14 +361,14 @@ int parse_sec_desc(struct cifs_ntsd *pntsd, int acl_len)
if (rc)
return rc;

parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr);
parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr, group_sid_ptr, inode);

/* cifscred->uid = owner_sid_ptr->rid;
cifscred->gid = group_sid_ptr->rid;
memcpy((void *)(&(cifscred->osid)), (void *)owner_sid_ptr,
sizeof (struct cifs_sid));
sizeof(struct cifs_sid));
memcpy((void *)(&(cifscred->gsid)), (void *)group_sid_ptr,
sizeof (struct cifs_sid)); */
sizeof(struct cifs_sid)); */


return (0);
Expand Down
9 changes: 5 additions & 4 deletions trunk/fs/cifs/cifsproto.h
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,9 @@ extern int checkSMB(struct smb_hdr *smb, __u16 mid, unsigned int length);
extern int is_valid_oplock_break(struct smb_hdr *smb, struct TCP_Server_Info *);
extern int is_size_safe_to_change(struct cifsInodeInfo *, __u64 eof);
extern struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *);
#ifdef CONFIG_CIFS_EXPERIMENTAL
extern struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *);
#endif
extern unsigned int smbCalcSize(struct smb_hdr *ptr);
extern unsigned int smbCalcSize_LE(struct smb_hdr *ptr);
extern int decode_negTokenInit(unsigned char *security_blob, int length,
Expand Down Expand Up @@ -92,7 +95,7 @@ extern int cifs_get_inode_info(struct inode **pinode,
extern int cifs_get_inode_info_unix(struct inode **pinode,
const unsigned char *search_path,
struct super_block *sb, int xid);
extern void get_mode_from_acl(struct inode * inode, const char * search_path);
extern void acl_to_uid_mode(struct inode *inode, const char *search_path);
extern int cifs_mount(struct super_block *, struct cifs_sb_info *, char *,
const char *);
extern int cifs_umount(struct super_block *, struct cifs_sb_info *);
Expand Down Expand Up @@ -311,7 +314,6 @@ extern void setup_ntlmv2_rsp(struct cifsSesInfo *, char *,
#ifdef CONFIG_CIFS_WEAK_PW_HASH
extern void calc_lanman_hash(struct cifsSesInfo *ses, char *lnm_session_key);
#endif /* CIFS_WEAK_PW_HASH */
extern int parse_sec_desc(struct cifs_ntsd *, int);
extern int CIFSSMBCopy(int xid,
struct cifsTconInfo *source_tcon,
const char *fromName,
Expand All @@ -336,8 +338,7 @@ extern int CIFSSMBSetEA(const int xid, struct cifsTconInfo *tcon,
const void *ea_value, const __u16 ea_value_len,
const struct nls_table *nls_codepage, int remap_special_chars);
extern int CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon,
__u16 fid, char *acl_inf, const int buflen,
const int acl_type /* ACCESS vs. DEFAULT */);
__u16 fid, struct cifs_ntsd **acl_inf, __u32 *buflen);
extern int CIFSSMBGetPosixACL(const int xid, struct cifsTconInfo *tcon,
const unsigned char *searchName,
char *acl_inf, const int buflen, const int acl_type,
Expand Down
55 changes: 40 additions & 15 deletions trunk/fs/cifs/cifssmb.c
Original file line number Diff line number Diff line change
Expand Up @@ -2526,12 +2526,15 @@ smb_init_ntransact(const __u16 sub_command, const int setup_count,

static int
validate_ntransact(char *buf, char **ppparm, char **ppdata,
int *pdatalen, int *pparmlen)
__u32 *pdatalen, __u32 *pparmlen)
{
char *end_of_smb;
__u32 data_count, data_offset, parm_count, parm_offset;
struct smb_com_ntransact_rsp *pSMBr;

*pdatalen = 0;
*pparmlen = 0;

if (buf == NULL)
return -EINVAL;

Expand Down Expand Up @@ -2568,6 +2571,8 @@ validate_ntransact(char *buf, char **ppparm, char **ppdata,
cFYI(1, ("parm count and data count larger than SMB"));
return -EINVAL;
}
*pdatalen = data_count;
*pparmlen = parm_count;
return 0;
}
#endif /* CIFS_EXPERIMENTAL */
Expand Down Expand Up @@ -3069,8 +3074,7 @@ CIFSGetExtAttr(const int xid, struct cifsTconInfo *tcon,
/* Get Security Descriptor (by handle) from remote server for a file or dir */
int
CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
/* BB fix up return info */ char *acl_inf, const int buflen,
const int acl_type)
struct cifs_ntsd **acl_inf, __u32 *pbuflen)
{
int rc = 0;
int buf_type = 0;
Expand All @@ -3079,6 +3083,9 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,

cFYI(1, ("GetCifsACL"));

*pbuflen = 0;
*acl_inf = NULL;

rc = smb_init_ntransact(NT_TRANSACT_QUERY_SECURITY_DESC, 0,
8 /* parm len */, tcon, (void **) &pSMB);
if (rc)
Expand All @@ -3101,34 +3108,52 @@ CIFSSMBGetCIFSACL(const int xid, struct cifsTconInfo *tcon, __u16 fid,
if (rc) {
cFYI(1, ("Send error in QuerySecDesc = %d", rc));
} else { /* decode response */
struct cifs_ntsd *psec_desc;
__le32 * parm;
int parm_len;
int data_len;
int acl_len;
__u32 parm_len;
__u32 acl_len;
struct smb_com_ntransact_rsp *pSMBr;
char *pdata;

/* validate_nttransact */
rc = validate_ntransact(iov[0].iov_base, (char **)&parm,
(char **)&psec_desc,
&parm_len, &data_len);
&pdata, &parm_len, pbuflen);
if (rc)
goto qsec_out;
pSMBr = (struct smb_com_ntransact_rsp *)iov[0].iov_base;

cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, psec_desc));
cFYI(1, ("smb %p parm %p data %p", pSMBr, parm, *acl_inf));

if (le32_to_cpu(pSMBr->ParameterCount) != 4) {
rc = -EIO; /* bad smb */
*pbuflen = 0;
goto qsec_out;
}

/* BB check that data area is minimum length and as big as acl_len */

acl_len = le32_to_cpu(*parm);
/* BB check if (acl_len > bufsize) */
if (acl_len != *pbuflen) {
cERROR(1, ("acl length %d does not match %d",
acl_len, *pbuflen));
if (*pbuflen > acl_len)
*pbuflen = acl_len;
}

parse_sec_desc(psec_desc, acl_len);
/* check if buffer is big enough for the acl
header followed by the smallest SID */
if ((*pbuflen < sizeof(struct cifs_ntsd) + 8) ||
(*pbuflen >= 64 * 1024)) {
cERROR(1, ("bad acl length %d", *pbuflen));
rc = -EINVAL;
*pbuflen = 0;
} else {
*acl_inf = kmalloc(*pbuflen, GFP_KERNEL);
if (*acl_inf == NULL) {
*pbuflen = 0;
rc = -ENOMEM;
}
memcpy(*acl_inf, pdata, *pbuflen);
}
}
qsec_out:
if (buf_type == CIFS_SMALL_BUFFER)
Expand Down Expand Up @@ -3383,7 +3408,7 @@ CIFSSMBUnixQPathInfo(const int xid, struct cifsTconInfo *tcon,
memcpy((char *) pFindData,
(char *) &pSMBr->hdr.Protocol +
data_offset,
sizeof (FILE_UNIX_BASIC_INFO));
sizeof(FILE_UNIX_BASIC_INFO));
}
}
cifs_buf_release(pSMB);
Expand Down Expand Up @@ -3651,7 +3676,7 @@ int CIFSFindNext(const int xid, struct cifsTconInfo *tcon,
pSMB->SubCommand = cpu_to_le16(TRANS2_FIND_NEXT);
pSMB->SearchHandle = searchHandle; /* always kept as le */
pSMB->SearchCount =
cpu_to_le16(CIFSMaxBufSize / sizeof (FILE_UNIX_INFO));
cpu_to_le16(CIFSMaxBufSize / sizeof(FILE_UNIX_INFO));
pSMB->InformationLevel = cpu_to_le16(psrch_inf->info_level);
pSMB->ResumeKey = psrch_inf->resume_key;
pSMB->SearchFlags =
Expand Down Expand Up @@ -4333,7 +4358,7 @@ CIFSSMBQFSDeviceInfo(const int xid, struct cifsTconInfo *tcon)
} else { /* decode response */
rc = validate_t2((struct smb_t2_rsp *)pSMBr);

if (rc || (pSMBr->ByteCount < sizeof (FILE_SYSTEM_DEVICE_INFO)))
if (rc || (pSMBr->ByteCount < sizeof(FILE_SYSTEM_DEVICE_INFO)))
rc = -EIO; /* bad smb */
else {
__u16 data_offset = le16_to_cpu(pSMBr->t2.DataOffset);
Expand Down
31 changes: 31 additions & 0 deletions trunk/fs/cifs/file.c
Original file line number Diff line number Diff line change
Expand Up @@ -1026,6 +1026,37 @@ static ssize_t cifs_write(struct file *file, const char *write_data,
return total_written;
}

#ifdef CONFIG_CIFS_EXPERIMENTAL
struct cifsFileInfo *find_readable_file(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *open_file = NULL;

read_lock(&GlobalSMBSeslock);
/* we could simply get the first_list_entry since write-only entries
are always at the end of the list but since the first entry might
have a close pending, we go through the whole list */
list_for_each_entry(open_file, &cifs_inode->openFileList, flist) {
if (open_file->closePend)
continue;
if (open_file->pfile && ((open_file->pfile->f_flags & O_RDWR) ||
(open_file->pfile->f_flags & O_RDONLY))) {
if (!open_file->invalidHandle) {
/* found a good file */
/* lock it so it will not be closed on us */
atomic_inc(&open_file->wrtPending);
read_unlock(&GlobalSMBSeslock);
return open_file;
} /* else might as well continue, and look for
another, or simply have the caller reopen it
again rather than trying to fix this handle */
} else /* write only file */
break; /* write only files are last so must be done */
}
read_unlock(&GlobalSMBSeslock);
return NULL;
}
#endif

struct cifsFileInfo *find_writable_file(struct cifsInodeInfo *cifs_inode)
{
struct cifsFileInfo *open_file;
Expand Down
2 changes: 1 addition & 1 deletion trunk/fs/cifs/inode.c
Original file line number Diff line number Diff line change
Expand Up @@ -530,7 +530,7 @@ int cifs_get_inode_info(struct inode **pinode,
#ifdef CONFIG_CIFS_EXPERIMENTAL
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_CIFS_ACL) {
cFYI(1, ("Getting mode bits from ACL"));
get_mode_from_acl(inode, search_path);
acl_to_uid_mode(inode, search_path);
}
#endif
if (cifs_sb->mnt_cifs_flags & CIFS_MOUNT_UNX_EMUL) {
Expand Down
8 changes: 4 additions & 4 deletions trunk/fs/cifs/md5.c
Original file line number Diff line number Diff line change
Expand Up @@ -276,8 +276,8 @@ hmac_md5_init_rfc2104(unsigned char *key, int key_len,
}

/* start out by storing key in pads */
memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
memcpy(ctx->k_ipad, key, key_len);
memcpy(ctx->k_opad, key, key_len);

Expand Down Expand Up @@ -307,8 +307,8 @@ hmac_md5_init_limK_to_64(const unsigned char *key, int key_len,
}

/* start out by storing key in pads */
memset(ctx->k_ipad, 0, sizeof (ctx->k_ipad));
memset(ctx->k_opad, 0, sizeof (ctx->k_opad));
memset(ctx->k_ipad, 0, sizeof(ctx->k_ipad));
memset(ctx->k_opad, 0, sizeof(ctx->k_opad));
memcpy(ctx->k_ipad, key, key_len);
memcpy(ctx->k_opad, key, key_len);

Expand Down
Loading

0 comments on commit 3bd96ca

Please sign in to comment.