lib/util_sec.c

説明を見る。
00001 /*
00002    Unix SMB/CIFS implementation.
00003    Copyright (C) Jeremy Allison 1998.
00004    rewritten for version 2.0.6 by Tridge
00005 
00006    This program is free software; you can redistribute it and/or modify
00007    it under the terms of the GNU General Public License as published by
00008    the Free Software Foundation; either version 2 of the License, or
00009    (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
00014    GNU General Public License for more details.
00015 
00016    You should have received a copy of the GNU General Public License
00017    along with this program; if not, write to the Free Software
00018    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
00019 */
00020 
00021 #ifndef AUTOCONF_TEST
00022 #include "includes.h"
00023 #else
00024 /* we are running this code in autoconf test mode to see which type of setuid
00025    function works */
00026 #if defined(HAVE_UNISTD_H)
00027 #include <unistd.h>
00028 #endif
00029 #include <stdlib.h>
00030 #include <stdio.h>
00031 #include <sys/types.h>
00032 #include <errno.h>
00033 
00034 #ifdef HAVE_SYS_PRIV_H
00035 #include <sys/priv.h>
00036 #endif
00037 #ifdef HAVE_SYS_ID_H
00038 #include <sys/id.h>
00039 #endif
00040 
00041 #define DEBUG(x, y) printf y
00042 #define smb_panic(x) exit(1)
00043 #define BOOL int
00044 #endif
00045 
00046 /* are we running as non-root? This is used by the regresison test code,
00047    and potentially also for sites that want non-root smbd */
00048 static uid_t initial_uid;
00049 static gid_t initial_gid;
00050 
00051 /****************************************************************************
00052 remember what uid we got started as - this allows us to run correctly
00053 as non-root while catching trapdoor systems
00054 ****************************************************************************/
00055 
00056 void sec_init(void)
00057 {
00058         static int initialized;
00059 
00060         if (!initialized) {
00061                 initial_uid = geteuid();
00062                 initial_gid = getegid();
00063                 initialized = 1;
00064         }
00065 }
00066 
00067 /****************************************************************************
00068 some code (eg. winbindd) needs to know what uid we started as
00069 ****************************************************************************/
00070 uid_t sec_initial_uid(void)
00071 {
00072         return initial_uid;
00073 }
00074 
00075 /****************************************************************************
00076 some code (eg. winbindd, profiling shm) needs to know what gid we started as
00077 ****************************************************************************/
00078 gid_t sec_initial_gid(void)
00079 {
00080         return initial_gid;
00081 }
00082 
00083 /****************************************************************************
00084 are we running in non-root mode?
00085 ****************************************************************************/
00086 BOOL non_root_mode(void)
00087 {
00088         return (initial_uid != (uid_t)0);
00089 }
00090 
00091 /****************************************************************************
00092 abort if we haven't set the uid correctly
00093 ****************************************************************************/
00094 static void assert_uid(uid_t ruid, uid_t euid)
00095 {
00096         if ((euid != (uid_t)-1 && geteuid() != euid) ||
00097             (ruid != (uid_t)-1 && getuid() != ruid)) {
00098                 if (!non_root_mode()) {
00099                         DEBUG(0,("Failed to set uid privileges to (%d,%d) now set to (%d,%d)\n",
00100                                  (int)ruid, (int)euid,
00101                                  (int)getuid(), (int)geteuid()));
00102                         smb_panic("failed to set uid\n");
00103                         exit(1);
00104                 }
00105         }
00106 }
00107 
00108 /****************************************************************************
00109 abort if we haven't set the gid correctly
00110 ****************************************************************************/
00111 static void assert_gid(gid_t rgid, gid_t egid)
00112 {
00113         if ((egid != (gid_t)-1 && getegid() != egid) ||
00114             (rgid != (gid_t)-1 && getgid() != rgid)) {
00115                 if (!non_root_mode()) {
00116                         DEBUG(0,("Failed to set gid privileges to (%d,%d) now set to (%d,%d) uid=(%d,%d)\n",
00117                                  (int)rgid, (int)egid,
00118                                  (int)getgid(), (int)getegid(),
00119                                  (int)getuid(), (int)geteuid()));
00120                         smb_panic("failed to set gid\n");
00121                         exit(1);
00122                 }
00123         }
00124 }
00125 
00126 /****************************************************************************
00127  Gain root privilege before doing something. 
00128  We want to end up with ruid==euid==0
00129 ****************************************************************************/
00130 void gain_root_privilege(void)
00131 {       
00132 #if USE_SETRESUID
00133         setresuid(0,0,0);
00134 #endif
00135     
00136 #if USE_SETEUID
00137         seteuid(0);
00138 #endif
00139 
00140 #if USE_SETREUID
00141         setreuid(0, 0);
00142 #endif
00143 
00144 #if USE_SETUIDX
00145         setuidx(ID_EFFECTIVE, 0);
00146         setuidx(ID_REAL, 0);
00147 #endif
00148 
00149         /* this is needed on some systems */
00150         setuid(0);
00151 
00152         assert_uid(0, 0);
00153 }
00154 
00155 
00156 /****************************************************************************
00157  Ensure our real and effective groups are zero.
00158  we want to end up with rgid==egid==0
00159 ****************************************************************************/
00160 void gain_root_group_privilege(void)
00161 {
00162 #if USE_SETRESUID
00163         setresgid(0,0,0);
00164 #endif
00165 
00166 #if USE_SETREUID
00167         setregid(0,0);
00168 #endif
00169 
00170 #if USE_SETEUID
00171         setegid(0);
00172 #endif
00173 
00174 #if USE_SETUIDX
00175         setgidx(ID_EFFECTIVE, 0);
00176         setgidx(ID_REAL, 0);
00177 #endif
00178 
00179         setgid(0);
00180 
00181         assert_gid(0, 0);
00182 }
00183 
00184 
00185 /****************************************************************************
00186  Set effective uid, and possibly the real uid too.
00187  We want to end up with either:
00188   
00189    ruid==uid and euid==uid
00190 
00191  or
00192 
00193    ruid==0 and euid==uid
00194 
00195  depending on what the local OS will allow us to regain root from.
00196 ****************************************************************************/
00197 void set_effective_uid(uid_t uid)
00198 {
00199 #if USE_SETRESUID
00200         /* Set the effective as well as the real uid. */
00201         if (setresuid(uid,uid,-1) == -1) {
00202                 if (errno == EAGAIN) {
00203                         DEBUG(0, ("setresuid failed with EAGAIN. uid(%d) "
00204                                   "might be over its NPROC limit\n",
00205                                   (int)uid));
00206                 }
00207         }
00208 #endif
00209 
00210 #if USE_SETREUID
00211         setreuid(-1,uid);
00212 #endif
00213 
00214 #if USE_SETEUID
00215         seteuid(uid);
00216 #endif
00217 
00218 #if USE_SETUIDX
00219         setuidx(ID_EFFECTIVE, uid);
00220 #endif
00221 
00222         assert_uid(-1, uid);
00223 }
00224 
00225 /****************************************************************************
00226  Set *only* the effective gid.
00227  we want to end up with rgid==0 and egid==gid
00228 ****************************************************************************/
00229 void set_effective_gid(gid_t gid)
00230 {
00231 #if USE_SETRESUID
00232         setresgid(-1,gid,-1);
00233 #endif
00234 
00235 #if USE_SETREUID
00236         setregid(-1,gid);
00237 #endif
00238 
00239 #if USE_SETEUID
00240         setegid(gid);
00241 #endif
00242 
00243 #if USE_SETUIDX
00244         setgidx(ID_EFFECTIVE, gid);
00245 #endif
00246 
00247         assert_gid(-1, gid);
00248 }
00249 
00250 static uid_t saved_euid, saved_ruid;
00251 static gid_t saved_egid, saved_rgid;
00252 
00253 /****************************************************************************
00254  save the real and effective uid for later restoration. Used by the quotas
00255  code
00256 ****************************************************************************/
00257 void save_re_uid(void)
00258 {
00259         saved_ruid = getuid();
00260         saved_euid = geteuid();
00261 }
00262 
00263 
00264 /****************************************************************************
00265  and restore them!
00266 ****************************************************************************/
00267 
00268 void restore_re_uid_fromroot(void)
00269 {
00270 #if USE_SETRESUID
00271         setresuid(saved_ruid, saved_euid, -1);
00272 #elif USE_SETREUID
00273         setreuid(saved_ruid, -1);
00274         setreuid(-1,saved_euid);
00275 #elif USE_SETUIDX
00276         setuidx(ID_REAL, saved_ruid);
00277         setuidx(ID_EFFECTIVE, saved_euid);
00278 #else
00279         set_effective_uid(saved_euid);
00280         if (getuid() != saved_ruid)
00281                 setuid(saved_ruid);
00282         set_effective_uid(saved_euid);
00283 #endif
00284 
00285         assert_uid(saved_ruid, saved_euid);
00286 }
00287 
00288 void restore_re_uid(void)
00289 {
00290         set_effective_uid(0);
00291         restore_re_uid_fromroot();
00292 }
00293 
00294 /****************************************************************************
00295  save the real and effective gid for later restoration. Used by the 
00296  getgroups code
00297 ****************************************************************************/
00298 void save_re_gid(void)
00299 {
00300         saved_rgid = getgid();
00301         saved_egid = getegid();
00302 }
00303 
00304 /****************************************************************************
00305  and restore them!
00306 ****************************************************************************/
00307 void restore_re_gid(void)
00308 {
00309 #if USE_SETRESUID
00310         setresgid(saved_rgid, saved_egid, -1);
00311 #elif USE_SETREUID
00312         setregid(saved_rgid, -1);
00313         setregid(-1,saved_egid);
00314 #elif USE_SETUIDX
00315         setgidx(ID_REAL, saved_rgid);
00316         setgidx(ID_EFFECTIVE, saved_egid);
00317 #else
00318         set_effective_gid(saved_egid);
00319         if (getgid() != saved_rgid)
00320                 setgid(saved_rgid);
00321         set_effective_gid(saved_egid);
00322 #endif
00323 
00324         assert_gid(saved_rgid, saved_egid);
00325 }
00326 
00327 
00328 /****************************************************************************
00329  set the real AND effective uid to the current effective uid in a way that
00330  allows root to be regained.
00331  This is only possible on some platforms.
00332 ****************************************************************************/
00333 int set_re_uid(void)
00334 {
00335         uid_t uid = geteuid();
00336 
00337 #if USE_SETRESUID
00338         setresuid(geteuid(), -1, -1);
00339 #endif
00340 
00341 #if USE_SETREUID
00342         setreuid(0, 0);
00343         setreuid(uid, -1);
00344         setreuid(-1, uid);
00345 #endif
00346 
00347 #if USE_SETEUID
00348         /* can't be done */
00349         return -1;
00350 #endif
00351 
00352 #if USE_SETUIDX
00353         /* can't be done */
00354         return -1;
00355 #endif
00356 
00357         assert_uid(uid, uid);
00358         return 0;
00359 }
00360 
00361 
00362 /****************************************************************************
00363  Become the specified uid and gid - permanently !
00364  there should be no way back if possible
00365 ****************************************************************************/
00366 void become_user_permanently(uid_t uid, gid_t gid)
00367 {
00368         /*
00369          * First - gain root privilege. We do this to ensure
00370          * we can lose it again.
00371          */
00372 
00373         gain_root_privilege();
00374         gain_root_group_privilege();
00375 
00376 #if USE_SETRESUID
00377         setresgid(gid,gid,gid);
00378         setgid(gid);
00379         setresuid(uid,uid,uid);
00380         setuid(uid);
00381 #endif
00382 
00383 #if USE_SETREUID
00384         setregid(gid,gid);
00385         setgid(gid);
00386         setreuid(uid,uid);
00387         setuid(uid);
00388 #endif
00389 
00390 #if USE_SETEUID
00391         setegid(gid);
00392         setgid(gid);
00393         setuid(uid);
00394         seteuid(uid);
00395         setuid(uid);
00396 #endif
00397 
00398 #if USE_SETUIDX
00399         setgidx(ID_REAL, gid);
00400         setgidx(ID_EFFECTIVE, gid);
00401         setgid(gid);
00402         setuidx(ID_REAL, uid);
00403         setuidx(ID_EFFECTIVE, uid);
00404         setuid(uid);
00405 #endif
00406         
00407         assert_uid(uid, uid);
00408         assert_gid(gid, gid);
00409 }
00410 
00411 #ifdef AUTOCONF_TEST
00412 
00413 /****************************************************************************
00414 this function just checks that we don't get ENOSYS back
00415 ****************************************************************************/
00416 static int have_syscall(void)
00417 {
00418         errno = 0;
00419 
00420 #if USE_SETRESUID
00421         setresuid(-1,-1,-1);
00422 #endif
00423 
00424 #if USE_SETREUID
00425         setreuid(-1,-1);
00426 #endif
00427 
00428 #if USE_SETEUID
00429         seteuid(-1);
00430 #endif
00431 
00432 #if USE_SETUIDX
00433         setuidx(ID_EFFECTIVE, -1);
00434 #endif
00435 
00436         if (errno == ENOSYS) return -1;
00437         
00438         return 0;
00439 }
00440 
00441 main()
00442 {
00443         if (getuid() != 0) {
00444 #if (defined(AIX) && defined(USE_SETREUID))
00445                 /* setreuid is badly broken on AIX 4.1, we avoid it completely */
00446                 fprintf(stderr,"avoiding possibly broken setreuid\n");
00447                 exit(1);
00448 #endif
00449 
00450                 /* if not running as root then at least check to see if we get ENOSYS - this 
00451                    handles Linux 2.0.x with glibc 2.1 */
00452                 fprintf(stderr,"not running as root: checking for ENOSYS\n");
00453                 exit(have_syscall());
00454         }
00455 
00456         gain_root_privilege();
00457         gain_root_group_privilege();
00458         set_effective_gid(1);
00459         set_effective_uid(1);
00460         save_re_uid();
00461         restore_re_uid();
00462         gain_root_privilege();
00463         gain_root_group_privilege();
00464         become_user_permanently(1, 1);
00465         setuid(0);
00466         if (getuid() == 0) {
00467                 fprintf(stderr,"uid not set permanently\n");
00468                 exit(1);
00469         }
00470 
00471         printf("OK\n");
00472 
00473         exit(0);
00474 }
00475 #endif
00476 
00477 /****************************************************************************
00478 Check if we are setuid root.  Used in libsmb and smbpasswd paranoia checks.
00479 ****************************************************************************/
00480 BOOL is_setuid_root(void) 
00481 {
00482         return (geteuid() == (uid_t)0) && (getuid() != (uid_t)0);
00483 }

Sambaに対してSat Aug 29 21:23:00 2009に生成されました。  doxygen 1.4.7