00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #ifndef AUTOCONF_TEST
00022 #include "includes.h"
00023 #else
00024
00025
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
00047
00048 static uid_t initial_uid;
00049 static gid_t initial_gid;
00050
00051
00052
00053
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
00069
00070 uid_t sec_initial_uid(void)
00071 {
00072 return initial_uid;
00073 }
00074
00075
00076
00077
00078 gid_t sec_initial_gid(void)
00079 {
00080 return initial_gid;
00081 }
00082
00083
00084
00085
00086 BOOL non_root_mode(void)
00087 {
00088 return (initial_uid != (uid_t)0);
00089 }
00090
00091
00092
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
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
00128
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
00150 setuid(0);
00151
00152 assert_uid(0, 0);
00153 }
00154
00155
00156
00157
00158
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
00187
00188
00189
00190
00191
00192
00193
00194
00195
00196
00197 void set_effective_uid(uid_t uid)
00198 {
00199 #if USE_SETRESUID
00200
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
00227
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
00255
00256
00257 void save_re_uid(void)
00258 {
00259 saved_ruid = getuid();
00260 saved_euid = geteuid();
00261 }
00262
00263
00264
00265
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
00296
00297
00298 void save_re_gid(void)
00299 {
00300 saved_rgid = getgid();
00301 saved_egid = getegid();
00302 }
00303
00304
00305
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
00330
00331
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
00349 return -1;
00350 #endif
00351
00352 #if USE_SETUIDX
00353
00354 return -1;
00355 #endif
00356
00357 assert_uid(uid, uid);
00358 return 0;
00359 }
00360
00361
00362
00363
00364
00365
00366 void become_user_permanently(uid_t uid, gid_t gid)
00367 {
00368
00369
00370
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
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
00446 fprintf(stderr,"avoiding possibly broken setreuid\n");
00447 exit(1);
00448 #endif
00449
00450
00451
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
00479
00480 BOOL is_setuid_root(void)
00481 {
00482 return (geteuid() == (uid_t)0) && (getuid() != (uid_t)0);
00483 }