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
00024 extern struct current_user current_user;
00025
00026
00027
00028
00029
00030 gid_t get_current_user_gid_first(int *piterator)
00031 {
00032 *piterator = 0;
00033 return current_user.ut.gid;
00034 }
00035
00036 gid_t get_current_user_gid_next(int *piterator)
00037 {
00038 gid_t ret;
00039
00040 if (!current_user.ut.groups || *piterator >= current_user.ut.ngroups) {
00041 return (gid_t)-1;
00042 }
00043
00044 ret = current_user.ut.groups[*piterator];
00045 (*piterator) += 1;
00046 return ret;
00047 }
00048
00049
00050
00051
00052
00053 BOOL change_to_guest(void)
00054 {
00055 static struct passwd *pass=NULL;
00056
00057 if (!pass) {
00058
00059 pass = getpwnam_alloc(NULL, lp_guestaccount());
00060 if (!pass)
00061 return(False);
00062 }
00063
00064 #ifdef AIX
00065
00066
00067 initgroups(pass->pw_name, pass->pw_gid);
00068 #endif
00069
00070 set_sec_ctx(pass->pw_uid, pass->pw_gid, 0, NULL, NULL);
00071
00072 current_user.conn = NULL;
00073 current_user.vuid = UID_FIELD_INVALID;
00074
00075 TALLOC_FREE(pass);
00076 pass = NULL;
00077
00078 return True;
00079 }
00080
00081
00082
00083
00084
00085 static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
00086 {
00087 unsigned int i;
00088 struct vuid_cache_entry *ent = NULL;
00089 BOOL readonly_share;
00090 NT_USER_TOKEN *token;
00091
00092 for (i=0;i<conn->vuid_cache.entries && i< VUID_CACHE_SIZE;i++) {
00093 if (conn->vuid_cache.array[i].vuid == vuser->vuid) {
00094 ent = &conn->vuid_cache.array[i];
00095 conn->read_only = ent->read_only;
00096 conn->admin_user = ent->admin_user;
00097 return(True);
00098 }
00099 }
00100
00101 if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum))
00102 return(False);
00103
00104 readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
00105 vuser->nt_user_token,
00106 SNUM(conn));
00107
00108 token = conn->nt_user_token ?
00109 conn->nt_user_token : vuser->nt_user_token;
00110
00111 if (!readonly_share &&
00112 !share_access_check(token, lp_servicename(snum),
00113 FILE_WRITE_DATA)) {
00114
00115
00116 readonly_share = True;
00117 DEBUG(5,("falling back to read-only access-evaluation due to "
00118 "security descriptor\n"));
00119 }
00120
00121 if (!share_access_check(token, lp_servicename(snum),
00122 readonly_share ?
00123 FILE_READ_DATA : FILE_WRITE_DATA)) {
00124 return False;
00125 }
00126
00127 i = conn->vuid_cache.entries % VUID_CACHE_SIZE;
00128 if (conn->vuid_cache.entries < VUID_CACHE_SIZE)
00129 conn->vuid_cache.entries++;
00130
00131 ent = &conn->vuid_cache.array[i];
00132 ent->vuid = vuser->vuid;
00133 ent->read_only = readonly_share;
00134
00135 ent->admin_user = token_contains_name_in_list(
00136 vuser->user.unix_name, NULL, vuser->nt_user_token,
00137 lp_admin_users(SNUM(conn)));
00138
00139 conn->read_only = ent->read_only;
00140 conn->admin_user = ent->admin_user;
00141
00142 return(True);
00143 }
00144
00145
00146
00147
00148
00149
00150 BOOL change_to_user(connection_struct *conn, uint16 vuid)
00151 {
00152 user_struct *vuser = get_valid_user_struct(vuid);
00153 int snum;
00154 gid_t gid;
00155 uid_t uid;
00156 char group_c;
00157 BOOL must_free_token = False;
00158 NT_USER_TOKEN *token = NULL;
00159 int num_groups = 0;
00160 gid_t *group_list = NULL;
00161
00162 if (!conn) {
00163 DEBUG(2,("change_to_user: Connection not open\n"));
00164 return(False);
00165 }
00166
00167
00168
00169
00170
00171
00172
00173
00174 if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
00175 (current_user.ut.uid == conn->uid)) {
00176 DEBUG(4,("change_to_user: Skipping user change - already "
00177 "user\n"));
00178 return(True);
00179 } else if ((current_user.conn == conn) &&
00180 (vuser != 0) && (current_user.vuid == vuid) &&
00181 (current_user.ut.uid == vuser->uid)) {
00182 DEBUG(4,("change_to_user: Skipping user change - already "
00183 "user\n"));
00184 return(True);
00185 }
00186
00187 snum = SNUM(conn);
00188
00189 if ((vuser) && !check_user_ok(conn, vuser, snum)) {
00190 DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
00191 "not permitted access to share %s.\n",
00192 vuser->user.smb_name, vuser->user.unix_name, vuid,
00193 lp_servicename(snum)));
00194 return False;
00195 }
00196
00197 if (conn->force_user) {
00198 uid = conn->uid;
00199 gid = conn->gid;
00200 group_list = conn->groups;
00201 num_groups = conn->ngroups;
00202 token = conn->nt_user_token;
00203 } else if (vuser) {
00204 uid = conn->admin_user ? 0 : vuser->uid;
00205 gid = vuser->gid;
00206 num_groups = vuser->n_groups;
00207 group_list = vuser->groups;
00208 token = vuser->nt_user_token;
00209 } else {
00210 DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
00211 "share %s.\n",vuid, lp_servicename(snum) ));
00212 return False;
00213 }
00214
00215
00216
00217
00218
00219
00220
00221 if((group_c = *lp_force_group(snum))) {
00222
00223 token = dup_nt_token(NULL, token);
00224 if (token == NULL) {
00225 DEBUG(0, ("dup_nt_token failed\n"));
00226 return False;
00227 }
00228 must_free_token = True;
00229
00230 if(group_c == '+') {
00231
00232
00233
00234
00235
00236
00237
00238
00239 int i;
00240 for (i = 0; i < num_groups; i++) {
00241 if (group_list[i] == conn->gid) {
00242 gid = conn->gid;
00243 gid_to_sid(&token->user_sids[1], gid);
00244 break;
00245 }
00246 }
00247 } else {
00248 gid = conn->gid;
00249 gid_to_sid(&token->user_sids[1], gid);
00250 }
00251 }
00252
00253
00254
00255
00256 current_user.ut.ngroups = num_groups;
00257 current_user.ut.groups = group_list;
00258
00259 set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
00260 token);
00261
00262
00263
00264
00265
00266 if (must_free_token)
00267 TALLOC_FREE(token);
00268
00269 current_user.conn = conn;
00270 current_user.vuid = vuid;
00271
00272 DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",
00273 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
00274
00275 return(True);
00276 }
00277
00278
00279
00280
00281
00282
00283 BOOL change_to_root_user(void)
00284 {
00285 set_root_sec_ctx();
00286
00287 DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",
00288 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));
00289
00290 current_user.conn = NULL;
00291 current_user.vuid = UID_FIELD_INVALID;
00292
00293 return(True);
00294 }
00295
00296
00297
00298
00299
00300
00301
00302 BOOL become_authenticated_pipe_user(pipes_struct *p)
00303 {
00304 if (!push_sec_ctx())
00305 return False;
00306
00307 set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid,
00308 p->pipe_user.ut.ngroups, p->pipe_user.ut.groups,
00309 p->pipe_user.nt_user_token);
00310
00311 return True;
00312 }
00313
00314
00315
00316
00317
00318
00319
00320
00321 BOOL unbecome_authenticated_pipe_user(void)
00322 {
00323 return pop_sec_ctx();
00324 }
00325
00326
00327
00328
00329
00330 struct conn_ctx {
00331 connection_struct *conn;
00332 uint16 vuid;
00333 };
00334
00335
00336
00337 static struct conn_ctx conn_ctx_stack[MAX_SEC_CTX_DEPTH];
00338 static int conn_ctx_stack_ndx;
00339
00340 static void push_conn_ctx(void)
00341 {
00342 struct conn_ctx *ctx_p;
00343
00344
00345
00346 if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) {
00347 DEBUG(0, ("Connection context stack overflow!\n"));
00348 smb_panic("Connection context stack overflow!\n");
00349 }
00350
00351
00352 ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
00353
00354 ctx_p->conn = current_user.conn;
00355 ctx_p->vuid = current_user.vuid;
00356
00357 DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",
00358 (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx ));
00359
00360 conn_ctx_stack_ndx++;
00361 }
00362
00363 static void pop_conn_ctx(void)
00364 {
00365 struct conn_ctx *ctx_p;
00366
00367
00368
00369 if (conn_ctx_stack_ndx == 0) {
00370 DEBUG(0, ("Connection context stack underflow!\n"));
00371 smb_panic("Connection context stack underflow!\n");
00372 }
00373
00374 conn_ctx_stack_ndx--;
00375 ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx];
00376
00377 current_user.conn = ctx_p->conn;
00378 current_user.vuid = ctx_p->vuid;
00379
00380 ctx_p->conn = NULL;
00381 ctx_p->vuid = UID_FIELD_INVALID;
00382 }
00383
00384
00385
00386
00387
00388
00389 void become_root(void)
00390 {
00391 push_sec_ctx();
00392 push_conn_ctx();
00393 set_root_sec_ctx();
00394 }
00395
00396
00397
00398 void unbecome_root(void)
00399 {
00400 pop_sec_ctx();
00401 pop_conn_ctx();
00402 }
00403
00404
00405
00406
00407
00408
00409 BOOL become_user(connection_struct *conn, uint16 vuid)
00410 {
00411 if (!push_sec_ctx())
00412 return False;
00413
00414 push_conn_ctx();
00415
00416 if (!change_to_user(conn, vuid)) {
00417 pop_sec_ctx();
00418 pop_conn_ctx();
00419 return False;
00420 }
00421
00422 return True;
00423 }
00424
00425 BOOL unbecome_user(void)
00426 {
00427 pop_sec_ctx();
00428 pop_conn_ctx();
00429 return True;
00430 }