libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2008-2011, 2013 Peter Miller 00004 * Written by Peter Miller <pmiller@opensource.org.au> 00005 * 00006 * This program is free software; you can redistribute it and/or modify 00007 * it under the terms of the GNU Lesser General Public License as 00008 * published by the Free Software Foundation; either version 3 of the 00009 * License, or (at your option) any later version. 00010 * 00011 * This program is distributed in the hope that it will be useful, 00012 * but WITHOUT ANY WARRANTY; without even the implied warranty of 00013 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 00014 * Lesser General Public License for more details. 00015 * 00016 * You should have received a copy of the GNU Lesser General Public License 00017 * along with this program. If not, see <http://www.gnu.org/licenses/>. 00018 */ 00019 00020 #include <libexplain/ac/sys/param.h> 00021 #include <libexplain/ac/sys/stat.h> 00022 #include <libexplain/ac/unistd.h> 00023 00024 #include <libexplain/buffer/dac.h> 00025 #include <libexplain/buffer/file_type.h> 00026 #include <libexplain/buffer/gettext.h> 00027 #include <libexplain/buffer/gid.h> 00028 #include <libexplain/buffer/group_permission_ignored.h> 00029 #include <libexplain/buffer/others_permission_ignored.h> 00030 #include <libexplain/buffer/others_permission.h> 00031 #include <libexplain/buffer/rwx.h> 00032 #include <libexplain/buffer/uid.h> 00033 #include <libexplain/capability.h> 00034 #include <libexplain/gettext.h> 00035 #include <libexplain/group_in_groups.h> 00036 #include <libexplain/have_permission.h> 00037 #include <libexplain/option.h> 00038 #include <libexplain/translate.h> 00039 00040 00041 static int 00042 explain_have_permission(const struct stat *st, 00043 const explain_have_identity_t *hip, int wanted) 00044 { 00045 /* 00046 * The first group of three is used when the effective user ID of 00047 * the process equals the owner ID of the file. 00048 */ 00049 if (st->st_uid == (uid_t)hip->uid) 00050 { 00051 return (0 != (st->st_mode & wanted & S_IRWXU)); 00052 } 00053 00054 /* 00055 * The second group of three is used when the group ID of the file 00056 * either equals the effective group ID of the process, or 00057 * is one of the supplementary group IDs of the process (as 00058 * set by setgroups(2)). 00059 */ 00060 if (explain_group_in_groups(st->st_gid, hip)) 00061 { 00062 return (0 != (st->st_mode & wanted & S_IRWXG)); 00063 } 00064 00065 /* 00066 * When neither holds, the third group is used. 00067 */ 00068 return (0 != (st->st_mode & wanted & S_IRWXO)); 00069 } 00070 00071 00072 static void 00073 owner_permission_mode_used(explain_string_buffer_t *sb, 00074 const struct stat *st, const explain_have_identity_t *hip) 00075 { 00076 char part1[40]; 00077 explain_string_buffer_t part1_sb; 00078 char part2[40]; 00079 explain_string_buffer_t part2_sb; 00080 char part3[8]; 00081 explain_string_buffer_t part3_sb; 00082 char filtyp[100]; 00083 explain_string_buffer_t filtyp_sb; 00084 00085 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00086 explain_buffer_uid(&part1_sb, hip->uid); 00087 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00088 explain_buffer_uid(&part2_sb, st->st_uid); 00089 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00090 explain_buffer_rwx(&part3_sb, st->st_mode & S_IRWXU); 00091 explain_string_buffer_init(&filtyp_sb, filtyp, sizeof(filtyp)); 00092 explain_buffer_file_type_st(&filtyp_sb, st); 00093 00094 explain_string_buffer_puts(sb, ", "); 00095 explain_string_buffer_printf_gettext 00096 ( 00097 sb, 00098 /* 00099 * xgettext: This message is used when explaining which 00100 * permission mode bits are used when determining file access 00101 * permissions. 00102 * 00103 * %1$s => the kind of UID, "real UID" or "effective UID", 00104 * already translated. 00105 * %2$s => the UID of the process, number and name. 00106 * %3$s => the file type, e.g. "directory" or "regular file" 00107 * %4$s => the owner of the file, number and name. 00108 * %5$s => The mode bits like "rwx", including the quotes, in 00109 * a form resembling the ls -l representation of mode 00110 * bits. 00111 */ 00112 i18n("the process %s %s matches the %s owner UID %s and the " 00113 "owner permission mode is %s"), 00114 explain_have_identity_kind_of_uid(hip), 00115 part1, 00116 filtyp, 00117 part2, 00118 part3 00119 ); 00120 } 00121 00122 00123 static void 00124 owner_permission_mode_ignored(explain_string_buffer_t *sb, 00125 const struct stat *st, const explain_have_identity_t *hip) 00126 { 00127 char part1[40]; 00128 explain_string_buffer_t part1_sb; 00129 char part2[40]; 00130 explain_string_buffer_t part2_sb; 00131 char part3[8]; 00132 explain_string_buffer_t part3_sb; 00133 char filtyp[100]; 00134 explain_string_buffer_t filtyp_sb; 00135 00136 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00137 explain_buffer_uid(&part1_sb, hip->uid); 00138 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00139 explain_buffer_uid(&part2_sb, st->st_uid); 00140 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00141 explain_buffer_rwx(&part3_sb, st->st_mode & S_IRWXU); 00142 explain_string_buffer_init(&filtyp_sb, filtyp, sizeof(filtyp)); 00143 explain_buffer_file_type_st(&filtyp_sb, st); 00144 00145 explain_string_buffer_puts(sb, ", "); 00146 explain_string_buffer_printf_gettext 00147 ( 00148 sb, 00149 /* 00150 * xgettext: This message is used when explaining which 00151 * permission mode bits are ignored when determining 00152 * file access permissions. 00153 * 00154 * %1$s => the kind of GID, "real GID" or "effective GID", 00155 * already translated 00156 * %2$s => the GID of the process, number and name. 00157 * %3$s => the file type, e.g. "directory" or "regular file" 00158 * %4$s => the owner of the file, number and name. 00159 * %5$s => The mode bits like "rwx", including the quotes, in 00160 * a form resembling the ls -l representation of mode 00161 * bits. 00162 */ 00163 i18n("the process %s %s does not match the %s owner " 00164 "%s so the owner permission mode %s is ignored"), 00165 explain_have_identity_kind_of_uid(hip), 00166 part1, 00167 filtyp, 00168 part2, 00169 part3 00170 ); 00171 } 00172 00173 00174 static void 00175 group_permission_mode_used(explain_string_buffer_t *sb, 00176 const struct stat *st, const explain_have_identity_t *hip) 00177 { 00178 char part1[40]; 00179 explain_string_buffer_t part1_sb; 00180 char part2[40]; 00181 explain_string_buffer_t part2_sb; 00182 char part3[8]; 00183 explain_string_buffer_t part3_sb; 00184 char filtyp[100]; 00185 explain_string_buffer_t filtyp_sb; 00186 00187 explain_string_buffer_init(&part1_sb, part1, sizeof(part1)); 00188 explain_buffer_gid(&part1_sb, hip->gid); 00189 explain_string_buffer_init(&part2_sb, part2, sizeof(part2)); 00190 explain_buffer_gid(&part2_sb, st->st_gid); 00191 explain_string_buffer_init(&part3_sb, part3, sizeof(part3)); 00192 explain_buffer_rwx(&part3_sb, st->st_mode & S_IRWXG); 00193 explain_string_buffer_init(&filtyp_sb, filtyp, sizeof(filtyp)); 00194 explain_buffer_file_type_st(&filtyp_sb, st); 00195 00196 explain_string_buffer_puts(sb, ", "); 00197 explain_string_buffer_printf_gettext 00198 ( 00199 sb, 00200 /* 00201 * xgettext: This message is used when explaining which 00202 * permission mode bits are used when determining file access 00203 * permissions. 00204 * 00205 * %1$s => the kind of GID, "real GID" or "effective GID", 00206 * already translated 00207 * %2$s => the GID of the process, number and name. 00208 * %3$s => the file type, e.g. 'directory' or 'regular file' 00209 * %4$s => the group of the file, number and name. 00210 * %5$s => The mode bits like "rwx", including the quotes, in 00211 * a form resembling the ls -l representation of mode 00212 * bits. 00213 */ 00214 i18n("the process %s %s matches the %s group GID %s and the " 00215 "group permission mode is %s"), 00216 explain_have_identity_kind_of_gid(hip), 00217 part1, 00218 filtyp, 00219 part2, 00220 part3 00221 ); 00222 } 00223 00224 00225 static int 00226 explain_explain_permission(explain_string_buffer_t *sb, 00227 const struct stat *st, const explain_have_identity_t *hip, int wanted) 00228 { 00229 if (!explain_option_dialect_specific()) 00230 { 00231 /* 00232 * The test suite doesn't need to see the uid and name, or the 00233 * gid and name, because these give false negatives. 00234 */ 00235 return -1; 00236 } 00237 00238 /* 00239 * The first group of three (0700) is used when the effective user 00240 * ID of the process equals the owner ID of the file. 00241 */ 00242 if (st->st_uid == (uid_t)hip->uid) 00243 { 00244 owner_permission_mode_used(sb, st, hip); 00245 00246 if 00247 ( 00248 (st->st_mode & wanted & S_IRWXG) 00249 && 00250 explain_group_in_groups(st->st_gid, hip) 00251 ) 00252 { 00253 explain_buffer_group_permission_ignored(sb, st->st_mode); 00254 } 00255 if (st->st_mode & wanted & S_IRWXO) 00256 { 00257 explain_buffer_others_permission_ignored(sb, st->st_mode); 00258 } 00259 return (0 != (st->st_mode & wanted & S_IRWXU)); 00260 } 00261 00262 /* 00263 * The second group of three (0070) is used when the group ID of the 00264 * file either equals the effective group ID of the process, 00265 * or is one of the supplementary group IDs of the process 00266 * (as set by setgroups(2)). 00267 * 00268 * FIXME: when the file is on a remote NFS mount, only the first 16 00269 * groups are consulted. This can be a problem when a process is in 00270 * more than 16 groups. 00271 */ 00272 if (explain_group_in_groups(st->st_gid, hip)) 00273 { 00274 if (st->st_mode & wanted & S_IRWXU) 00275 { 00276 owner_permission_mode_ignored(sb, st, hip); 00277 } 00278 00279 group_permission_mode_used(sb, st, hip); 00280 00281 if (st->st_mode & wanted & S_IRWXO) 00282 { 00283 explain_buffer_others_permission_ignored(sb, st->st_mode); 00284 } 00285 return (0 != (st->st_mode & wanted & S_IRWXG)); 00286 } 00287 00288 /* 00289 * When neither holds, the third group is used. 00290 */ 00291 if (st->st_mode & wanted & S_IRWXU) 00292 { 00293 owner_permission_mode_ignored(sb, st, hip); 00294 } 00295 if (st->st_mode & wanted & S_IRWXG) 00296 { 00297 explain_buffer_group_permission_ignored(sb, st->st_mode); 00298 } 00299 explain_buffer_others_permission(sb, st->st_mode); 00300 return (0 != (st->st_mode & wanted & S_IRWXO)); 00301 } 00302 00303 00304 int 00305 explain_have_read_permission(const struct stat *st, 00306 const explain_have_identity_t *hip) 00307 { 00308 if (explain_capability_dac_read_search()) 00309 return 1; 00310 return explain_have_permission(st, hip, 0444); 00311 } 00312 00313 00314 int 00315 explain_explain_read_permission(explain_string_buffer_t *sb, 00316 const struct stat *st, const explain_have_identity_t *hip) 00317 { 00318 int result; 00319 00320 if (explain_capability_dac_read_search()) 00321 return 1; 00322 result = explain_explain_permission(sb, st, hip, 0444); 00323 if (!result) 00324 explain_buffer_dac_read_search(sb); 00325 return result; 00326 } 00327 00328 00329 int 00330 explain_have_write_permission(const struct stat *st, 00331 const explain_have_identity_t *hip) 00332 { 00333 if (explain_capability_dac_override()) 00334 return 1; 00335 return explain_have_permission(st, hip, 0222); 00336 } 00337 00338 00339 int 00340 explain_explain_write_permission(explain_string_buffer_t *sb, 00341 const struct stat *st, const explain_have_identity_t *hip) 00342 { 00343 int result; 00344 00345 if (explain_capability_dac_override()) 00346 return 1; 00347 result = explain_explain_permission(sb, st, hip, 0222); 00348 if (!result) 00349 explain_buffer_dac_override(sb); 00350 return result; 00351 } 00352 00353 00354 int 00355 explain_have_execute_permission(const struct stat *st, 00356 const explain_have_identity_t *hip) 00357 { 00358 if (!S_ISREG(st->st_mode)) 00359 return 0; 00360 if 00361 ( 00362 explain_capability_dac_override() 00363 #ifdef __linux__ 00364 && 00365 (st->st_mode & 0111) 00366 #endif 00367 ) 00368 return 1; 00369 return explain_have_permission(st, hip, 0111); 00370 } 00371 00372 00373 int 00374 explain_explain_execute_permission(explain_string_buffer_t *sb, 00375 const struct stat *st, const explain_have_identity_t *hip) 00376 { 00377 int result; 00378 00379 if (!S_ISREG(st->st_mode)) 00380 return 0; 00381 if 00382 ( 00383 explain_capability_dac_override() 00384 #ifdef __linux__ 00385 && 00386 (st->st_mode & 0111) 00387 #endif 00388 ) 00389 return 1; 00390 result = explain_explain_permission(sb, st, hip, 0111); 00391 if (!result) 00392 explain_buffer_dac_override(sb); 00393 return result; 00394 } 00395 00396 00397 int 00398 explain_have_search_permission(const struct stat *st, 00399 const explain_have_identity_t *hip) 00400 { 00401 if (!S_ISDIR(st->st_mode)) 00402 return 0; 00403 if (explain_capability_dac_read_search()) 00404 return 1; 00405 return explain_have_permission(st, hip, 0111); 00406 } 00407 00408 00409 int 00410 explain_explain_search_permission(explain_string_buffer_t *sb, 00411 const struct stat *st, const explain_have_identity_t *hip) 00412 { 00413 int result; 00414 00415 if (!S_ISDIR(st->st_mode)) 00416 return 0; 00417 if (explain_capability_dac_read_search()) 00418 return 1; 00419 result = explain_explain_permission(sb, st, hip, 0111); 00420 if (!result) 00421 explain_buffer_dac_read_search(sb); 00422 return result; 00423 } 00424 00425 00426 int 00427 explain_have_inode_permission(const struct stat *st, 00428 const explain_have_identity_t *hip) 00429 { 00430 if (explain_capability_fowner()) 00431 return 1; 00432 return ((uid_t)hip->uid == st->st_uid); 00433 } 00434 00435 00436 const char * 00437 explain_have_identity_kind_of_uid(const explain_have_identity_t *hip) 00438 { 00439 if ((uid_t)hip->uid != geteuid()) 00440 { 00441 return explain_translate_real_uid(); 00442 } 00443 else 00444 { 00445 return explain_translate_effective_uid(); 00446 } 00447 } 00448 00449 00450 const char * 00451 explain_have_identity_kind_of_gid(const explain_have_identity_t *hip) 00452 { 00453 if ((gid_t)hip->gid != getegid()) 00454 { 00455 return explain_translate_real_gid(); 00456 } 00457 else 00458 { 00459 return explain_translate_effective_gid(); 00460 } 00461 } 00462 00463 00464 void 00465 explain_have_identity_init(explain_have_identity_t *hip) 00466 { 00467 hip->uid = geteuid(); 00468 hip->gid = getegid(); 00469 } 00470 00471 00472 /* vim: set ts=8 sw=4 et : */