1/* 2 Unix SMB/Netbios implementation. 3 VFS module to get and set posix acls 4 Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2006 5 6 This program is free software; you can redistribute it and/or modify 7 it under the terms of the GNU General Public License as published by 8 the Free Software Foundation; either version 2 of the License, or 9 (at your option) any later version. 10 11 This program is distributed in the hope that it will be useful, 12 but WITHOUT ANY WARRANTY; without even the implied warranty of 13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 GNU General Public License for more details. 15 16 You should have received a copy of the GNU General Public License 17 along with this program; if not, write to the Free Software 18 Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 19*/ 20 21#include "includes.h" 22 23SMB_ACL_T aixacl_to_smbacl(struct acl *file_acl) 24{ 25 struct acl_entry *acl_entry; 26 struct ace_id *idp; 27 28 struct smb_acl_t *result = SMB_MALLOC_P(struct smb_acl_t); 29 struct smb_acl_entry *ace; 30 int i; 31 32 if (result == NULL) { 33 return NULL; 34 } 35 ZERO_STRUCTP(result); 36 37 /* Point to the first acl entry in the acl */ 38 acl_entry = file_acl->acl_ext; 39 40 41 42 DEBUG(10,("acl_entry is %d\n",acl_entry)); 43 DEBUG(10,("acl_last(file_acl) id %d\n",acl_last(file_acl))); 44 45 /* Check if the extended acl bit is on. * 46 * If it isn't, do not show the * 47 * contents of the acl since AIX intends * 48 * the extended info to remain unused */ 49 50 if(file_acl->acl_mode & S_IXACL){ 51 /* while we are not pointing to the very end */ 52 while(acl_entry < acl_last(file_acl)) { 53 /* before we malloc anything, make sure this is */ 54 /* a valid acl entry and one that we want to map */ 55 idp = id_nxt(acl_entry->ace_id); 56 if((acl_entry->ace_type == ACC_SPECIFY || 57 (acl_entry->ace_type == ACC_PERMIT)) && (idp != id_last(acl_entry))) { 58 acl_entry = acl_nxt(acl_entry); 59 continue; 60 } 61 62 idp = acl_entry->ace_id; 63 DEBUG(10,("idp->id_data is %d\n",idp->id_data[0])); 64 65 result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + 66 (sizeof(struct smb_acl_entry) * 67 (result->count+1))); 68 if (result == NULL) { 69 DEBUG(0, ("SMB_REALLOC failed\n")); 70 errno = ENOMEM; 71 return NULL; 72 } 73 74 75 DEBUG(10,("idp->id_type is %d\n",idp->id_type)); 76 ace = &result->acl[result->count]; 77 78 ace->a_type = idp->id_type; 79 80 switch(ace->a_type) { 81 case ACEID_USER: { 82 ace->uid = idp->id_data[0]; 83 DEBUG(10,("case ACEID_USER ace->uid is %d\n",ace->uid)); 84 ace->a_type = SMB_ACL_USER; 85 break; 86 } 87 88 case ACEID_GROUP: { 89 ace->gid = idp->id_data[0]; 90 DEBUG(10,("case ACEID_GROUP ace->gid is %d\n",ace->gid)); 91 ace->a_type = SMB_ACL_GROUP; 92 break; 93 } 94 default: 95 break; 96 } 97 /* The access in the acl entries must be left shifted by * 98 * three bites, because they will ultimately be compared * 99 * to S_IRUSR, S_IWUSR, and S_IXUSR. */ 100 101 switch(acl_entry->ace_type){ 102 case ACC_PERMIT: 103 case ACC_SPECIFY: 104 ace->a_perm = acl_entry->ace_access; 105 ace->a_perm <<= 6; 106 DEBUG(10,("ace->a_perm is %d\n",ace->a_perm)); 107 break; 108 case ACC_DENY: 109 /* Since there is no way to return a DENY acl entry * 110 * change to PERMIT and then shift. */ 111 DEBUG(10,("acl_entry->ace_access is %d\n",acl_entry->ace_access)); 112 ace->a_perm = ~acl_entry->ace_access & 7; 113 DEBUG(10,("ace->a_perm is %d\n",ace->a_perm)); 114 ace->a_perm <<= 6; 115 break; 116 default: 117 DEBUG(0, ("unknown ace->type\n")); 118 SAFE_FREE(result); 119 return(0); 120 } 121 122 result->count++; 123 ace->a_perm |= (ace->a_perm & S_IRUSR) ? SMB_ACL_READ : 0; 124 ace->a_perm |= (ace->a_perm & S_IWUSR) ? SMB_ACL_WRITE : 0; 125 ace->a_perm |= (ace->a_perm & S_IXUSR) ? SMB_ACL_EXECUTE : 0; 126 DEBUG(10,("ace->a_perm is %d\n",ace->a_perm)); 127 128 DEBUG(10,("acl_entry = %d\n",acl_entry)); 129 DEBUG(10,("The ace_type is %d\n",acl_entry->ace_type)); 130 131 acl_entry = acl_nxt(acl_entry); 132 } 133 } /* end of if enabled */ 134 135 /* Since owner, group, other acl entries are not * 136 * part of the acl entries in an acl, they must * 137 * be dummied up to become part of the list. */ 138 139 for( i = 1; i < 4; i++) { 140 DEBUG(10,("i is %d\n",i)); 141 142 result = SMB_REALLOC(result, sizeof(struct smb_acl_t) + 143 (sizeof(struct smb_acl_entry) * 144 (result->count+1))); 145 if (result == NULL) { 146 DEBUG(0, ("SMB_REALLOC failed\n")); 147 errno = ENOMEM; 148 DEBUG(0,("Error in AIX sys_acl_get_file is %d\n",errno)); 149 return NULL; 150 } 151 152 ace = &result->acl[result->count]; 153 154 ace->uid = 0; 155 ace->gid = 0; 156 DEBUG(10,("ace->uid = %d\n",ace->uid)); 157 158 switch(i) { 159 case 2: 160 ace->a_perm = file_acl->g_access << 6; 161 ace->a_type = SMB_ACL_GROUP_OBJ; 162 break; 163 164 case 3: 165 ace->a_perm = file_acl->o_access << 6; 166 ace->a_type = SMB_ACL_OTHER; 167 break; 168 169 case 1: 170 ace->a_perm = file_acl->u_access << 6; 171 ace->a_type = SMB_ACL_USER_OBJ; 172 break; 173 174 default: 175 return(NULL); 176 177 } 178 ace->a_perm |= ((ace->a_perm & S_IRUSR) ? SMB_ACL_READ : 0); 179 ace->a_perm |= ((ace->a_perm & S_IWUSR) ? SMB_ACL_WRITE : 0); 180 ace->a_perm |= ((ace->a_perm & S_IXUSR) ? SMB_ACL_EXECUTE : 0); 181 182 memcpy(&result->acl[result->count],ace,sizeof(struct smb_acl_entry)); 183 result->count++; 184 DEBUG(10,("ace->a_perm = %d\n",ace->a_perm)); 185 DEBUG(10,("ace->a_type = %d\n",ace->a_type)); 186 } 187 188 189 return result; 190 191 192} 193 194static ushort aixacl_smb_to_aixperm(SMB_ACL_PERM_T a_perm) 195{ 196 ushort ret = (ushort)0; 197 if (a_perm & SMB_ACL_READ) 198 ret |= R_ACC; 199 if (a_perm & SMB_ACL_WRITE) 200 ret |= W_ACC; 201 if (a_perm & SMB_ACL_EXECUTE) 202 ret |= X_ACC; 203 return ret; 204} 205 206struct acl *aixacl_smb_to_aixacl(SMB_ACL_TYPE_T acltype, SMB_ACL_T theacl) 207{ 208 struct smb_acl_entry *smb_entry = NULL; 209 struct acl *file_acl = NULL; 210 struct acl *file_acl_temp = NULL; 211 struct acl_entry *acl_entry = NULL; 212 struct ace_id *ace_id = NULL; 213 uint id_type; 214 uint user_id; 215 uint acl_length; 216 int i; 217 218 DEBUG(10,("Entering aixacl_smb_to_aixacl\n")); 219 /* AIX has no default ACL */ 220 if(acltype == SMB_ACL_TYPE_DEFAULT) 221 return NULL; 222 223 acl_length = BUFSIZ; 224 file_acl = (struct acl *)SMB_MALLOC(BUFSIZ); 225 if(file_acl == NULL) { 226 errno = ENOMEM; 227 DEBUG(0,("Error in aixacl_smb_to_aixacl is %d\n",errno)); 228 return NULL; 229 } 230 231 memset(file_acl,0,BUFSIZ); 232 233 file_acl->acl_len = ACL_SIZ; 234 file_acl->acl_mode = S_IXACL; 235 236 for(i=0; i<theacl->count; i++ ) { 237 smb_entry = &(theacl->acl[i]); 238 id_type = smb_entry->a_type; 239 DEBUG(10,("The id_type is %d\n",id_type)); 240 241 switch(id_type) { 242 case SMB_ACL_USER_OBJ: 243 file_acl->u_access = aixacl_smb_to_aixperm(smb_entry->a_perm); 244 continue; 245 case SMB_ACL_GROUP_OBJ: 246 file_acl->g_access = aixacl_smb_to_aixperm(smb_entry->a_perm); 247 continue; 248 case SMB_ACL_OTHER: 249 file_acl->o_access = aixacl_smb_to_aixperm(smb_entry->a_perm); 250 continue; 251 case SMB_ACL_MASK: 252 continue; 253 case SMB_ACL_GROUP: 254 break; /* process this */ 255 case SMB_ACL_USER: 256 break; /* process this */ 257 default: /* abnormal case */ 258 DEBUG(10,("The id_type is unknown !\n")); 259 continue; 260 } 261 262 if((file_acl->acl_len + sizeof(struct acl_entry)) > acl_length) { 263 acl_length += sizeof(struct acl_entry); 264 file_acl_temp = (struct acl *)SMB_MALLOC(acl_length); 265 if(file_acl_temp == NULL) { 266 SAFE_FREE(file_acl); 267 errno = ENOMEM; 268 DEBUG(0,("Error in aixacl_smb_to_aixacl is %d\n",errno)); 269 return NULL; 270 } 271 272 memcpy(file_acl_temp,file_acl,file_acl->acl_len); 273 SAFE_FREE(file_acl); 274 file_acl = file_acl_temp; 275 } 276 277 acl_entry = (struct acl_entry *)((char *)file_acl + file_acl->acl_len); 278 file_acl->acl_len += sizeof(struct acl_entry); 279 acl_entry->ace_len = sizeof(struct acl_entry); /* contains 1 ace_id */ 280 acl_entry->ace_access = aixacl_smb_to_aixperm(smb_entry->a_perm); 281 282 /* In order to use this, we'll need to wait until we can get denies */ 283 /* if(!acl_entry->ace_access && acl_entry->ace_type == ACC_PERMIT) 284 acl_entry->ace_type = ACC_SPECIFY; */ 285 286 acl_entry->ace_type = ACC_SPECIFY; 287 288 ace_id = acl_entry->ace_id; 289 290 ace_id->id_type = (smb_entry->a_type==SMB_ACL_GROUP) ? ACEID_GROUP : ACEID_USER; 291 DEBUG(10,("The id type is %d\n",ace_id->id_type)); 292 ace_id->id_len = sizeof(struct ace_id); /* contains 1 id_data */ 293 ace_id->id_data[0] = (smb_entry->a_type==SMB_ACL_GROUP) ? smb_entry->gid : smb_entry->uid; 294 } 295 296 return file_acl; 297} 298