libexplain
1.4.D001
|
00001 /* 00002 * libexplain - Explain errno values returned by libc functions 00003 * Copyright (C) 2012, 2013 Peter Miller 00004 * 00005 * This program is free software; you can redistribute it and/or modify it 00006 * under the terms of the GNU Lesser General Public License as published by 00007 * the Free Software Foundation; either version 3 of the License, or (at 00008 * your option) any later version. 00009 * 00010 * This program is distributed in the hope that it will be useful, but 00011 * WITHOUT ANY WARRANTY; without even the implied warranty of 00012 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser 00013 * 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/errno.h> 00020 00021 #include <libexplain/buffer/dac.h> 00022 #include <libexplain/buffer/eagain.h> 00023 #include <libexplain/buffer/eperm.h> 00024 #include <libexplain/buffer/errno/generic.h> 00025 #include <libexplain/buffer/errno/setresuid.h> 00026 #include <libexplain/buffer/uid.h> 00027 #include <libexplain/explanation.h> 00028 00029 00030 static void 00031 explain_buffer_errno_setresuid_system_call(explain_string_buffer_t *sb, 00032 int errnum, uid_t ruid, uid_t euid, uid_t suid) 00033 { 00034 (void)errnum; 00035 explain_string_buffer_puts(sb, "setresuid(ruid = "); 00036 explain_buffer_uid(sb, ruid); 00037 explain_string_buffer_puts(sb, ", euid = "); 00038 explain_buffer_uid(sb, euid); 00039 explain_string_buffer_puts(sb, ", suid = "); 00040 explain_buffer_uid(sb, suid); 00041 explain_string_buffer_putc(sb, ')'); 00042 } 00043 00044 00045 static void 00046 explain_buffer_eperm_setresuid(explain_string_buffer_t *sb, const char *caption, 00047 const char *ruid_str, const char *euid_str, const char *suid_str) 00048 { 00049 explain_string_buffer_printf_gettext 00050 ( 00051 sb, 00052 i18n 00053 ( 00054 /* 00055 * xgettext: This error message is used to explain an EPERM error 00056 * reported by the setresuid system call, in the case where uid does 00057 * not match the real user ID or effective user ID or saved user ID 00058 * of the calling process, and the user is not privileged (Linux: 00059 * does not have the CAP_SETUID capability) 00060 */ 00061 "the %1$s argument does not match the real user ID (%2$s) or the " 00062 "effective user ID (%3$s) or the saved user ID (%4$s) of the " 00063 "calling process" 00064 ), 00065 caption, 00066 ruid_str, 00067 euid_str, 00068 suid_str 00069 ); 00070 explain_buffer_dac_setuid(sb); 00071 } 00072 00073 00074 void 00075 explain_buffer_errno_setresuid_explanation(explain_string_buffer_t *sb, 00076 int errnum, const char *syscall_name, uid_t ruid, uid_t euid, uid_t suid) 00077 { 00078 uid_t cruid = -1; 00079 char ruid_str[100]; 00080 uid_t ceuid = -1; 00081 char euid_str[100]; 00082 uid_t csuid = -1; 00083 char suid_str[100]; 00084 const uid_t minus1 = -1; 00085 00086 /* 00087 * http://www.opengroup.org/onlinepubs/009695399/functions/setresuid.html 00088 */ 00089 switch (errnum) 00090 { 00091 case EAGAIN: 00092 #if defined(EWOULDBLOCK) && EAGAIN != EWOULDBLOCK 00093 case EWOULDBLOCK: 00094 #endif 00095 if (ruid != getuid()) 00096 { 00097 explain_buffer_eagain_setuid(sb, "ruid"); 00098 break; 00099 } 00100 explain_buffer_eagain(sb, syscall_name); 00101 break; 00102 00103 case EPERM: 00104 getresuid(&cruid, &ceuid, &csuid); 00105 00106 /* build the strings we will need to report the error */ 00107 { 00108 explain_string_buffer_t ruid_sb; 00109 explain_string_buffer_t euid_sb; 00110 explain_string_buffer_t suid_sb; 00111 00112 explain_string_buffer_init(&ruid_sb, ruid_str, sizeof(ruid_str)); 00113 explain_buffer_uid(&ruid_sb, cruid); 00114 explain_string_buffer_init(&euid_sb, euid_str, sizeof(euid_str)); 00115 explain_buffer_uid(&euid_sb, ceuid); 00116 explain_string_buffer_init(&suid_sb, suid_str, sizeof(suid_str)); 00117 explain_buffer_uid(&suid_sb, csuid); 00118 } 00119 00120 if (ruid != minus1 && ruid != cruid && ruid != ceuid && ruid != csuid) 00121 { 00122 explain_buffer_eperm_setresuid(sb, "ruid", ruid_str, euid_str, 00123 suid_str); 00124 break; 00125 } 00126 if (euid != minus1 && euid != cruid && euid != ceuid && euid != csuid) 00127 { 00128 explain_buffer_eperm_setresuid(sb, "euid", ruid_str, euid_str, 00129 suid_str); 00130 break; 00131 } 00132 if (suid != minus1 && suid != cruid && suid != ceuid && suid != csuid) 00133 { 00134 explain_buffer_eperm_setresuid(sb, "suid", ruid_str, euid_str, 00135 suid_str); 00136 break; 00137 } 00138 /* Fall through... */ 00139 00140 default: 00141 explain_buffer_errno_generic(sb, errnum, syscall_name); 00142 break; 00143 } 00144 } 00145 00146 00147 void 00148 explain_buffer_errno_setresuid(explain_string_buffer_t *sb, int errnum, 00149 uid_t ruid, uid_t euid, uid_t suid) 00150 { 00151 explain_explanation_t exp; 00152 00153 explain_explanation_init(&exp, errnum); 00154 explain_buffer_errno_setresuid_system_call(&exp.system_call_sb, errnum, 00155 ruid, euid, suid); 00156 explain_buffer_errno_setresuid_explanation(&exp.explanation_sb, errnum, 00157 "setresuid", ruid, euid, suid); 00158 explain_explanation_assemble(&exp, sb); 00159 } 00160 00161 00162 /* vim: set ts=8 sw=4 et : */