Changeset 745 for trunk/server/source3/smbd/uid.c
- Timestamp:
- Nov 27, 2012, 4:43:17 PM (13 years ago)
- Location:
- trunk/server
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/server
- Property svn:mergeinfo changed
/vendor/current merged: 581,587,591,594,597,600,615,618,740
- Property svn:mergeinfo changed
-
trunk/server/source3/smbd/uid.c
r596 r745 19 19 20 20 #include "includes.h" 21 #include "system/passwd.h" 22 #include "smbd/smbd.h" 21 23 #include "smbd/globals.h" 24 #include "../librpc/gen_ndr/netlogon.h" 25 #include "libcli/security/security.h" 26 #include "passdb/lookup_sid.h" 27 #include "auth.h" 22 28 23 29 /* what user is current? */ … … 32 38 struct passwd *pass; 33 39 34 pass = Get_Pwnam_alloc(talloc_ autofree_context(), lp_guestaccount());40 pass = Get_Pwnam_alloc(talloc_tos(), lp_guestaccount()); 35 41 if (!pass) { 36 42 return false; … … 54 60 55 61 /**************************************************************************** 56 talloc free the conn->se rver_info if not used in the vuid cache.57 ****************************************************************************/ 58 59 static void free_conn_se rver_info_if_unused(connection_struct *conn)62 talloc free the conn->session_info if not used in the vuid cache. 63 ****************************************************************************/ 64 65 static void free_conn_session_info_if_unused(connection_struct *conn) 60 66 { 61 67 unsigned int i; … … 65 71 ent = &conn->vuid_cache.array[i]; 66 72 if (ent->vuid != UID_FIELD_INVALID && 67 conn->se rver_info == ent->server_info) {73 conn->session_info == ent->session_info) { 68 74 return; 69 75 } 70 76 } 71 77 /* Not used, safe to free. */ 72 TALLOC_FREE(conn->se rver_info);78 TALLOC_FREE(conn->session_info); 73 79 } 74 80 … … 76 82 Check if a username is OK. 77 83 78 This sets up conn->se rver_info with a copy related to this vuser that84 This sets up conn->session_info with a copy related to this vuser that 79 85 later code can then mess with. 80 86 ********************************************************************/ … … 82 88 static bool check_user_ok(connection_struct *conn, 83 89 uint16_t vuid, 84 const struct auth_serversupplied_info *se rver_info,90 const struct auth_serversupplied_info *session_info, 85 91 int snum) 86 92 { … … 96 102 ent = &conn->vuid_cache.array[i]; 97 103 if (ent->vuid == vuid) { 98 free_conn_se rver_info_if_unused(conn);99 conn->se rver_info = ent->server_info;104 free_conn_session_info_if_unused(conn); 105 conn->session_info = ent->session_info; 100 106 conn->read_only = ent->read_only; 101 conn->admin_user = ent->admin_user;102 107 return(True); 103 108 } … … 105 110 } 106 111 107 if (!user_ok_token(se rver_info->unix_name,108 pdb_get_domain(server_info->sam_account),109 se rver_info->ptok, snum))112 if (!user_ok_token(session_info->unix_name, 113 session_info->info3->base.domain.string, 114 session_info->security_token, snum)) 110 115 return(False); 111 116 112 117 readonly_share = is_share_read_only_for_token( 113 se rver_info->unix_name,114 pdb_get_domain(server_info->sam_account),115 se rver_info->ptok,118 session_info->unix_name, 119 session_info->info3->base.domain.string, 120 session_info->security_token, 116 121 conn); 117 122 118 123 if (!readonly_share && 119 !share_access_check(server_info->ptok, lp_servicename(snum), 120 FILE_WRITE_DATA)) { 124 !share_access_check(session_info->security_token, 125 lp_servicename(snum), FILE_WRITE_DATA, 126 NULL)) { 121 127 /* smb.conf allows r/w, but the security descriptor denies 122 128 * write. Fall back to looking at readonly. */ … … 126 132 } 127 133 128 if (!share_access_check(server_info->ptok, lp_servicename(snum), 134 if (!share_access_check(session_info->security_token, 135 lp_servicename(snum), 129 136 readonly_share ? 130 FILE_READ_DATA : FILE_WRITE_DATA)) { 137 FILE_READ_DATA : FILE_WRITE_DATA, 138 NULL)) { 131 139 return False; 132 140 } 133 141 134 142 admin_user = token_contains_name_in_list( 135 se rver_info->unix_name,136 pdb_get_domain(server_info->sam_account),137 NULL, se rver_info->ptok, lp_admin_users(snum));143 session_info->unix_name, 144 session_info->info3->base.domain.string, 145 NULL, session_info->security_token, lp_admin_users(snum)); 138 146 139 147 if (valid_vuid) { … … 144 152 (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE; 145 153 146 TALLOC_FREE(ent->se rver_info);154 TALLOC_FREE(ent->session_info); 147 155 148 156 /* 149 * If force_user was set, all se rver_info's are based on the same157 * If force_user was set, all session_info's are based on the same 150 158 * username-based faked one. 151 159 */ 152 160 153 ent->se rver_info = copy_serverinfo(154 conn, conn->force_user ? conn->se rver_info : server_info);155 156 if (ent->se rver_info == NULL) {161 ent->session_info = copy_serverinfo( 162 conn, conn->force_user ? conn->session_info : session_info); 163 164 if (ent->session_info == NULL) { 157 165 ent->vuid = UID_FIELD_INVALID; 158 166 return false; … … 161 169 ent->vuid = vuid; 162 170 ent->read_only = readonly_share; 163 ent->admin_user = admin_user; 164 free_conn_server_info_if_unused(conn); 165 conn->server_info = ent->server_info; 171 free_conn_session_info_if_unused(conn); 172 conn->session_info = ent->session_info; 166 173 } 167 174 168 175 conn->read_only = readonly_share; 169 conn->admin_user = admin_user; 176 if (admin_user) { 177 DEBUG(2,("check_user_ok: user %s is an admin user. " 178 "Setting uid as %d\n", 179 conn->session_info->unix_name, 180 sec_initial_uid() )); 181 conn->session_info->utok.uid = sec_initial_uid(); 182 } 170 183 171 184 return(True); … … 189 202 ent->vuid = UID_FIELD_INVALID; 190 203 /* 191 * We need to keep conn->se rver_info around192 * if it's equal to ent->se rver_info as a SMBulogoff204 * We need to keep conn->session_info around 205 * if it's equal to ent->session_info as a SMBulogoff 193 206 * is often followed by a SMBtdis (with an invalid 194 207 * vuid). The debug code (or regular code in 195 208 * vfs_full_audit) wants to refer to the 196 * conn->se rver_info pointer to print debug209 * conn->session_info pointer to print debug 197 210 * statements. Theoretically this is a bug, 198 * as once the vuid is gone the se rver_info211 * as once the vuid is gone the session_info 199 212 * on the conn struct isn't valid any more, 200 213 * but there's enough code that assumes 201 * conn->se rver_info is never null that214 * conn->session_info is never null that 202 215 * it's easier to hold onto the old pointer 203 216 * until we get a new sessionsetupX. … … 206 219 * leaking memory here. See bug #6315. JRA. 207 220 */ 208 if (conn->se rver_info == ent->server_info) {209 ent->se rver_info = NULL;221 if (conn->session_info == ent->session_info) { 222 ent->session_info = NULL; 210 223 } else { 211 TALLOC_FREE(ent->se rver_info);224 TALLOC_FREE(ent->session_info); 212 225 } 213 226 ent->read_only = False; 214 ent->admin_user = False;215 227 } 216 228 } … … 222 234 ****************************************************************************/ 223 235 224 bool change_to_user(connection_struct *conn, uint16 vuid) 225 { 226 const struct auth_serversupplied_info *server_info = NULL; 227 struct smbd_server_connection *sconn = smbd_server_conn; 228 user_struct *vuser = get_valid_user_struct(sconn, vuid); 236 static bool change_to_user_internal(connection_struct *conn, 237 const struct auth_serversupplied_info *session_info, 238 uint16_t vuid) 239 { 229 240 int snum; 230 241 gid_t gid; … … 233 244 int num_groups = 0; 234 245 gid_t *group_list = NULL; 246 bool ok; 247 248 snum = SNUM(conn); 249 250 ok = check_user_ok(conn, vuid, session_info, snum); 251 if (!ok) { 252 DEBUG(2,("SMB user %s (unix user %s) " 253 "not permitted access to share %s.\n", 254 session_info->sanitized_username, 255 session_info->unix_name, 256 lp_servicename(snum))); 257 return false; 258 } 259 260 uid = conn->session_info->utok.uid; 261 gid = conn->session_info->utok.gid; 262 num_groups = conn->session_info->utok.ngroups; 263 group_list = conn->session_info->utok.groups; 264 265 /* 266 * See if we should force group for this service. If so this overrides 267 * any group set in the force user code. 268 */ 269 if((group_c = *lp_force_group(snum))) { 270 271 SMB_ASSERT(conn->force_group_gid != (gid_t)-1); 272 273 if (group_c == '+') { 274 int i; 275 276 /* 277 * Only force group if the user is a member of the 278 * service group. Check the group memberships for this 279 * user (we already have this) to see if we should force 280 * the group. 281 */ 282 for (i = 0; i < num_groups; i++) { 283 if (group_list[i] == conn->force_group_gid) { 284 conn->session_info->utok.gid = 285 conn->force_group_gid; 286 gid = conn->force_group_gid; 287 gid_to_sid(&conn->session_info->security_token 288 ->sids[1], gid); 289 break; 290 } 291 } 292 } else { 293 conn->session_info->utok.gid = conn->force_group_gid; 294 gid = conn->force_group_gid; 295 gid_to_sid(&conn->session_info->security_token->sids[1], 296 gid); 297 } 298 } 299 300 /*Set current_user since we will immediately also call set_sec_ctx() */ 301 current_user.ut.ngroups = num_groups; 302 current_user.ut.groups = group_list; 303 304 set_sec_ctx(uid, 305 gid, 306 current_user.ut.ngroups, 307 current_user.ut.groups, 308 conn->session_info->security_token); 309 310 current_user.conn = conn; 311 current_user.vuid = vuid; 312 313 DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n", 314 (int)getuid(), 315 (int)geteuid(), 316 (int)getgid(), 317 (int)getegid())); 318 319 return true; 320 } 321 322 bool change_to_user(connection_struct *conn, uint16_t vuid) 323 { 324 const struct auth_serversupplied_info *session_info = NULL; 325 user_struct *vuser; 326 int snum = SNUM(conn); 235 327 236 328 if (!conn) { 237 DEBUG(2,(" change_to_user:Connection not open\n"));329 DEBUG(2,("Connection not open\n")); 238 330 return(False); 239 331 } 332 333 vuser = get_valid_user_struct(conn->sconn, vuid); 240 334 241 335 /* … … 247 341 248 342 if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && 249 (current_user.ut.uid == conn->se rver_info->utok.uid)) {250 DEBUG(4,(" change_to_user:Skipping user change - already "343 (current_user.ut.uid == conn->session_info->utok.uid)) { 344 DEBUG(4,("Skipping user change - already " 251 345 "user\n")); 252 346 return(True); 253 } else if ((current_user.conn == conn) && 347 } else if ((current_user.conn == conn) && 254 348 (vuser != NULL) && (current_user.vuid == vuid) && 255 (current_user.ut.uid == vuser->se rver_info->utok.uid)) {256 DEBUG(4,(" change_to_user:Skipping user change - already "349 (current_user.ut.uid == vuser->session_info->utok.uid)) { 350 DEBUG(4,("Skipping user change - already " 257 351 "user\n")); 258 352 return(True); 259 353 } 260 354 261 snum = SNUM(conn); 262 263 server_info = vuser ? vuser->server_info : conn->server_info; 264 265 if (!server_info) { 355 session_info = vuser ? vuser->session_info : conn->session_info; 356 357 if (session_info == NULL) { 266 358 /* Invalid vuid sent - even with security = share. */ 267 DEBUG(2,(" change_to_user:Invalid vuid %d used on "268 "share %s.\n", vuid, lp_servicename(snum) ));359 DEBUG(2,("Invalid vuid %d used on " 360 "share %s.\n", vuid, lp_servicename(snum) )); 269 361 return false; 270 362 } 271 363 272 if (!check_user_ok(conn, vuid, server_info, snum)) { 273 DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) " 274 "not permitted access to share %s.\n", 275 server_info->sanitized_username, 276 server_info->unix_name, vuid, 277 lp_servicename(snum))); 278 return false; 279 } 280 281 /* 282 * conn->server_info is now correctly set up with a copy we can mess 283 * with for force_group etc. 284 */ 285 286 if (conn->force_user) /* security = share sets this too */ { 287 uid = conn->server_info->utok.uid; 288 gid = conn->server_info->utok.gid; 289 group_list = conn->server_info->utok.groups; 290 num_groups = conn->server_info->utok.ngroups; 291 } else if (vuser) { 292 uid = conn->admin_user ? 0 : vuser->server_info->utok.uid; 293 gid = conn->server_info->utok.gid; 294 num_groups = conn->server_info->utok.ngroups; 295 group_list = conn->server_info->utok.groups; 296 } else { 297 DEBUG(2,("change_to_user: Invalid vuid used %d in accessing " 298 "share %s.\n",vuid, lp_servicename(snum) )); 364 /* security = share sets force_user. */ 365 if (!conn->force_user && vuser == NULL) { 366 DEBUG(2,("Invalid vuid used %d in accessing " 367 "share %s.\n", vuid, lp_servicename(snum) )); 299 368 return False; 300 369 } 301 370 302 /* 303 * See if we should force group for this service. 304 * If so this overrides any group set in the force 305 * user code. 306 */ 307 308 if((group_c = *lp_force_group(snum))) { 309 310 SMB_ASSERT(conn->force_group_gid != (gid_t)-1); 311 312 if(group_c == '+') { 313 314 /* 315 * Only force group if the user is a member of 316 * the service group. Check the group memberships for 317 * this user (we already have this) to 318 * see if we should force the group. 319 */ 320 321 int i; 322 for (i = 0; i < num_groups; i++) { 323 if (group_list[i] 324 == conn->force_group_gid) { 325 conn->server_info->utok.gid = 326 conn->force_group_gid; 327 gid = conn->force_group_gid; 328 gid_to_sid(&conn->server_info->ptok 329 ->user_sids[1], gid); 330 break; 331 } 332 } 333 } else { 334 conn->server_info->utok.gid = conn->force_group_gid; 335 gid = conn->force_group_gid; 336 gid_to_sid(&conn->server_info->ptok->user_sids[1], 337 gid); 338 } 339 } 340 341 /* Now set current_user since we will immediately also call 342 set_sec_ctx() */ 343 344 current_user.ut.ngroups = num_groups; 345 current_user.ut.groups = group_list; 346 347 set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, 348 conn->server_info->ptok); 349 350 current_user.conn = conn; 351 current_user.vuid = vuid; 352 353 DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n", 354 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid())); 355 356 return(True); 371 return change_to_user_internal(conn, session_info, vuid); 372 } 373 374 bool change_to_user_by_session(connection_struct *conn, 375 const struct auth_serversupplied_info *session_info) 376 { 377 SMB_ASSERT(conn != NULL); 378 SMB_ASSERT(session_info != NULL); 379 380 if ((current_user.conn == conn) && 381 (current_user.ut.uid == session_info->utok.uid)) { 382 DEBUG(7, ("Skipping user change - already user\n")); 383 384 return true; 385 } 386 387 return change_to_user_internal(conn, session_info, UID_FIELD_INVALID); 357 388 } 358 389 … … 381 412 ****************************************************************************/ 382 413 383 bool become_authenticated_pipe_user( pipes_struct *p)414 bool become_authenticated_pipe_user(struct auth_serversupplied_info *session_info) 384 415 { 385 416 if (!push_sec_ctx()) 386 417 return False; 387 418 388 set_sec_ctx( p->server_info->utok.uid, p->server_info->utok.gid,389 p->server_info->utok.ngroups, p->server_info->utok.groups,390 p->server_info->ptok);419 set_sec_ctx(session_info->utok.uid, session_info->utok.gid, 420 session_info->utok.ngroups, session_info->utok.groups, 421 session_info->security_token); 391 422 392 423 return True; … … 426 457 ctx_p->vuid = current_user.vuid; 427 458 428 DEBUG( 3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n",459 DEBUG(4, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n", 429 460 (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx )); 430 461 … … 500 531 } 501 532 533 bool become_user_by_session(connection_struct *conn, 534 const struct auth_serversupplied_info *session_info) 535 { 536 if (!push_sec_ctx()) 537 return false; 538 539 push_conn_ctx(); 540 541 if (!change_to_user_by_session(conn, session_info)) { 542 pop_sec_ctx(); 543 pop_conn_ctx(); 544 return false; 545 } 546 547 return true; 548 } 549 502 550 bool unbecome_user(void) 503 551 { … … 506 554 return True; 507 555 } 556 557 /**************************************************************************** 558 Return the current user we are running effectively as on this connection. 559 I'd like to make this return conn->session_info->utok.uid, but become_root() 560 doesn't alter this value. 561 ****************************************************************************/ 562 563 uid_t get_current_uid(connection_struct *conn) 564 { 565 return current_user.ut.uid; 566 } 567 568 /**************************************************************************** 569 Return the current group we are running effectively as on this connection. 570 I'd like to make this return conn->session_info->utok.gid, but become_root() 571 doesn't alter this value. 572 ****************************************************************************/ 573 574 gid_t get_current_gid(connection_struct *conn) 575 { 576 return current_user.ut.gid; 577 } 578 579 /**************************************************************************** 580 Return the UNIX token we are running effectively as on this connection. 581 I'd like to make this return &conn->session_info->utok, but become_root() 582 doesn't alter this value. 583 ****************************************************************************/ 584 585 const struct security_unix_token *get_current_utok(connection_struct *conn) 586 { 587 return ¤t_user.ut; 588 } 589 590 const struct security_token *get_current_nttok(connection_struct *conn) 591 { 592 return current_user.nt_user_token; 593 } 594 595 uint16_t get_current_vuid(connection_struct *conn) 596 { 597 return current_user.vuid; 598 }
Note:
See TracChangeset
for help on using the changeset viewer.