libexplain  1.4.D001
libexplain/buffer/does_not_have_inode_modify_permission.c
Go to the documentation of this file.
00001 /*
00002  * libexplain - Explain errno values returned by libc functions
00003  * Copyright (C) 2008-2011, 2013 Peter Miller
00004  *
00005  * This program is free software; you can redistribute it and/or modify
00006  * it under the terms of the GNU Lesser General Public License as
00007  * published by the Free Software Foundation; either version 3 of the
00008  * License, or (at your option) any later version.
00009  *
00010  * This program is distributed in the hope that it will be useful,
00011  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00012  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00013  * Lesser General Public License for more details.
00014  *
00015  * You should have received a copy of the GNU Lesser General Public License
00016  * along with this program. If not, see <http://www.gnu.org/licenses/>.
00017  */
00018 
00019 #include <libexplain/ac/limits.h> /* for PATH_MAX on Solaris */
00020 #include <libexplain/ac/string.h>
00021 #include <libexplain/ac/sys/param.h> /* for PATH_MAX except Solaris */
00022 #include <libexplain/ac/sys/stat.h>
00023 
00024 #include <libexplain/buffer/caption_name_type.h>
00025 #include <libexplain/buffer/dac.h>
00026 #include <libexplain/buffer/does_not_have_inode_modify_permission.h>
00027 #include <libexplain/buffer/errno/path_resolution.h>
00028 #include <libexplain/buffer/file_type.h>
00029 #include <libexplain/buffer/gettext.h>
00030 #include <libexplain/buffer/uid.h>
00031 #include <libexplain/dirname.h>
00032 #include <libexplain/name_max.h>
00033 
00034 
00035 void
00036 explain_buffer_does_not_have_inode_modify_permission1(
00037     explain_string_buffer_t *sb, const char *pathname,
00038     const struct stat *pathname_st, const char *caption,
00039     const explain_have_identity_t *hip)
00040 {
00041     struct stat     dirname_st;
00042     char            filename[NAME_MAX + 1];
00043     char            dirname[PATH_MAX + 1];
00044 
00045     explain_dirname(dirname, pathname, sizeof(dirname));
00046     if (stat(dirname, &dirname_st) < 0)
00047     {
00048         memset(&dirname_st, 0, sizeof(dirname_st));
00049         dirname_st.st_mode = S_IFDIR;
00050     }
00051     explain_basename(filename, pathname, sizeof(filename));
00052 
00053     explain_buffer_does_not_have_inode_modify_permission
00054     (
00055         sb,
00056         filename,
00057         pathname_st,
00058         caption,
00059         dirname,
00060         &dirname_st,
00061         hip
00062     );
00063 }
00064 
00065 
00066 static void
00067 process_does_not_match_the_owner_uid(explain_string_buffer_t *sb,
00068     const char *kind_of_uid, const char *puid, const char *caption,
00069     int st_uid)
00070 {
00071     char            fuid[40];
00072     explain_string_buffer_t fuid_sb;
00073 
00074     explain_string_buffer_init(&fuid_sb, fuid, sizeof(fuid));
00075     explain_buffer_uid(&fuid_sb, st_uid);
00076 
00077     explain_string_buffer_printf_gettext
00078     (
00079         sb,
00080         /*
00081          * xgettext: This message supplements the "no inode modify
00082          * permission" message, explaining that the process effective UID
00083          * must match the file owner UID.
00084          *
00085          * %1$s => the kind of UID, either "real UID" or "effective UID",
00086          *         already translated
00087          * %2$s => the numeric UID of the process, and the corresponding
00088          *         login name from the password file, if available.
00089          * %3$s => the name of the offending system call argument,
00090          *         possibly with some additional file type info
00091          * %4$s => the numeric UID of the file owner, and the
00092          *         corresponding login name from the password file, if
00093          *         available.
00094          */
00095         i18n("the process %s %s does not match the %s owner UID %s"),
00096         kind_of_uid,
00097         puid,
00098         caption,
00099         fuid
00100     );
00101     explain_buffer_dac_fowner(sb);
00102 }
00103 
00104 
00105 void
00106 explain_buffer_does_not_have_inode_modify_permission_fd(
00107     explain_string_buffer_t *sb, int fildes, const char *fildes_caption)
00108 {
00109     struct stat     st;
00110     struct stat     *st_p;
00111     explain_have_identity_t id;
00112 
00113     explain_have_identity_init(&id);
00114     st_p = &st;
00115     if (fstat(fildes, st_p) < 0)
00116         st_p = 0;
00117     explain_buffer_does_not_have_inode_modify_permission_fd_st
00118     (
00119         sb,
00120         st_p,
00121         fildes_caption,
00122         &id
00123     );
00124 }
00125 
00126 
00127 void
00128 explain_buffer_does_not_have_inode_modify_permission_fd_st(
00129     explain_string_buffer_t *sb, const struct stat *fildes_st,
00130     const char *fildes_caption, const explain_have_identity_t *hip)
00131 {
00132     explain_string_buffer_t puid_sb;
00133     explain_string_buffer_t caption_sb;
00134     const char      *kind_of_uid;
00135     char            puid[40];
00136     char            caption[100];
00137 
00138     explain_buffer_gettext
00139     (
00140         sb,
00141         /*
00142          * xgettext: This message is used when a process does not have
00143          * inode modification permission to something it attempts to
00144          * modify); for example, fchmod.
00145          */
00146         i18n("the process does not have inode modification permission")
00147     );
00148     if (!fildes_st)
00149     {
00150         explain_buffer_dac_fowner(sb);
00151         return;
00152     }
00153 
00154     kind_of_uid = explain_have_identity_kind_of_uid(hip);
00155 
00156     /*
00157      * Give more information: tell them who they are (this can be a
00158      * surprise to users of set-UID programs) and who owns the file.
00159      */
00160     explain_string_buffer_init(&puid_sb, puid, sizeof(puid));
00161     explain_buffer_uid(&puid_sb, hip->uid);
00162 
00163     explain_string_buffer_init(&caption_sb, caption, sizeof(caption));
00164     explain_buffer_caption_name_type_st
00165     (
00166         &caption_sb,
00167         fildes_caption,
00168         0,
00169         fildes_st
00170     );
00171 
00172     explain_string_buffer_puts(sb, ", ");
00173     process_does_not_match_the_owner_uid
00174     (
00175         sb,
00176         kind_of_uid,
00177         puid,
00178         caption,
00179         fildes_st->st_uid
00180     );
00181 }
00182 
00183 
00184 void
00185 explain_buffer_does_not_have_inode_modify_permission(
00186     explain_string_buffer_t *sb, const char *comp,
00187     const struct stat *comp_st, const char *caption, const char *dir,
00188     const struct stat *dir_st, const explain_have_identity_t *hip)
00189 {
00190     char            final_part[NAME_MAX * 4 + 100];
00191     explain_string_buffer_t final_part_sb;
00192     char            dir_part[PATH_MAX * 4 + 100];
00193     explain_string_buffer_t dir_part_sb;
00194     const char      *kind_of_uid;
00195     char            puid[40];
00196     explain_string_buffer_t puid_sb;
00197 
00198     explain_string_buffer_init
00199     (
00200         &final_part_sb,
00201         final_part,
00202         sizeof(final_part)
00203     );
00204     explain_buffer_caption_name_type_st
00205     (
00206         &final_part_sb,
00207         0,
00208         comp,
00209         comp_st
00210     );
00211     explain_string_buffer_init(&dir_part_sb, dir_part, sizeof(dir_part));
00212     explain_buffer_caption_name_type_st
00213     (
00214         &dir_part_sb,
00215         caption,
00216         dir,
00217         dir_st
00218     );
00219 
00220     explain_string_buffer_printf_gettext
00221     (
00222         sb,
00223         /*
00224          * xgettext: This message is used when a process does not have
00225          * inode modification permission to something it attempts to
00226          * modify); for example, chmod.
00227          * Different language grammars may need to rearrange the parts.
00228          *
00229          * %1$s => the name of the final component of the path, the
00230          *         regular file in question (will never have slashes).
00231          *         It will in clude the name of the file, and the file
00232          *         type "regular file".
00233          * %2$s => the name of the directory that contains the regular
00234          *         file to be executed; it may have zero, one or more
00235          *         slashes in it.  Will include the name of the function
00236          *         call argument, the name of the directory, and the
00237          *         file type "directory".
00238          */
00239         i18n("the process does not have inode modification permission "
00240             "to the %s in the %s"),
00241         final_part,
00242         dir_part
00243     );
00244 
00245     kind_of_uid = explain_have_identity_kind_of_uid(hip);
00246 
00247     /*
00248      * Give more information: tell them who they are (this can be a
00249      * surprise to users of set-UID programs) and who owns the file.
00250      */
00251     explain_string_buffer_init(&puid_sb, puid, sizeof(puid));
00252     explain_buffer_uid(&puid_sb, hip->uid);
00253 
00254     explain_string_buffer_init
00255     (
00256         &final_part_sb,
00257         final_part,
00258         sizeof(final_part)
00259     );
00260     explain_buffer_file_type_st(&final_part_sb, comp_st);
00261 
00262     explain_string_buffer_puts(sb, ", ");
00263     process_does_not_match_the_owner_uid
00264     (
00265         sb,
00266         kind_of_uid,
00267         puid,
00268         final_part,
00269         comp_st->st_uid
00270     );
00271 }
00272 
00273 
00274 /* vim: set ts=8 sw=4 et : */