1 /* 2 * Copyright (c) 2005, PADL Software Pty Ltd. 3 * All rights reserved. 4 * 5 * Portions Copyright (c) 2009 Apple Inc. All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 18 * 3. Neither the name of PADL Software nor the names of its contributors 19 * may be used to endorse or promote products derived from this software 20 * without specific prior written permission. 21 * 22 * THIS SOFTWARE IS PROVIDED BY PADL SOFTWARE AND CONTRIBUTORS ``AS IS'' AND 23 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 24 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 25 * ARE DISCLAIMED. IN NO EVENT SHALL PADL SOFTWARE OR CONTRIBUTORS BE LIABLE 26 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 27 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 28 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 29 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 30 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 31 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 */ 34 35 #include "kcm_locl.h" 36 37 krb5_error_code 38 kcm_access(krb5_context context, 39 kcm_client *client, 40 kcm_operation opcode, 41 kcm_ccache ccache) 42 { 43 int read_p = 0; 44 int write_p = 0; 45 uint16_t mask; 46 krb5_error_code ret; 47 48 KCM_ASSERT_VALID(ccache); 49 50 switch (opcode) { 51 case KCM_OP_INITIALIZE: 52 case KCM_OP_DESTROY: 53 case KCM_OP_STORE: 54 case KCM_OP_REMOVE_CRED: 55 case KCM_OP_SET_FLAGS: 56 case KCM_OP_CHOWN: 57 case KCM_OP_CHMOD: 58 case KCM_OP_GET_INITIAL_TICKET: 59 case KCM_OP_GET_TICKET: 60 case KCM_OP_MOVE_CACHE: 61 case KCM_OP_SET_DEFAULT_CACHE: 62 case KCM_OP_SET_KDC_OFFSET: 63 write_p = 1; 64 read_p = 0; 65 break; 66 case KCM_OP_NOOP: 67 case KCM_OP_GET_NAME: 68 case KCM_OP_RESOLVE: 69 case KCM_OP_GEN_NEW: 70 case KCM_OP_RETRIEVE: 71 case KCM_OP_GET_PRINCIPAL: 72 case KCM_OP_GET_CRED_UUID_LIST: 73 case KCM_OP_GET_CRED_BY_UUID: 74 case KCM_OP_GET_CACHE_UUID_LIST: 75 case KCM_OP_GET_CACHE_BY_UUID: 76 case KCM_OP_GET_DEFAULT_CACHE: 77 case KCM_OP_GET_KDC_OFFSET: 78 write_p = 0; 79 read_p = 1; 80 break; 81 default: 82 ret = KRB5_FCC_PERM; 83 goto out; 84 } 85 86 if (ccache->flags & KCM_FLAGS_OWNER_IS_SYSTEM) { 87 /* System caches cannot be reinitialized or destroyed by users */ 88 if (opcode == KCM_OP_INITIALIZE || 89 opcode == KCM_OP_DESTROY || 90 opcode == KCM_OP_REMOVE_CRED || 91 opcode == KCM_OP_MOVE_CACHE) { 92 ret = KRB5_FCC_PERM; 93 goto out; 94 } 95 96 /* Let root always read system caches */ 97 if (CLIENT_IS_ROOT(client)) { 98 ret = 0; 99 goto out; 100 } 101 } 102 103 /* start out with "other" mask */ 104 mask = S_IROTH|S_IWOTH; 105 106 /* root can do anything */ 107 if (CLIENT_IS_ROOT(client)) { 108 if (read_p) 109 mask |= S_IRUSR|S_IRGRP|S_IROTH; 110 if (write_p) 111 mask |= S_IWUSR|S_IWGRP|S_IWOTH; 112 } 113 /* same session same as owner */ 114 if (kcm_is_same_session(client, ccache->uid, ccache->session)) { 115 if (read_p) 116 mask |= S_IROTH; 117 if (write_p) 118 mask |= S_IWOTH; 119 } 120 /* owner */ 121 if (client->uid == ccache->uid) { 122 if (read_p) 123 mask |= S_IRUSR; 124 if (write_p) 125 mask |= S_IWUSR; 126 } 127 /* group */ 128 if (client->gid == ccache->gid) { 129 if (read_p) 130 mask |= S_IRGRP; 131 if (write_p) 132 mask |= S_IWGRP; 133 } 134 135 ret = (ccache->mode & mask) ? 0 : KRB5_FCC_PERM; 136 137 out: 138 if (ret) { 139 kcm_log(2, "Process %d is not permitted to call %s on cache %s", 140 client->pid, kcm_op2string(opcode), ccache->name); 141 } 142 143 return ret; 144 } 145 146 krb5_error_code 147 kcm_chmod(krb5_context context, 148 kcm_client *client, 149 kcm_ccache ccache, 150 uint16_t mode) 151 { 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 173 krb5_error_code 174 kcm_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