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