00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021 #include "includes.h"
00022
00023 extern struct current_user current_user;
00024
00025 struct sec_ctx {
00026 UNIX_USER_TOKEN ut;
00027 NT_USER_TOKEN *token;
00028 };
00029
00030
00031
00032
00033 static struct sec_ctx sec_ctx_stack[MAX_SEC_CTX_DEPTH + 1];
00034 static int sec_ctx_stack_ndx;
00035
00036
00037
00038
00039
00040 static BOOL become_uid(uid_t uid)
00041 {
00042
00043
00044 if (uid == (uid_t)-1 ||
00045 ((sizeof(uid_t) == 2) && (uid == (uid_t)65535))) {
00046 static int done;
00047
00048 if (!done) {
00049 DEBUG(1,("WARNING: using uid %d is a security risk\n",
00050 (int)uid));
00051 done = 1;
00052 }
00053 }
00054
00055
00056
00057 set_effective_uid(uid);
00058
00059 DO_PROFILE_INC(uid_changes);
00060 return True;
00061 }
00062
00063
00064
00065
00066
00067 static BOOL become_gid(gid_t gid)
00068 {
00069
00070
00071 if (gid == (gid_t)-1 || ((sizeof(gid_t) == 2) &&
00072 (gid == (gid_t)65535))) {
00073 static int done;
00074
00075 if (!done) {
00076 DEBUG(1,("WARNING: using gid %d is a security risk\n",
00077 (int)gid));
00078 done = 1;
00079 }
00080 }
00081
00082
00083
00084 set_effective_gid(gid);
00085 return True;
00086 }
00087
00088
00089
00090
00091
00092 static BOOL become_id(uid_t uid, gid_t gid)
00093 {
00094 return become_gid(gid) && become_uid(uid);
00095 }
00096
00097
00098
00099
00100
00101 static void gain_root(void)
00102 {
00103 if (non_root_mode()) {
00104 return;
00105 }
00106
00107 if (geteuid() != 0) {
00108 set_effective_uid(0);
00109
00110 if (geteuid() != 0) {
00111 DEBUG(0,
00112 ("Warning: You appear to have a trapdoor "
00113 "uid system\n"));
00114 }
00115 }
00116
00117 if (getegid() != 0) {
00118 set_effective_gid(0);
00119
00120 if (getegid() != 0) {
00121 DEBUG(0,
00122 ("Warning: You appear to have a trapdoor "
00123 "gid system\n"));
00124 }
00125 }
00126 }
00127
00128
00129
00130
00131
00132 static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
00133 {
00134 int i;
00135 gid_t grp;
00136 int ngroups;
00137 gid_t *groups = NULL;
00138
00139 (*p_ngroups) = 0;
00140 (*p_groups) = NULL;
00141
00142
00143
00144
00145 save_re_gid();
00146 set_effective_gid(gid);
00147 setgid(gid);
00148
00149 ngroups = sys_getgroups(0,&grp);
00150 if (ngroups <= 0) {
00151 goto fail;
00152 }
00153
00154 if((groups = SMB_MALLOC_ARRAY(gid_t, ngroups+1)) == NULL) {
00155 DEBUG(0,("setup_groups malloc fail !\n"));
00156 goto fail;
00157 }
00158
00159 if ((ngroups = sys_getgroups(ngroups,groups)) == -1) {
00160 goto fail;
00161 }
00162
00163 restore_re_gid();
00164
00165 (*p_ngroups) = ngroups;
00166 (*p_groups) = groups;
00167
00168 DEBUG( 3, ( "get_current_groups: user is in %u groups: ", ngroups));
00169 for (i = 0; i < ngroups; i++ ) {
00170 DEBUG( 3, ( "%s%d", (i ? ", " : ""), (int)groups[i] ) );
00171 }
00172 DEBUG( 3, ( "\n" ) );
00173
00174 return ngroups;
00175
00176 fail:
00177 SAFE_FREE(groups);
00178 restore_re_gid();
00179 return -1;
00180 }
00181
00182
00183
00184
00185
00186
00187 BOOL push_sec_ctx(void)
00188 {
00189 struct sec_ctx *ctx_p;
00190
00191
00192
00193 if (sec_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
00194 DEBUG(0, ("Security context stack overflow!\n"));
00195 smb_panic("Security context stack overflow!\n");
00196 }
00197
00198
00199
00200 sec_ctx_stack_ndx++;
00201
00202 ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
00203
00204 ctx_p->ut.uid = geteuid();
00205 ctx_p->ut.gid = getegid();
00206
00207 DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n",
00208 (unsigned int)ctx_p->ut.uid, (unsigned int)ctx_p->ut.gid, sec_ctx_stack_ndx ));
00209
00210 ctx_p->token = dup_nt_token(NULL,
00211 sec_ctx_stack[sec_ctx_stack_ndx-1].token);
00212
00213 ctx_p->ut.ngroups = sys_getgroups(0, NULL);
00214
00215 if (ctx_p->ut.ngroups != 0) {
00216 if (!(ctx_p->ut.groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ut.ngroups))) {
00217 DEBUG(0, ("Out of memory in push_sec_ctx()\n"));
00218 TALLOC_FREE(ctx_p->token);
00219 return False;
00220 }
00221
00222 sys_getgroups(ctx_p->ut.ngroups, ctx_p->ut.groups);
00223 } else {
00224 ctx_p->ut.groups = NULL;
00225 }
00226
00227 return True;
00228 }
00229
00230
00231
00232
00233
00234 void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN *token)
00235 {
00236 struct sec_ctx *ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
00237
00238
00239
00240 DEBUG(3, ("setting sec ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
00241 (unsigned int)uid, (unsigned int)gid, sec_ctx_stack_ndx));
00242
00243 debug_nt_user_token(DBGC_CLASS, 5, token);
00244 debug_unix_user_token(DBGC_CLASS, 5, uid, gid, ngroups, groups);
00245
00246 gain_root();
00247
00248 #ifdef HAVE_SETGROUPS
00249 sys_setgroups(ngroups, groups);
00250 #endif
00251
00252 ctx_p->ut.ngroups = ngroups;
00253
00254 SAFE_FREE(ctx_p->ut.groups);
00255 if (token && (token == ctx_p->token)) {
00256 smb_panic("DUPLICATE_TOKEN");
00257 }
00258
00259 TALLOC_FREE(ctx_p->token);
00260
00261 if (ngroups) {
00262 ctx_p->ut.groups = (gid_t *)memdup(groups,
00263 sizeof(gid_t) * ngroups);
00264 if (!ctx_p->ut.groups) {
00265 smb_panic("memdup failed");
00266 }
00267 } else {
00268 ctx_p->ut.groups = NULL;
00269 }
00270
00271 if (token) {
00272 ctx_p->token = dup_nt_token(NULL, token);
00273 if (!ctx_p->token) {
00274 smb_panic("dup_nt_token failed");
00275 }
00276 } else {
00277 ctx_p->token = NULL;
00278 }
00279
00280 become_id(uid, gid);
00281
00282 ctx_p->ut.uid = uid;
00283 ctx_p->ut.gid = gid;
00284
00285
00286
00287 current_user.ut.uid = uid;
00288 current_user.ut.gid = gid;
00289 current_user.ut.ngroups = ngroups;
00290 current_user.ut.groups = groups;
00291 current_user.nt_user_token = ctx_p->token;
00292 }
00293
00294
00295
00296
00297
00298 void set_root_sec_ctx(void)
00299 {
00300
00301
00302 set_sec_ctx(0, 0, 0, NULL, NULL);
00303 }
00304
00305
00306
00307
00308
00309 BOOL pop_sec_ctx(void)
00310 {
00311 struct sec_ctx *ctx_p;
00312 struct sec_ctx *prev_ctx_p;
00313
00314
00315
00316 if (sec_ctx_stack_ndx == 0) {
00317 DEBUG(0, ("Security context stack underflow!\n"));
00318 smb_panic("Security context stack underflow!\n");
00319 }
00320
00321 ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
00322
00323
00324
00325 ctx_p->ut.uid = (uid_t)-1;
00326 ctx_p->ut.gid = (gid_t)-1;
00327
00328 SAFE_FREE(ctx_p->ut.groups);
00329 ctx_p->ut.ngroups = 0;
00330
00331 TALLOC_FREE(ctx_p->token);
00332
00333
00334
00335 sec_ctx_stack_ndx--;
00336
00337 gain_root();
00338
00339 prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx];
00340
00341 #ifdef HAVE_SETGROUPS
00342 sys_setgroups(prev_ctx_p->ut.ngroups, prev_ctx_p->ut.groups);
00343 #endif
00344
00345 become_id(prev_ctx_p->ut.uid, prev_ctx_p->ut.gid);
00346
00347
00348
00349 current_user.ut.uid = prev_ctx_p->ut.uid;
00350 current_user.ut.gid = prev_ctx_p->ut.gid;
00351 current_user.ut.ngroups = prev_ctx_p->ut.ngroups;
00352 current_user.ut.groups = prev_ctx_p->ut.groups;
00353 current_user.nt_user_token = prev_ctx_p->token;
00354
00355 DEBUG(3, ("pop_sec_ctx (%u, %u) - sec_ctx_stack_ndx = %d\n",
00356 (unsigned int)geteuid(), (unsigned int)getegid(), sec_ctx_stack_ndx));
00357
00358 return True;
00359 }
00360
00361
00362
00363 void init_sec_ctx(void)
00364 {
00365 int i;
00366 struct sec_ctx *ctx_p;
00367
00368
00369
00370 memset(sec_ctx_stack, 0, sizeof(struct sec_ctx) * MAX_SEC_CTX_DEPTH);
00371
00372 for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) {
00373 sec_ctx_stack[i].ut.uid = (uid_t)-1;
00374 sec_ctx_stack[i].ut.gid = (gid_t)-1;
00375 }
00376
00377
00378 ctx_p = &sec_ctx_stack[0];
00379
00380 ctx_p->ut.uid = geteuid();
00381 ctx_p->ut.gid = getegid();
00382
00383 get_current_groups(ctx_p->ut.gid, &ctx_p->ut.ngroups, &ctx_p->ut.groups);
00384
00385 ctx_p->token = NULL;
00386
00387
00388
00389 current_user.ut.uid = ctx_p->ut.uid;
00390 current_user.ut.gid = ctx_p->ut.gid;
00391 current_user.ut.ngroups = ctx_p->ut.ngroups;
00392 current_user.ut.groups = ctx_p->ut.groups;
00393
00394
00395
00396
00397 current_user.conn = NULL;
00398 current_user.vuid = UID_FIELD_INVALID;
00399 current_user.nt_user_token = NULL;
00400 }