1/* 2 Unix SMB/CIFS implementation. 3 4 security access checking routines 5 6 Copyright (C) Andrew Tridgell 2004 7 8 This program is free software; you can redistribute it and/or modify 9 it under the terms of the GNU General Public License as published by 10 the Free Software Foundation; either version 3 of the License, or 11 (at your option) any later version. 12 13 This program is distributed in the hope that it will be useful, 14 but WITHOUT ANY WARRANTY; without even the implied warranty of 15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 16 GNU General Public License for more details. 17 18 You should have received a copy of the GNU General Public License 19 along with this program. If not, see <http://www.gnu.org/licenses/>. 20*/ 21 22#include "includes.h" 23#include "libcli/security/security.h" 24 25 26/* 27 perform a SEC_FLAG_MAXIMUM_ALLOWED access check 28*/ 29static uint32_t access_check_max_allowed(const struct security_descriptor *sd, 30 const struct security_token *token) 31{ 32 uint32_t denied = 0, granted = 0; 33 unsigned i; 34 35 if (security_token_has_sid(token, sd->owner_sid)) { 36 granted |= SEC_STD_WRITE_DAC | SEC_STD_READ_CONTROL | SEC_STD_DELETE; 37 } else if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) { 38 granted |= SEC_STD_DELETE; 39 } 40 41 if (sd->dacl == NULL) { 42 return granted & ~denied; 43 } 44 45 for (i = 0;i<sd->dacl->num_aces; i++) { 46 struct security_ace *ace = &sd->dacl->aces[i]; 47 48 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { 49 continue; 50 } 51 52 if (!security_token_has_sid(token, &ace->trustee)) { 53 continue; 54 } 55 56 switch (ace->type) { 57 case SEC_ACE_TYPE_ACCESS_ALLOWED: 58 granted |= ace->access_mask; 59 break; 60 case SEC_ACE_TYPE_ACCESS_DENIED: 61 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: 62 denied |= ace->access_mask; 63 break; 64 default: /* Other ACE types not handled/supported */ 65 break; 66 } 67 } 68 69 return granted & ~denied; 70} 71 72static const struct GUID *get_ace_object_type(struct security_ace *ace) 73{ 74 struct GUID *type; 75 76 if (ace->object.object.flags & SEC_ACE_OBJECT_TYPE_PRESENT) 77 type = &ace->object.object.type.type; 78 else if (ace->object.object.flags & SEC_ACE_INHERITED_OBJECT_TYPE_PRESENT) 79 type = &ace->object.object.inherited_type.inherited_type; /* This doesn't look right. Is something wrong with the IDL? */ 80 else 81 type = NULL; 82 83 return type; 84 85} 86 87/* 88 the main entry point for access checking. 89*/ 90NTSTATUS sec_access_check(const struct security_descriptor *sd, 91 const struct security_token *token, 92 uint32_t access_desired, 93 uint32_t *access_granted) 94{ 95 int i; 96 uint32_t bits_remaining; 97 98 *access_granted = access_desired; 99 bits_remaining = access_desired; 100 101 /* handle the maximum allowed flag */ 102 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) { 103 access_desired |= access_check_max_allowed(sd, token); 104 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED; 105 *access_granted = access_desired; 106 bits_remaining = access_desired & ~SEC_STD_DELETE; 107 } 108 109 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) { 110 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { 111 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY; 112 } else { 113 return NT_STATUS_PRIVILEGE_NOT_HELD; 114 } 115 } 116 117 /* a NULL dacl allows access */ 118 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) { 119 *access_granted = access_desired; 120 return NT_STATUS_OK; 121 } 122 123 /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */ 124 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) && 125 security_token_has_sid(token, sd->owner_sid)) { 126 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE); 127 } 128 if ((bits_remaining & SEC_STD_DELETE) && 129 security_token_has_privilege(token, SEC_PRIV_RESTORE)) { 130 bits_remaining &= ~SEC_STD_DELETE; 131 } 132 133 if (sd->dacl == NULL) { 134 goto done; 135 } 136 137 /* check each ace in turn. */ 138 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { 139 struct security_ace *ace = &sd->dacl->aces[i]; 140 141 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { 142 continue; 143 } 144 145 if (!security_token_has_sid(token, &ace->trustee)) { 146 continue; 147 } 148 149 switch (ace->type) { 150 case SEC_ACE_TYPE_ACCESS_ALLOWED: 151 bits_remaining &= ~ace->access_mask; 152 break; 153 case SEC_ACE_TYPE_ACCESS_DENIED: 154 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: 155 if (bits_remaining & ace->access_mask) { 156 return NT_STATUS_ACCESS_DENIED; 157 } 158 break; 159 default: /* Other ACE types not handled/supported */ 160 break; 161 } 162 } 163 164done: 165 if (bits_remaining != 0) { 166 return NT_STATUS_ACCESS_DENIED; 167 } 168 169 return NT_STATUS_OK; 170} 171 172/* modified access check for the purposes of DS security 173 * Lots of code duplication, it will ve united in just one 174 * function eventually */ 175 176NTSTATUS sec_access_check_ds(const struct security_descriptor *sd, 177 const struct security_token *token, 178 uint32_t access_desired, 179 uint32_t *access_granted, 180 struct object_tree *tree) 181{ 182 int i; 183 uint32_t bits_remaining; 184 struct object_tree *node; 185 struct GUID *type; 186 187 *access_granted = access_desired; 188 bits_remaining = access_desired; 189 190 /* handle the maximum allowed flag */ 191 if (access_desired & SEC_FLAG_MAXIMUM_ALLOWED) { 192 access_desired |= access_check_max_allowed(sd, token); 193 access_desired &= ~SEC_FLAG_MAXIMUM_ALLOWED; 194 *access_granted = access_desired; 195 bits_remaining = access_desired & ~SEC_STD_DELETE; 196 } 197 198 if (access_desired & SEC_FLAG_SYSTEM_SECURITY) { 199 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { 200 bits_remaining &= ~SEC_FLAG_SYSTEM_SECURITY; 201 } else { 202 return NT_STATUS_PRIVILEGE_NOT_HELD; 203 } 204 } 205 206 /* a NULL dacl allows access */ 207 if ((sd->type & SEC_DESC_DACL_PRESENT) && sd->dacl == NULL) { 208 *access_granted = access_desired; 209 return NT_STATUS_OK; 210 } 211 212 /* the owner always gets SEC_STD_WRITE_DAC, SEC_STD_READ_CONTROL and SEC_STD_DELETE */ 213 if ((bits_remaining & (SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE)) && 214 security_token_has_sid(token, sd->owner_sid)) { 215 bits_remaining &= ~(SEC_STD_WRITE_DAC|SEC_STD_READ_CONTROL|SEC_STD_DELETE); 216 } 217 if ((bits_remaining & SEC_STD_DELETE) && 218 security_token_has_privilege(token, SEC_PRIV_RESTORE)) { 219 bits_remaining &= ~SEC_STD_DELETE; 220 } 221 222 if (sd->dacl == NULL) { 223 goto done; 224 } 225 226 /* check each ace in turn. */ 227 for (i=0; bits_remaining && i < sd->dacl->num_aces; i++) { 228 struct security_ace *ace = &sd->dacl->aces[i]; 229 230 if (ace->flags & SEC_ACE_FLAG_INHERIT_ONLY) { 231 continue; 232 } 233 234 if (!security_token_has_sid(token, &ace->trustee)) { 235 continue; 236 } 237 238 switch (ace->type) { 239 case SEC_ACE_TYPE_ACCESS_ALLOWED: 240 if (tree) 241 object_tree_modify_access(tree, ace->access_mask); 242 243 bits_remaining &= ~ace->access_mask; 244 break; 245 case SEC_ACE_TYPE_ACCESS_DENIED: 246 if (bits_remaining & ace->access_mask) { 247 return NT_STATUS_ACCESS_DENIED; 248 } 249 break; 250 case SEC_ACE_TYPE_ACCESS_DENIED_OBJECT: 251 case SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT: 252 /* check only in case we have provided a tree, 253 * the ACE has an object type and that type 254 * is in the tree */ 255 type = get_ace_object_type(ace); 256 257 if (!tree) 258 continue; 259 260 if (!type) 261 node = tree; 262 else 263 if (!(node = get_object_tree_by_GUID(tree, type))) 264 continue; 265 266 if (ace->type == SEC_ACE_TYPE_ACCESS_ALLOWED_OBJECT){ 267 object_tree_modify_access(node, ace->access_mask); 268 } 269 else { 270 if (node->remaining_access & ace->access_mask){ 271 return NT_STATUS_ACCESS_DENIED; 272 } 273 } 274 break; 275 default: /* Other ACE types not handled/supported */ 276 break; 277 } 278 } 279 280done: 281 if (bits_remaining != 0) { 282 return NT_STATUS_ACCESS_DENIED; 283 } 284 285 return NT_STATUS_OK; 286} 287 288 289 290 291