1235368Sgnn/* 2235368Sgnn * Copyright (c) 2005, PADL Software Pty Ltd. 3235368Sgnn * All rights reserved. 4235368Sgnn * 5235368Sgnn * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 6235368Sgnn * 7235368Sgnn * Redistribution and use in source and binary forms, with or without 8235368Sgnn * modification, are permitted provided that the following conditions 9235368Sgnn * are met: 10235368Sgnn * 11235368Sgnn * 1. Redistributions of source code must retain the above copyright 12235368Sgnn * notice, this list of conditions and the following disclaimer. 13235368Sgnn * 14235368Sgnn * 2. Redistributions in binary form must reproduce the above copyright 15235368Sgnn * notice, this list of conditions and the following disclaimer in the 16235368Sgnn * documentation and/or other materials provided with the distribution. 17235368Sgnn * 18235368Sgnn * 3. Neither the name of PADL Software nor the names of its contributors 19235368Sgnn * may be used to endorse or promote products derived from this software 20235368Sgnn * without specific prior written permission. 21235368Sgnn * 22235368Sgnn * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 23235368Sgnn * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24235368Sgnn * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25235368Sgnn * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 26235368Sgnn * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27235368Sgnn * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28235368Sgnn * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29235368Sgnn * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30235368Sgnn * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31235368Sgnn * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32235368Sgnn * SUCH DAMAGE. 33235368Sgnn */ 34235368Sgnn 35235368Sgnn#include "kcm_locl.h" 36235368Sgnn 37235368Sgnnkrb5_error_code 38235368Sgnnkcm_access(krb5_context context, 39235368Sgnn kcm_client *client, 40235368Sgnn kcm_operation opcode, 41235368Sgnn kcm_ccache ccache) 42235368Sgnn{ 43235368Sgnn int read_p = 0; 44235368Sgnn int write_p = 0; 45235368Sgnn uint16_t mask; 46235368Sgnn krb5_error_code ret; 47235368Sgnn 48235368Sgnn KCM_ASSERT_VALID(ccache); 49235368Sgnn 50235368Sgnn switch (opcode) { 51235368Sgnn case KCM_OP_INITIALIZE: 52235368Sgnn case KCM_OP_DESTROY: 53235368Sgnn case KCM_OP_STORE: 54235368Sgnn case KCM_OP_REMOVE_CRED: 55235368Sgnn case KCM_OP_SET_FLAGS: 56235368Sgnn case KCM_OP_CHOWN: 57235368Sgnn case KCM_OP_CHMOD: 58235368Sgnn case KCM_OP_GET_INITIAL_TICKET: 59235368Sgnn case KCM_OP_GET_TICKET: 60235368Sgnn case KCM_OP_MOVE_CACHE: 61235368Sgnn case KCM_OP_SET_DEFAULT_CACHE: 62235368Sgnn case KCM_OP_SET_KDC_OFFSET: 63235368Sgnn write_p = 1; 64235368Sgnn read_p = 0; 65235368Sgnn break; 66235368Sgnn case KCM_OP_NOOP: 67235368Sgnn case KCM_OP_GET_NAME: 68235368Sgnn case KCM_OP_RESOLVE: 69235368Sgnn case KCM_OP_GEN_NEW: 70235368Sgnn case KCM_OP_RETRIEVE: 71235368Sgnn case KCM_OP_GET_PRINCIPAL: 72235368Sgnn case KCM_OP_GET_CRED_UUID_LIST: 73235368Sgnn case KCM_OP_GET_CRED_BY_UUID: 74235368Sgnn case KCM_OP_GET_CACHE_UUID_LIST: 75235368Sgnn case KCM_OP_GET_CACHE_BY_UUID: 76235368Sgnn case KCM_OP_GET_DEFAULT_CACHE: 77235368Sgnn case KCM_OP_GET_KDC_OFFSET: 78235368Sgnn write_p = 0; 79235368Sgnn read_p = 1; 80235368Sgnn break; 81235368Sgnn default: 82235368Sgnn ret = KRB5_FCC_PERM; 83235368Sgnn goto out; 84235368Sgnn } 85235368Sgnn 86235368Sgnn if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) { 87235368Sgnn /* System caches cannot be reinitialized or destroyed by users */ 88235368Sgnn if (opcode == KCM_OP_INITIALIZE || 89235368Sgnn opcode == KCM_OP_DESTROY || 90235368Sgnn opcode == KCM_OP_REMOVE_CRED || 91235368Sgnn opcode == KCM_OP_MOVE_CACHE) { 92235368Sgnn ret = KRB5_FCC_PERM; 93235368Sgnn goto out; 94235368Sgnn } 95235368Sgnn 96235368Sgnn /* Let root always read system caches */ 97235368Sgnn if (CLIENT_IS_ROOT(client)) { 98235368Sgnn ret = 0; 99235368Sgnn goto out; 100235368Sgnn } 101235368Sgnn } 102235368Sgnn 103235368Sgnn /* start out with "other" mask */ 104235368Sgnn mask = S_IROTH|S_IWOTH; 105235368Sgnn 106235368Sgnn /* root can do anything */ 107235368Sgnn if (CLIENT_IS_ROOT(client)) { 108235368Sgnn if (read_p) 109235368Sgnn mask |= S_IRUSR|S_IRGRP|S_IROTH; 110235368Sgnn if (write_p) 111235368Sgnn mask |= S_IWUSR|S_IWGRP|S_IWOTH; 112235368Sgnn } 113235368Sgnn /* same session same as owner */ 114235368Sgnn if (kcm_is_same_session(client, ccache->uid, ccache->session)) { 115235368Sgnn if (read_p) 116235368Sgnn mask |= S_IROTH; 117235368Sgnn if (write_p) 118235368Sgnn mask |= S_IWOTH; 119235368Sgnn } 120235368Sgnn /* owner */ 121235368Sgnn if (client->uid == ccache->uid) { 122235368Sgnn if (read_p) 123235368Sgnn mask |= S_IRUSR; 124235368Sgnn if (write_p) 125235368Sgnn mask |= S_IWUSR; 126235368Sgnn } 127235368Sgnn /* group */ 128235368Sgnn if (client->gid == ccache->gid) { 129235368Sgnn if (read_p) 130235368Sgnn mask |= S_IRGRP; 131235368Sgnn if (write_p) 132235368Sgnn mask |= S_IWGRP; 133235368Sgnn } 134235368Sgnn 135235368Sgnn ret = (ccache->mode & mask) ? 0 : KRB5_FCC_PERM; 136235368Sgnn 137235368Sgnnout: 138235368Sgnn if (ret) { 139235368Sgnn kcm_log(2, "Process %d is not permitted to call %s on cache %s", 140235368Sgnn client->pid, kcm_op2string(opcode), ccache->name); 141235368Sgnn } 142235368Sgnn 143235368Sgnn return ret; 144235368Sgnn} 145235368Sgnn 146235368Sgnnkrb5_error_code 147235368Sgnnkcm_chmod(krb5_context context, 148235368Sgnn kcm_client *client, 149235368Sgnn kcm_ccache ccache, 150235368Sgnn uint16_t mode) 151235368Sgnn{ 152 KCM_ASSERT_VALID(ccache); 153 154 /* System cache mode can only be set at startup */ 155 if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) 156 return KRB5_FCC_PERM; 157 158 if (ccache->uid != client->uid) 159 return KRB5_FCC_PERM; 160 161 if (ccache->gid != client->gid) 162 return KRB5_FCC_PERM; 163 164 HEIMDAL_MUTEX_lock(&ccache->mutex); 165 166 ccache->mode = mode; 167 168 HEIMDAL_MUTEX_unlock(&ccache->mutex); 169 170 return 0; 171} 172 173krb5_error_code 174kcm_chown(krb5_context context, 175 kcm_client *client, 176 kcm_ccache ccache, 177 uid_t uid, 178 gid_t gid) 179{ 180 KCM_ASSERT_VALID(ccache); 181 182 /* System cache owner can only be set at startup */ 183 if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) 184 return KRB5_FCC_PERM; 185 186 if (ccache->uid != client->uid) 187 return KRB5_FCC_PERM; 188 189 if (ccache->gid != client->gid) 190 return KRB5_FCC_PERM; 191 192 HEIMDAL_MUTEX_lock(&ccache->mutex); 193 194 ccache->uid = uid; 195 ccache->gid = gid; 196 197 HEIMDAL_MUTEX_unlock(&ccache->mutex); 198 199 return 0; 200} 201 202