Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
Note: File does not exist in v6.8.
   1/*
   2 *   fs/cifs/cifsacl.c
   3 *
   4 *   Copyright (C) International Business Machines  Corp., 2007,2008
   5 *   Author(s): Steve French (sfrench@us.ibm.com)
   6 *
   7 *   Contains the routines for mapping CIFS/NTFS ACLs
   8 *
   9 *   This library is free software; you can redistribute it and/or modify
  10 *   it under the terms of the GNU Lesser General Public License as published
  11 *   by the Free Software Foundation; either version 2.1 of the License, or
  12 *   (at your option) any later version.
  13 *
  14 *   This library is distributed in the hope that it will be useful,
  15 *   but WITHOUT ANY WARRANTY; without even the implied warranty of
  16 *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
  17 *   the GNU Lesser General Public License for more details.
  18 *
  19 *   You should have received a copy of the GNU Lesser General Public License
  20 *   along with this library; if not, write to the Free Software
  21 *   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
  22 */
  23
  24#include <linux/fs.h>
  25#include <linux/slab.h>
  26#include <linux/string.h>
  27#include <linux/keyctl.h>
  28#include <linux/key-type.h>
  29#include <keys/user-type.h>
  30#include "cifspdu.h"
  31#include "cifsglob.h"
  32#include "cifsacl.h"
  33#include "cifsproto.h"
  34#include "cifs_debug.h"
  35
  36/* security id for everyone/world system group */
  37static const struct cifs_sid sid_everyone = {
  38	1, 1, {0, 0, 0, 0, 0, 1}, {0} };
  39/* security id for Authenticated Users system group */
  40static const struct cifs_sid sid_authusers = {
  41	1, 1, {0, 0, 0, 0, 0, 5}, {__constant_cpu_to_le32(11)} };
  42/* group users */
  43static const struct cifs_sid sid_user = {1, 2 , {0, 0, 0, 0, 0, 5}, {} };
  44
  45static const struct cred *root_cred;
  46
  47static int
  48cifs_idmap_key_instantiate(struct key *key, struct key_preparsed_payload *prep)
  49{
  50	char *payload;
  51
  52	/*
  53	 * If the payload is less than or equal to the size of a pointer, then
  54	 * an allocation here is wasteful. Just copy the data directly to the
  55	 * payload.value union member instead.
  56	 *
  57	 * With this however, you must check the datalen before trying to
  58	 * dereference payload.data!
  59	 */
  60	if (prep->datalen <= sizeof(key->payload)) {
  61		key->payload.value = 0;
  62		memcpy(&key->payload.value, prep->data, prep->datalen);
  63		key->datalen = prep->datalen;
  64		return 0;
  65	}
  66	payload = kmemdup(prep->data, prep->datalen, GFP_KERNEL);
  67	if (!payload)
  68		return -ENOMEM;
  69
  70	key->payload.data = payload;
  71	key->datalen = prep->datalen;
  72	return 0;
  73}
  74
  75static inline void
  76cifs_idmap_key_destroy(struct key *key)
  77{
  78	if (key->datalen > sizeof(key->payload))
  79		kfree(key->payload.data);
  80}
  81
  82static struct key_type cifs_idmap_key_type = {
  83	.name        = "cifs.idmap",
  84	.instantiate = cifs_idmap_key_instantiate,
  85	.destroy     = cifs_idmap_key_destroy,
  86	.describe    = user_describe,
  87	.match       = user_match,
  88};
  89
  90static char *
  91sid_to_key_str(struct cifs_sid *sidptr, unsigned int type)
  92{
  93	int i, len;
  94	unsigned int saval;
  95	char *sidstr, *strptr;
  96	unsigned long long id_auth_val;
  97
  98	/* 3 bytes for prefix */
  99	sidstr = kmalloc(3 + SID_STRING_BASE_SIZE +
 100			 (SID_STRING_SUBAUTH_SIZE * sidptr->num_subauth),
 101			 GFP_KERNEL);
 102	if (!sidstr)
 103		return sidstr;
 104
 105	strptr = sidstr;
 106	len = sprintf(strptr, "%cs:S-%hhu", type == SIDOWNER ? 'o' : 'g',
 107			sidptr->revision);
 108	strptr += len;
 109
 110	/* The authority field is a single 48-bit number */
 111	id_auth_val = (unsigned long long)sidptr->authority[5];
 112	id_auth_val |= (unsigned long long)sidptr->authority[4] << 8;
 113	id_auth_val |= (unsigned long long)sidptr->authority[3] << 16;
 114	id_auth_val |= (unsigned long long)sidptr->authority[2] << 24;
 115	id_auth_val |= (unsigned long long)sidptr->authority[1] << 32;
 116	id_auth_val |= (unsigned long long)sidptr->authority[0] << 48;
 117
 118	/*
 119	 * MS-DTYP states that if the authority is >= 2^32, then it should be
 120	 * expressed as a hex value.
 121	 */
 122	if (id_auth_val <= UINT_MAX)
 123		len = sprintf(strptr, "-%llu", id_auth_val);
 124	else
 125		len = sprintf(strptr, "-0x%llx", id_auth_val);
 126
 127	strptr += len;
 128
 129	for (i = 0; i < sidptr->num_subauth; ++i) {
 130		saval = le32_to_cpu(sidptr->sub_auth[i]);
 131		len = sprintf(strptr, "-%u", saval);
 132		strptr += len;
 133	}
 134
 135	return sidstr;
 136}
 137
 138/*
 139 * if the two SIDs (roughly equivalent to a UUID for a user or group) are
 140 * the same returns zero, if they do not match returns non-zero.
 141 */
 142static int
 143compare_sids(const struct cifs_sid *ctsid, const struct cifs_sid *cwsid)
 144{
 145	int i;
 146	int num_subauth, num_sat, num_saw;
 147
 148	if ((!ctsid) || (!cwsid))
 149		return 1;
 150
 151	/* compare the revision */
 152	if (ctsid->revision != cwsid->revision) {
 153		if (ctsid->revision > cwsid->revision)
 154			return 1;
 155		else
 156			return -1;
 157	}
 158
 159	/* compare all of the six auth values */
 160	for (i = 0; i < NUM_AUTHS; ++i) {
 161		if (ctsid->authority[i] != cwsid->authority[i]) {
 162			if (ctsid->authority[i] > cwsid->authority[i])
 163				return 1;
 164			else
 165				return -1;
 166		}
 167	}
 168
 169	/* compare all of the subauth values if any */
 170	num_sat = ctsid->num_subauth;
 171	num_saw = cwsid->num_subauth;
 172	num_subauth = num_sat < num_saw ? num_sat : num_saw;
 173	if (num_subauth) {
 174		for (i = 0; i < num_subauth; ++i) {
 175			if (ctsid->sub_auth[i] != cwsid->sub_auth[i]) {
 176				if (le32_to_cpu(ctsid->sub_auth[i]) >
 177					le32_to_cpu(cwsid->sub_auth[i]))
 178					return 1;
 179				else
 180					return -1;
 181			}
 182		}
 183	}
 184
 185	return 0; /* sids compare/match */
 186}
 187
 188static void
 189cifs_copy_sid(struct cifs_sid *dst, const struct cifs_sid *src)
 190{
 191	int i;
 192
 193	dst->revision = src->revision;
 194	dst->num_subauth = min_t(u8, src->num_subauth, SID_MAX_SUB_AUTHORITIES);
 195	for (i = 0; i < NUM_AUTHS; ++i)
 196		dst->authority[i] = src->authority[i];
 197	for (i = 0; i < dst->num_subauth; ++i)
 198		dst->sub_auth[i] = src->sub_auth[i];
 199}
 200
 201static int
 202id_to_sid(unsigned int cid, uint sidtype, struct cifs_sid *ssid)
 203{
 204	int rc;
 205	struct key *sidkey;
 206	struct cifs_sid *ksid;
 207	unsigned int ksid_size;
 208	char desc[3 + 10 + 1]; /* 3 byte prefix + 10 bytes for value + NULL */
 209	const struct cred *saved_cred;
 210
 211	rc = snprintf(desc, sizeof(desc), "%ci:%u",
 212			sidtype == SIDOWNER ? 'o' : 'g', cid);
 213	if (rc >= sizeof(desc))
 214		return -EINVAL;
 215
 216	rc = 0;
 217	saved_cred = override_creds(root_cred);
 218	sidkey = request_key(&cifs_idmap_key_type, desc, "");
 219	if (IS_ERR(sidkey)) {
 220		rc = -EINVAL;
 221		cifs_dbg(FYI, "%s: Can't map %cid %u to a SID\n",
 222			 __func__, sidtype == SIDOWNER ? 'u' : 'g', cid);
 223		goto out_revert_creds;
 224	} else if (sidkey->datalen < CIFS_SID_BASE_SIZE) {
 225		rc = -EIO;
 226		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
 227			 __func__, sidkey->datalen);
 228		goto invalidate_key;
 229	}
 230
 231	/*
 232	 * A sid is usually too large to be embedded in payload.value, but if
 233	 * there are no subauthorities and the host has 8-byte pointers, then
 234	 * it could be.
 235	 */
 236	ksid = sidkey->datalen <= sizeof(sidkey->payload) ?
 237		(struct cifs_sid *)&sidkey->payload.value :
 238		(struct cifs_sid *)sidkey->payload.data;
 239
 240	ksid_size = CIFS_SID_BASE_SIZE + (ksid->num_subauth * sizeof(__le32));
 241	if (ksid_size > sidkey->datalen) {
 242		rc = -EIO;
 243		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu, ksid_size=%u)\n",
 244			 __func__, sidkey->datalen, ksid_size);
 245		goto invalidate_key;
 246	}
 247
 248	cifs_copy_sid(ssid, ksid);
 249out_key_put:
 250	key_put(sidkey);
 251out_revert_creds:
 252	revert_creds(saved_cred);
 253	return rc;
 254
 255invalidate_key:
 256	key_invalidate(sidkey);
 257	goto out_key_put;
 258}
 259
 260static int
 261sid_to_id(struct cifs_sb_info *cifs_sb, struct cifs_sid *psid,
 262		struct cifs_fattr *fattr, uint sidtype)
 263{
 264	int rc;
 265	struct key *sidkey;
 266	char *sidstr;
 267	const struct cred *saved_cred;
 268	kuid_t fuid = cifs_sb->mnt_uid;
 269	kgid_t fgid = cifs_sb->mnt_gid;
 270
 271	/*
 272	 * If we have too many subauthorities, then something is really wrong.
 273	 * Just return an error.
 274	 */
 275	if (unlikely(psid->num_subauth > SID_MAX_SUB_AUTHORITIES)) {
 276		cifs_dbg(FYI, "%s: %u subauthorities is too many!\n",
 277			 __func__, psid->num_subauth);
 278		return -EIO;
 279	}
 280
 281	sidstr = sid_to_key_str(psid, sidtype);
 282	if (!sidstr)
 283		return -ENOMEM;
 284
 285	saved_cred = override_creds(root_cred);
 286	sidkey = request_key(&cifs_idmap_key_type, sidstr, "");
 287	if (IS_ERR(sidkey)) {
 288		rc = -EINVAL;
 289		cifs_dbg(FYI, "%s: Can't map SID %s to a %cid\n",
 290			 __func__, sidstr, sidtype == SIDOWNER ? 'u' : 'g');
 291		goto out_revert_creds;
 292	}
 293
 294	/*
 295	 * FIXME: Here we assume that uid_t and gid_t are same size. It's
 296	 * probably a safe assumption but might be better to check based on
 297	 * sidtype.
 298	 */
 299	BUILD_BUG_ON(sizeof(uid_t) != sizeof(gid_t));
 300	if (sidkey->datalen != sizeof(uid_t)) {
 301		rc = -EIO;
 302		cifs_dbg(FYI, "%s: Downcall contained malformed key (datalen=%hu)\n",
 303			 __func__, sidkey->datalen);
 304		key_invalidate(sidkey);
 305		goto out_key_put;
 306	}
 307
 308	if (sidtype == SIDOWNER) {
 309		kuid_t uid;
 310		uid_t id;
 311		memcpy(&id, &sidkey->payload.value, sizeof(uid_t));
 312		uid = make_kuid(&init_user_ns, id);
 313		if (uid_valid(uid))
 314			fuid = uid;
 315	} else {
 316		kgid_t gid;
 317		gid_t id;
 318		memcpy(&id, &sidkey->payload.value, sizeof(gid_t));
 319		gid = make_kgid(&init_user_ns, id);
 320		if (gid_valid(gid))
 321			fgid = gid;
 322	}
 323
 324out_key_put:
 325	key_put(sidkey);
 326out_revert_creds:
 327	revert_creds(saved_cred);
 328	kfree(sidstr);
 329
 330	/*
 331	 * Note that we return 0 here unconditionally. If the mapping
 332	 * fails then we just fall back to using the mnt_uid/mnt_gid.
 333	 */
 334	if (sidtype == SIDOWNER)
 335		fattr->cf_uid = fuid;
 336	else
 337		fattr->cf_gid = fgid;
 338	return 0;
 339}
 340
 341int
 342init_cifs_idmap(void)
 343{
 344	struct cred *cred;
 345	struct key *keyring;
 346	int ret;
 347
 348	cifs_dbg(FYI, "Registering the %s key type\n",
 349		 cifs_idmap_key_type.name);
 350
 351	/* create an override credential set with a special thread keyring in
 352	 * which requests are cached
 353	 *
 354	 * this is used to prevent malicious redirections from being installed
 355	 * with add_key().
 356	 */
 357	cred = prepare_kernel_cred(NULL);
 358	if (!cred)
 359		return -ENOMEM;
 360
 361	keyring = keyring_alloc(".cifs_idmap",
 362				GLOBAL_ROOT_UID, GLOBAL_ROOT_GID, cred,
 363				(KEY_POS_ALL & ~KEY_POS_SETATTR) |
 364				KEY_USR_VIEW | KEY_USR_READ,
 365				KEY_ALLOC_NOT_IN_QUOTA, NULL);
 366	if (IS_ERR(keyring)) {
 367		ret = PTR_ERR(keyring);
 368		goto failed_put_cred;
 369	}
 370
 371	ret = register_key_type(&cifs_idmap_key_type);
 372	if (ret < 0)
 373		goto failed_put_key;
 374
 375	/* instruct request_key() to use this special keyring as a cache for
 376	 * the results it looks up */
 377	set_bit(KEY_FLAG_ROOT_CAN_CLEAR, &keyring->flags);
 378	cred->thread_keyring = keyring;
 379	cred->jit_keyring = KEY_REQKEY_DEFL_THREAD_KEYRING;
 380	root_cred = cred;
 381
 382	cifs_dbg(FYI, "cifs idmap keyring: %d\n", key_serial(keyring));
 383	return 0;
 384
 385failed_put_key:
 386	key_put(keyring);
 387failed_put_cred:
 388	put_cred(cred);
 389	return ret;
 390}
 391
 392void
 393exit_cifs_idmap(void)
 394{
 395	key_revoke(root_cred->thread_keyring);
 396	unregister_key_type(&cifs_idmap_key_type);
 397	put_cred(root_cred);
 398	cifs_dbg(FYI, "Unregistered %s key type\n", cifs_idmap_key_type.name);
 399}
 400
 401/* copy ntsd, owner sid, and group sid from a security descriptor to another */
 402static void copy_sec_desc(const struct cifs_ntsd *pntsd,
 403				struct cifs_ntsd *pnntsd, __u32 sidsoffset)
 404{
 405	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 406	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 407
 408	/* copy security descriptor control portion */
 409	pnntsd->revision = pntsd->revision;
 410	pnntsd->type = pntsd->type;
 411	pnntsd->dacloffset = cpu_to_le32(sizeof(struct cifs_ntsd));
 412	pnntsd->sacloffset = 0;
 413	pnntsd->osidoffset = cpu_to_le32(sidsoffset);
 414	pnntsd->gsidoffset = cpu_to_le32(sidsoffset + sizeof(struct cifs_sid));
 415
 416	/* copy owner sid */
 417	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 418				le32_to_cpu(pntsd->osidoffset));
 419	nowner_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset);
 420	cifs_copy_sid(nowner_sid_ptr, owner_sid_ptr);
 421
 422	/* copy group sid */
 423	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 424				le32_to_cpu(pntsd->gsidoffset));
 425	ngroup_sid_ptr = (struct cifs_sid *)((char *)pnntsd + sidsoffset +
 426					sizeof(struct cifs_sid));
 427	cifs_copy_sid(ngroup_sid_ptr, group_sid_ptr);
 428
 429	return;
 430}
 431
 432
 433/*
 434   change posix mode to reflect permissions
 435   pmode is the existing mode (we only want to overwrite part of this
 436   bits to set can be: S_IRWXU, S_IRWXG or S_IRWXO ie 00700 or 00070 or 00007
 437*/
 438static void access_flags_to_mode(__le32 ace_flags, int type, umode_t *pmode,
 439				 umode_t *pbits_to_set)
 440{
 441	__u32 flags = le32_to_cpu(ace_flags);
 442	/* the order of ACEs is important.  The canonical order is to begin with
 443	   DENY entries followed by ALLOW, otherwise an allow entry could be
 444	   encountered first, making the subsequent deny entry like "dead code"
 445	   which would be superflous since Windows stops when a match is made
 446	   for the operation you are trying to perform for your user */
 447
 448	/* For deny ACEs we change the mask so that subsequent allow access
 449	   control entries do not turn on the bits we are denying */
 450	if (type == ACCESS_DENIED) {
 451		if (flags & GENERIC_ALL)
 452			*pbits_to_set &= ~S_IRWXUGO;
 453
 454		if ((flags & GENERIC_WRITE) ||
 455			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
 456			*pbits_to_set &= ~S_IWUGO;
 457		if ((flags & GENERIC_READ) ||
 458			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
 459			*pbits_to_set &= ~S_IRUGO;
 460		if ((flags & GENERIC_EXECUTE) ||
 461			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 462			*pbits_to_set &= ~S_IXUGO;
 463		return;
 464	} else if (type != ACCESS_ALLOWED) {
 465		cifs_dbg(VFS, "unknown access control type %d\n", type);
 466		return;
 467	}
 468	/* else ACCESS_ALLOWED type */
 469
 470	if (flags & GENERIC_ALL) {
 471		*pmode |= (S_IRWXUGO & (*pbits_to_set));
 472		cifs_dbg(NOISY, "all perms\n");
 473		return;
 474	}
 475	if ((flags & GENERIC_WRITE) ||
 476			((flags & FILE_WRITE_RIGHTS) == FILE_WRITE_RIGHTS))
 477		*pmode |= (S_IWUGO & (*pbits_to_set));
 478	if ((flags & GENERIC_READ) ||
 479			((flags & FILE_READ_RIGHTS) == FILE_READ_RIGHTS))
 480		*pmode |= (S_IRUGO & (*pbits_to_set));
 481	if ((flags & GENERIC_EXECUTE) ||
 482			((flags & FILE_EXEC_RIGHTS) == FILE_EXEC_RIGHTS))
 483		*pmode |= (S_IXUGO & (*pbits_to_set));
 484
 485	cifs_dbg(NOISY, "access flags 0x%x mode now 0x%x\n", flags, *pmode);
 486	return;
 487}
 488
 489/*
 490   Generate access flags to reflect permissions mode is the existing mode.
 491   This function is called for every ACE in the DACL whose SID matches
 492   with either owner or group or everyone.
 493*/
 494
 495static void mode_to_access_flags(umode_t mode, umode_t bits_to_use,
 496				__u32 *pace_flags)
 497{
 498	/* reset access mask */
 499	*pace_flags = 0x0;
 500
 501	/* bits to use are either S_IRWXU or S_IRWXG or S_IRWXO */
 502	mode &= bits_to_use;
 503
 504	/* check for R/W/X UGO since we do not know whose flags
 505	   is this but we have cleared all the bits sans RWX for
 506	   either user or group or other as per bits_to_use */
 507	if (mode & S_IRUGO)
 508		*pace_flags |= SET_FILE_READ_RIGHTS;
 509	if (mode & S_IWUGO)
 510		*pace_flags |= SET_FILE_WRITE_RIGHTS;
 511	if (mode & S_IXUGO)
 512		*pace_flags |= SET_FILE_EXEC_RIGHTS;
 513
 514	cifs_dbg(NOISY, "mode: 0x%x, access flags now 0x%x\n",
 515		 mode, *pace_flags);
 516	return;
 517}
 518
 519static __u16 fill_ace_for_sid(struct cifs_ace *pntace,
 520			const struct cifs_sid *psid, __u64 nmode, umode_t bits)
 521{
 522	int i;
 523	__u16 size = 0;
 524	__u32 access_req = 0;
 525
 526	pntace->type = ACCESS_ALLOWED;
 527	pntace->flags = 0x0;
 528	mode_to_access_flags(nmode, bits, &access_req);
 529	if (!access_req)
 530		access_req = SET_MINIMUM_RIGHTS;
 531	pntace->access_req = cpu_to_le32(access_req);
 532
 533	pntace->sid.revision = psid->revision;
 534	pntace->sid.num_subauth = psid->num_subauth;
 535	for (i = 0; i < NUM_AUTHS; i++)
 536		pntace->sid.authority[i] = psid->authority[i];
 537	for (i = 0; i < psid->num_subauth; i++)
 538		pntace->sid.sub_auth[i] = psid->sub_auth[i];
 539
 540	size = 1 + 1 + 2 + 4 + 1 + 1 + 6 + (psid->num_subauth * 4);
 541	pntace->size = cpu_to_le16(size);
 542
 543	return size;
 544}
 545
 546
 547#ifdef CONFIG_CIFS_DEBUG2
 548static void dump_ace(struct cifs_ace *pace, char *end_of_acl)
 549{
 550	int num_subauth;
 551
 552	/* validate that we do not go past end of acl */
 553
 554	if (le16_to_cpu(pace->size) < 16) {
 555		cifs_dbg(VFS, "ACE too small %d\n", le16_to_cpu(pace->size));
 556		return;
 557	}
 558
 559	if (end_of_acl < (char *)pace + le16_to_cpu(pace->size)) {
 560		cifs_dbg(VFS, "ACL too small to parse ACE\n");
 561		return;
 562	}
 563
 564	num_subauth = pace->sid.num_subauth;
 565	if (num_subauth) {
 566		int i;
 567		cifs_dbg(FYI, "ACE revision %d num_auth %d type %d flags %d size %d\n",
 568			 pace->sid.revision, pace->sid.num_subauth, pace->type,
 569			 pace->flags, le16_to_cpu(pace->size));
 570		for (i = 0; i < num_subauth; ++i) {
 571			cifs_dbg(FYI, "ACE sub_auth[%d]: 0x%x\n",
 572				 i, le32_to_cpu(pace->sid.sub_auth[i]));
 573		}
 574
 575		/* BB add length check to make sure that we do not have huge
 576			num auths and therefore go off the end */
 577	}
 578
 579	return;
 580}
 581#endif
 582
 583
 584static void parse_dacl(struct cifs_acl *pdacl, char *end_of_acl,
 585		       struct cifs_sid *pownersid, struct cifs_sid *pgrpsid,
 586		       struct cifs_fattr *fattr)
 587{
 588	int i;
 589	int num_aces = 0;
 590	int acl_size;
 591	char *acl_base;
 592	struct cifs_ace **ppace;
 593
 594	/* BB need to add parm so we can store the SID BB */
 595
 596	if (!pdacl) {
 597		/* no DACL in the security descriptor, set
 598		   all the permissions for user/group/other */
 599		fattr->cf_mode |= S_IRWXUGO;
 600		return;
 601	}
 602
 603	/* validate that we do not go past end of acl */
 604	if (end_of_acl < (char *)pdacl + le16_to_cpu(pdacl->size)) {
 605		cifs_dbg(VFS, "ACL too small to parse DACL\n");
 606		return;
 607	}
 608
 609	cifs_dbg(NOISY, "DACL revision %d size %d num aces %d\n",
 610		 le16_to_cpu(pdacl->revision), le16_to_cpu(pdacl->size),
 611		 le32_to_cpu(pdacl->num_aces));
 612
 613	/* reset rwx permissions for user/group/other.
 614	   Also, if num_aces is 0 i.e. DACL has no ACEs,
 615	   user/group/other have no permissions */
 616	fattr->cf_mode &= ~(S_IRWXUGO);
 617
 618	acl_base = (char *)pdacl;
 619	acl_size = sizeof(struct cifs_acl);
 620
 621	num_aces = le32_to_cpu(pdacl->num_aces);
 622	if (num_aces > 0) {
 623		umode_t user_mask = S_IRWXU;
 624		umode_t group_mask = S_IRWXG;
 625		umode_t other_mask = S_IRWXU | S_IRWXG | S_IRWXO;
 626
 627		if (num_aces > ULONG_MAX / sizeof(struct cifs_ace *))
 628			return;
 629		ppace = kmalloc(num_aces * sizeof(struct cifs_ace *),
 630				GFP_KERNEL);
 631		if (!ppace)
 632			return;
 633
 634		for (i = 0; i < num_aces; ++i) {
 635			ppace[i] = (struct cifs_ace *) (acl_base + acl_size);
 636#ifdef CONFIG_CIFS_DEBUG2
 637			dump_ace(ppace[i], end_of_acl);
 638#endif
 639			if (compare_sids(&(ppace[i]->sid), pownersid) == 0)
 640				access_flags_to_mode(ppace[i]->access_req,
 641						     ppace[i]->type,
 642						     &fattr->cf_mode,
 643						     &user_mask);
 644			if (compare_sids(&(ppace[i]->sid), pgrpsid) == 0)
 645				access_flags_to_mode(ppace[i]->access_req,
 646						     ppace[i]->type,
 647						     &fattr->cf_mode,
 648						     &group_mask);
 649			if (compare_sids(&(ppace[i]->sid), &sid_everyone) == 0)
 650				access_flags_to_mode(ppace[i]->access_req,
 651						     ppace[i]->type,
 652						     &fattr->cf_mode,
 653						     &other_mask);
 654			if (compare_sids(&(ppace[i]->sid), &sid_authusers) == 0)
 655				access_flags_to_mode(ppace[i]->access_req,
 656						     ppace[i]->type,
 657						     &fattr->cf_mode,
 658						     &other_mask);
 659
 660
 661/*			memcpy((void *)(&(cifscred->aces[i])),
 662				(void *)ppace[i],
 663				sizeof(struct cifs_ace)); */
 664
 665			acl_base = (char *)ppace[i];
 666			acl_size = le16_to_cpu(ppace[i]->size);
 667		}
 668
 669		kfree(ppace);
 670	}
 671
 672	return;
 673}
 674
 675
 676static int set_chmod_dacl(struct cifs_acl *pndacl, struct cifs_sid *pownersid,
 677			struct cifs_sid *pgrpsid, __u64 nmode)
 678{
 679	u16 size = 0;
 680	struct cifs_acl *pnndacl;
 681
 682	pnndacl = (struct cifs_acl *)((char *)pndacl + sizeof(struct cifs_acl));
 683
 684	size += fill_ace_for_sid((struct cifs_ace *) ((char *)pnndacl + size),
 685					pownersid, nmode, S_IRWXU);
 686	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 687					pgrpsid, nmode, S_IRWXG);
 688	size += fill_ace_for_sid((struct cifs_ace *)((char *)pnndacl + size),
 689					 &sid_everyone, nmode, S_IRWXO);
 690
 691	pndacl->size = cpu_to_le16(size + sizeof(struct cifs_acl));
 692	pndacl->num_aces = cpu_to_le32(3);
 693
 694	return 0;
 695}
 696
 697
 698static int parse_sid(struct cifs_sid *psid, char *end_of_acl)
 699{
 700	/* BB need to add parm so we can store the SID BB */
 701
 702	/* validate that we do not go past end of ACL - sid must be at least 8
 703	   bytes long (assuming no sub-auths - e.g. the null SID */
 704	if (end_of_acl < (char *)psid + 8) {
 705		cifs_dbg(VFS, "ACL too small to parse SID %p\n", psid);
 706		return -EINVAL;
 707	}
 708
 709#ifdef CONFIG_CIFS_DEBUG2
 710	if (psid->num_subauth) {
 711		int i;
 712		cifs_dbg(FYI, "SID revision %d num_auth %d\n",
 713			 psid->revision, psid->num_subauth);
 714
 715		for (i = 0; i < psid->num_subauth; i++) {
 716			cifs_dbg(FYI, "SID sub_auth[%d]: 0x%x\n",
 717				 i, le32_to_cpu(psid->sub_auth[i]));
 718		}
 719
 720		/* BB add length check to make sure that we do not have huge
 721			num auths and therefore go off the end */
 722		cifs_dbg(FYI, "RID 0x%x\n",
 723			 le32_to_cpu(psid->sub_auth[psid->num_subauth-1]));
 724	}
 725#endif
 726
 727	return 0;
 728}
 729
 730
 731/* Convert CIFS ACL to POSIX form */
 732static int parse_sec_desc(struct cifs_sb_info *cifs_sb,
 733		struct cifs_ntsd *pntsd, int acl_len, struct cifs_fattr *fattr)
 734{
 735	int rc = 0;
 736	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 737	struct cifs_acl *dacl_ptr; /* no need for SACL ptr */
 738	char *end_of_acl = ((char *)pntsd) + acl_len;
 739	__u32 dacloffset;
 740
 741	if (pntsd == NULL)
 742		return -EIO;
 743
 744	owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 745				le32_to_cpu(pntsd->osidoffset));
 746	group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 747				le32_to_cpu(pntsd->gsidoffset));
 748	dacloffset = le32_to_cpu(pntsd->dacloffset);
 749	dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 750	cifs_dbg(NOISY, "revision %d type 0x%x ooffset 0x%x goffset 0x%x sacloffset 0x%x dacloffset 0x%x\n",
 751		 pntsd->revision, pntsd->type, le32_to_cpu(pntsd->osidoffset),
 752		 le32_to_cpu(pntsd->gsidoffset),
 753		 le32_to_cpu(pntsd->sacloffset), dacloffset);
 754/*	cifs_dump_mem("owner_sid: ", owner_sid_ptr, 64); */
 755	rc = parse_sid(owner_sid_ptr, end_of_acl);
 756	if (rc) {
 757		cifs_dbg(FYI, "%s: Error %d parsing Owner SID\n", __func__, rc);
 758		return rc;
 759	}
 760	rc = sid_to_id(cifs_sb, owner_sid_ptr, fattr, SIDOWNER);
 761	if (rc) {
 762		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to uid\n",
 763			 __func__, rc);
 764		return rc;
 765	}
 766
 767	rc = parse_sid(group_sid_ptr, end_of_acl);
 768	if (rc) {
 769		cifs_dbg(FYI, "%s: Error %d mapping Owner SID to gid\n",
 770			 __func__, rc);
 771		return rc;
 772	}
 773	rc = sid_to_id(cifs_sb, group_sid_ptr, fattr, SIDGROUP);
 774	if (rc) {
 775		cifs_dbg(FYI, "%s: Error %d mapping Group SID to gid\n",
 776			 __func__, rc);
 777		return rc;
 778	}
 779
 780	if (dacloffset)
 781		parse_dacl(dacl_ptr, end_of_acl, owner_sid_ptr,
 782			   group_sid_ptr, fattr);
 783	else
 784		cifs_dbg(FYI, "no ACL\n"); /* BB grant all or default perms? */
 785
 786	return rc;
 787}
 788
 789/* Convert permission bits from mode to equivalent CIFS ACL */
 790static int build_sec_desc(struct cifs_ntsd *pntsd, struct cifs_ntsd *pnntsd,
 791	__u32 secdesclen, __u64 nmode, kuid_t uid, kgid_t gid, int *aclflag)
 792{
 793	int rc = 0;
 794	__u32 dacloffset;
 795	__u32 ndacloffset;
 796	__u32 sidsoffset;
 797	struct cifs_sid *owner_sid_ptr, *group_sid_ptr;
 798	struct cifs_sid *nowner_sid_ptr, *ngroup_sid_ptr;
 799	struct cifs_acl *dacl_ptr = NULL;  /* no need for SACL ptr */
 800	struct cifs_acl *ndacl_ptr = NULL; /* no need for SACL ptr */
 801
 802	if (nmode != NO_CHANGE_64) { /* chmod */
 803		owner_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 804				le32_to_cpu(pntsd->osidoffset));
 805		group_sid_ptr = (struct cifs_sid *)((char *)pntsd +
 806				le32_to_cpu(pntsd->gsidoffset));
 807		dacloffset = le32_to_cpu(pntsd->dacloffset);
 808		dacl_ptr = (struct cifs_acl *)((char *)pntsd + dacloffset);
 809		ndacloffset = sizeof(struct cifs_ntsd);
 810		ndacl_ptr = (struct cifs_acl *)((char *)pnntsd + ndacloffset);
 811		ndacl_ptr->revision = dacl_ptr->revision;
 812		ndacl_ptr->size = 0;
 813		ndacl_ptr->num_aces = 0;
 814
 815		rc = set_chmod_dacl(ndacl_ptr, owner_sid_ptr, group_sid_ptr,
 816					nmode);
 817		sidsoffset = ndacloffset + le16_to_cpu(ndacl_ptr->size);
 818		/* copy sec desc control portion & owner and group sids */
 819		copy_sec_desc(pntsd, pnntsd, sidsoffset);
 820		*aclflag = CIFS_ACL_DACL;
 821	} else {
 822		memcpy(pnntsd, pntsd, secdesclen);
 823		if (uid_valid(uid)) { /* chown */
 824			uid_t id;
 825			owner_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
 826					le32_to_cpu(pnntsd->osidoffset));
 827			nowner_sid_ptr = kmalloc(sizeof(struct cifs_sid),
 828								GFP_KERNEL);
 829			if (!nowner_sid_ptr)
 830				return -ENOMEM;
 831			id = from_kuid(&init_user_ns, uid);
 832			rc = id_to_sid(id, SIDOWNER, nowner_sid_ptr);
 833			if (rc) {
 834				cifs_dbg(FYI, "%s: Mapping error %d for owner id %d\n",
 835					 __func__, rc, id);
 836				kfree(nowner_sid_ptr);
 837				return rc;
 838			}
 839			cifs_copy_sid(owner_sid_ptr, nowner_sid_ptr);
 840			kfree(nowner_sid_ptr);
 841			*aclflag = CIFS_ACL_OWNER;
 842		}
 843		if (gid_valid(gid)) { /* chgrp */
 844			gid_t id;
 845			group_sid_ptr = (struct cifs_sid *)((char *)pnntsd +
 846					le32_to_cpu(pnntsd->gsidoffset));
 847			ngroup_sid_ptr = kmalloc(sizeof(struct cifs_sid),
 848								GFP_KERNEL);
 849			if (!ngroup_sid_ptr)
 850				return -ENOMEM;
 851			id = from_kgid(&init_user_ns, gid);
 852			rc = id_to_sid(id, SIDGROUP, ngroup_sid_ptr);
 853			if (rc) {
 854				cifs_dbg(FYI, "%s: Mapping error %d for group id %d\n",
 855					 __func__, rc, id);
 856				kfree(ngroup_sid_ptr);
 857				return rc;
 858			}
 859			cifs_copy_sid(group_sid_ptr, ngroup_sid_ptr);
 860			kfree(ngroup_sid_ptr);
 861			*aclflag = CIFS_ACL_GROUP;
 862		}
 863	}
 864
 865	return rc;
 866}
 867
 868struct cifs_ntsd *get_cifs_acl_by_fid(struct cifs_sb_info *cifs_sb,
 869		const struct cifs_fid *cifsfid, u32 *pacllen)
 870{
 871	struct cifs_ntsd *pntsd = NULL;
 872	unsigned int xid;
 873	int rc;
 874	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 875
 876	if (IS_ERR(tlink))
 877		return ERR_CAST(tlink);
 878
 879	xid = get_xid();
 880	rc = CIFSSMBGetCIFSACL(xid, tlink_tcon(tlink), cifsfid->netfid, &pntsd,
 881				pacllen);
 882	free_xid(xid);
 883
 884	cifs_put_tlink(tlink);
 885
 886	cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
 887	if (rc)
 888		return ERR_PTR(rc);
 889	return pntsd;
 890}
 891
 892static struct cifs_ntsd *get_cifs_acl_by_path(struct cifs_sb_info *cifs_sb,
 893		const char *path, u32 *pacllen)
 894{
 895	struct cifs_ntsd *pntsd = NULL;
 896	int oplock = 0;
 897	unsigned int xid;
 898	int rc, create_options = 0;
 899	struct cifs_tcon *tcon;
 900	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 901	struct cifs_fid fid;
 902	struct cifs_open_parms oparms;
 903
 904	if (IS_ERR(tlink))
 905		return ERR_CAST(tlink);
 906
 907	tcon = tlink_tcon(tlink);
 908	xid = get_xid();
 909
 910	if (backup_cred(cifs_sb))
 911		create_options |= CREATE_OPEN_BACKUP_INTENT;
 912
 913	oparms.tcon = tcon;
 914	oparms.cifs_sb = cifs_sb;
 915	oparms.desired_access = READ_CONTROL;
 916	oparms.create_options = create_options;
 917	oparms.disposition = FILE_OPEN;
 918	oparms.path = path;
 919	oparms.fid = &fid;
 920	oparms.reconnect = false;
 921
 922	rc = CIFS_open(xid, &oparms, &oplock, NULL);
 923	if (!rc) {
 924		rc = CIFSSMBGetCIFSACL(xid, tcon, fid.netfid, &pntsd, pacllen);
 925		CIFSSMBClose(xid, tcon, fid.netfid);
 926	}
 927
 928	cifs_put_tlink(tlink);
 929	free_xid(xid);
 930
 931	cifs_dbg(FYI, "%s: rc = %d ACL len %d\n", __func__, rc, *pacllen);
 932	if (rc)
 933		return ERR_PTR(rc);
 934	return pntsd;
 935}
 936
 937/* Retrieve an ACL from the server */
 938struct cifs_ntsd *get_cifs_acl(struct cifs_sb_info *cifs_sb,
 939				      struct inode *inode, const char *path,
 940				      u32 *pacllen)
 941{
 942	struct cifs_ntsd *pntsd = NULL;
 943	struct cifsFileInfo *open_file = NULL;
 944
 945	if (inode)
 946		open_file = find_readable_file(CIFS_I(inode), true);
 947	if (!open_file)
 948		return get_cifs_acl_by_path(cifs_sb, path, pacllen);
 949
 950	pntsd = get_cifs_acl_by_fid(cifs_sb, &open_file->fid, pacllen);
 951	cifsFileInfo_put(open_file);
 952	return pntsd;
 953}
 954
 955 /* Set an ACL on the server */
 956int set_cifs_acl(struct cifs_ntsd *pnntsd, __u32 acllen,
 957			struct inode *inode, const char *path, int aclflag)
 958{
 959	int oplock = 0;
 960	unsigned int xid;
 961	int rc, access_flags, create_options = 0;
 962	struct cifs_tcon *tcon;
 963	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
 964	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
 965	struct cifs_fid fid;
 966	struct cifs_open_parms oparms;
 967
 968	if (IS_ERR(tlink))
 969		return PTR_ERR(tlink);
 970
 971	tcon = tlink_tcon(tlink);
 972	xid = get_xid();
 973
 974	if (backup_cred(cifs_sb))
 975		create_options |= CREATE_OPEN_BACKUP_INTENT;
 976
 977	if (aclflag == CIFS_ACL_OWNER || aclflag == CIFS_ACL_GROUP)
 978		access_flags = WRITE_OWNER;
 979	else
 980		access_flags = WRITE_DAC;
 981
 982	oparms.tcon = tcon;
 983	oparms.cifs_sb = cifs_sb;
 984	oparms.desired_access = access_flags;
 985	oparms.create_options = create_options;
 986	oparms.disposition = FILE_OPEN;
 987	oparms.path = path;
 988	oparms.fid = &fid;
 989	oparms.reconnect = false;
 990
 991	rc = CIFS_open(xid, &oparms, &oplock, NULL);
 992	if (rc) {
 993		cifs_dbg(VFS, "Unable to open file to set ACL\n");
 994		goto out;
 995	}
 996
 997	rc = CIFSSMBSetCIFSACL(xid, tcon, fid.netfid, pnntsd, acllen, aclflag);
 998	cifs_dbg(NOISY, "SetCIFSACL rc = %d\n", rc);
 999
1000	CIFSSMBClose(xid, tcon, fid.netfid);
1001out:
1002	free_xid(xid);
1003	cifs_put_tlink(tlink);
1004	return rc;
1005}
1006
1007/* Translate the CIFS ACL (simlar to NTFS ACL) for a file into mode bits */
1008int
1009cifs_acl_to_fattr(struct cifs_sb_info *cifs_sb, struct cifs_fattr *fattr,
1010		  struct inode *inode, const char *path,
1011		  const struct cifs_fid *pfid)
1012{
1013	struct cifs_ntsd *pntsd = NULL;
1014	u32 acllen = 0;
1015	int rc = 0;
1016	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1017	struct cifs_tcon *tcon;
1018
1019	cifs_dbg(NOISY, "converting ACL to mode for %s\n", path);
1020
1021	if (IS_ERR(tlink))
1022		return PTR_ERR(tlink);
1023	tcon = tlink_tcon(tlink);
1024
1025	if (pfid && (tcon->ses->server->ops->get_acl_by_fid))
1026		pntsd = tcon->ses->server->ops->get_acl_by_fid(cifs_sb, pfid,
1027							  &acllen);
1028	else if (tcon->ses->server->ops->get_acl)
1029		pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1030							&acllen);
1031	else {
1032		cifs_put_tlink(tlink);
1033		return -EOPNOTSUPP;
1034	}
1035	/* if we can retrieve the ACL, now parse Access Control Entries, ACEs */
1036	if (IS_ERR(pntsd)) {
1037		rc = PTR_ERR(pntsd);
1038		cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1039	} else {
1040		rc = parse_sec_desc(cifs_sb, pntsd, acllen, fattr);
1041		kfree(pntsd);
1042		if (rc)
1043			cifs_dbg(VFS, "parse sec desc failed rc = %d\n", rc);
1044	}
1045
1046	cifs_put_tlink(tlink);
1047
1048	return rc;
1049}
1050
1051/* Convert mode bits to an ACL so we can update the ACL on the server */
1052int
1053id_mode_to_cifs_acl(struct inode *inode, const char *path, __u64 nmode,
1054			kuid_t uid, kgid_t gid)
1055{
1056	int rc = 0;
1057	int aclflag = CIFS_ACL_DACL; /* default flag to set */
1058	__u32 secdesclen = 0;
1059	struct cifs_ntsd *pntsd = NULL; /* acl obtained from server */
1060	struct cifs_ntsd *pnntsd = NULL; /* modified acl to be sent to server */
1061	struct cifs_sb_info *cifs_sb = CIFS_SB(inode->i_sb);
1062	struct tcon_link *tlink = cifs_sb_tlink(cifs_sb);
1063	struct cifs_tcon *tcon;
1064
1065	if (IS_ERR(tlink))
1066		return PTR_ERR(tlink);
1067	tcon = tlink_tcon(tlink);
1068
1069	cifs_dbg(NOISY, "set ACL from mode for %s\n", path);
1070
1071	/* Get the security descriptor */
1072
1073	if (tcon->ses->server->ops->get_acl == NULL) {
1074		cifs_put_tlink(tlink);
1075		return -EOPNOTSUPP;
1076	}
1077
1078	pntsd = tcon->ses->server->ops->get_acl(cifs_sb, inode, path,
1079						&secdesclen);
1080	if (IS_ERR(pntsd)) {
1081		rc = PTR_ERR(pntsd);
1082		cifs_dbg(VFS, "%s: error %d getting sec desc\n", __func__, rc);
1083		cifs_put_tlink(tlink);
1084		return rc;
1085	}
1086
1087	/*
1088	 * Add three ACEs for owner, group, everyone getting rid of other ACEs
1089	 * as chmod disables ACEs and set the security descriptor. Allocate
1090	 * memory for the smb header, set security descriptor request security
1091	 * descriptor parameters, and secuirty descriptor itself
1092	 */
1093	secdesclen = max_t(u32, secdesclen, DEFAULT_SEC_DESC_LEN);
1094	pnntsd = kmalloc(secdesclen, GFP_KERNEL);
1095	if (!pnntsd) {
1096		kfree(pntsd);
1097		cifs_put_tlink(tlink);
1098		return -ENOMEM;
1099	}
1100
1101	rc = build_sec_desc(pntsd, pnntsd, secdesclen, nmode, uid, gid,
1102				&aclflag);
1103
1104	cifs_dbg(NOISY, "build_sec_desc rc: %d\n", rc);
1105
1106	if (tcon->ses->server->ops->set_acl == NULL)
1107		rc = -EOPNOTSUPP;
1108
1109	if (!rc) {
1110		/* Set the security descriptor */
1111		rc = tcon->ses->server->ops->set_acl(pnntsd, secdesclen, inode,
1112						     path, aclflag);
1113		cifs_dbg(NOISY, "set_cifs_acl rc: %d\n", rc);
1114	}
1115	cifs_put_tlink(tlink);
1116
1117	kfree(pnntsd);
1118	kfree(pntsd);
1119	return rc;
1120}