Changeset 988 for vendor/current/source3/smbd/uid.c
- Timestamp:
- Nov 24, 2016, 1:14:11 PM (9 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
vendor/current/source3/smbd/uid.c
r740 r988 38 38 struct passwd *pass; 39 39 40 pass = Get_Pwnam_alloc(talloc_tos(), lp_guest account());40 pass = Get_Pwnam_alloc(talloc_tos(), lp_guest_account()); 41 41 if (!pass) { 42 42 return false; … … 69 69 for (i = 0; i < VUID_CACHE_SIZE; i++) { 70 70 struct vuid_cache_entry *ent; 71 ent = &conn->vuid_cache .array[i];71 ent = &conn->vuid_cache->array[i]; 72 72 if (ent->vuid != UID_FIELD_INVALID && 73 73 conn->session_info == ent->session_info) { … … 79 79 } 80 80 81 /**************************************************************************** 82 Setup the share access mask for a connection. 83 ****************************************************************************/ 84 85 static uint32_t create_share_access_mask(int snum, 86 bool readonly_share, 87 const struct security_token *token) 88 { 89 uint32_t share_access = 0; 90 91 share_access_check(token, 92 lp_servicename(talloc_tos(), snum), 93 MAXIMUM_ALLOWED_ACCESS, 94 &share_access); 95 96 if (readonly_share) { 97 share_access &= 98 ~(SEC_FILE_WRITE_DATA | SEC_FILE_APPEND_DATA | 99 SEC_FILE_WRITE_EA | SEC_FILE_WRITE_ATTRIBUTE | 100 SEC_DIR_DELETE_CHILD ); 101 } 102 103 if (security_token_has_privilege(token, SEC_PRIV_SECURITY)) { 104 share_access |= SEC_FLAG_SYSTEM_SECURITY; 105 } 106 if (security_token_has_privilege(token, SEC_PRIV_RESTORE)) { 107 share_access |= SEC_RIGHTS_PRIV_RESTORE; 108 } 109 if (security_token_has_privilege(token, SEC_PRIV_BACKUP)) { 110 share_access |= SEC_RIGHTS_PRIV_BACKUP; 111 } 112 if (security_token_has_privilege(token, SEC_PRIV_TAKE_OWNERSHIP)) { 113 share_access |= SEC_STD_WRITE_OWNER; 114 } 115 116 return share_access; 117 } 118 81 119 /******************************************************************* 82 Check if a username is OK. 83 84 This sets up conn->session_info with a copy related to this vuser that 85 later code can then mess with. 120 Calculate access mask and if this user can access this share. 86 121 ********************************************************************/ 87 122 88 static bool check_user_ok(connection_struct *conn, 89 uint16_t vuid, 90 const struct auth_serversupplied_info *session_info, 91 int snum) 92 { 93 bool valid_vuid = (vuid != UID_FIELD_INVALID); 94 unsigned int i; 95 bool readonly_share; 96 bool admin_user; 97 98 if (valid_vuid) { 99 struct vuid_cache_entry *ent; 100 101 for (i=0; i<VUID_CACHE_SIZE; i++) { 102 ent = &conn->vuid_cache.array[i]; 103 if (ent->vuid == vuid) { 104 free_conn_session_info_if_unused(conn); 105 conn->session_info = ent->session_info; 106 conn->read_only = ent->read_only; 107 return(True); 108 } 109 } 110 } 111 112 if (!user_ok_token(session_info->unix_name, 113 session_info->info3->base.domain.string, 114 session_info->security_token, snum)) 115 return(False); 123 NTSTATUS check_user_share_access(connection_struct *conn, 124 const struct auth_session_info *session_info, 125 uint32_t *p_share_access, 126 bool *p_readonly_share) 127 { 128 int snum = SNUM(conn); 129 uint32_t share_access = 0; 130 bool readonly_share = false; 131 132 if (!user_ok_token(session_info->unix_info->unix_name, 133 session_info->info->domain_name, 134 session_info->security_token, snum)) { 135 return NT_STATUS_ACCESS_DENIED; 136 } 116 137 117 138 readonly_share = is_share_read_only_for_token( 118 session_info->unix_ name,119 session_info->info 3->base.domain.string,139 session_info->unix_info->unix_name, 140 session_info->info->domain_name, 120 141 session_info->security_token, 121 142 conn); 122 143 144 share_access = create_share_access_mask(snum, 145 readonly_share, 146 session_info->security_token); 147 148 if ((share_access & (FILE_READ_DATA|FILE_WRITE_DATA)) == 0) { 149 /* No access, read or write. */ 150 DEBUG(3,("user %s connection to %s denied due to share " 151 "security descriptor.\n", 152 session_info->unix_info->unix_name, 153 lp_servicename(talloc_tos(), snum))); 154 return NT_STATUS_ACCESS_DENIED; 155 } 156 123 157 if (!readonly_share && 124 !share_access_check(session_info->security_token, 125 lp_servicename(snum), FILE_WRITE_DATA, 126 NULL)) { 158 !(share_access & FILE_WRITE_DATA)) { 127 159 /* smb.conf allows r/w, but the security descriptor denies 128 160 * write. Fall back to looking at readonly. */ … … 132 164 } 133 165 134 if (!share_access_check(session_info->security_token, 135 lp_servicename(snum), 136 readonly_share ? 137 FILE_READ_DATA : FILE_WRITE_DATA, 138 NULL)) { 139 return False; 166 *p_share_access = share_access; 167 *p_readonly_share = readonly_share; 168 169 return NT_STATUS_OK; 170 } 171 172 /******************************************************************* 173 Check if a username is OK. 174 175 This sets up conn->session_info with a copy related to this vuser that 176 later code can then mess with. 177 ********************************************************************/ 178 179 static bool check_user_ok(connection_struct *conn, 180 uint64_t vuid, 181 const struct auth_session_info *session_info, 182 int snum) 183 { 184 unsigned int i; 185 bool readonly_share = false; 186 bool admin_user = false; 187 struct vuid_cache_entry *ent = NULL; 188 uint32_t share_access = 0; 189 NTSTATUS status; 190 191 for (i=0; i<VUID_CACHE_SIZE; i++) { 192 ent = &conn->vuid_cache->array[i]; 193 if (ent->vuid == vuid) { 194 if (vuid == UID_FIELD_INVALID) { 195 /* 196 * Slow path, we don't care 197 * about the array traversal. 198 */ 199 continue; 200 } 201 free_conn_session_info_if_unused(conn); 202 conn->session_info = ent->session_info; 203 conn->read_only = ent->read_only; 204 conn->share_access = ent->share_access; 205 return(True); 206 } 207 } 208 209 status = check_user_share_access(conn, 210 session_info, 211 &share_access, 212 &readonly_share); 213 if (!NT_STATUS_IS_OK(status)) { 214 return false; 140 215 } 141 216 142 217 admin_user = token_contains_name_in_list( 143 session_info->unix_ name,144 session_info->info 3->base.domain.string,218 session_info->unix_info->unix_name, 219 session_info->info->domain_name, 145 220 NULL, session_info->security_token, lp_admin_users(snum)); 146 221 147 if (valid_vuid) { 148 struct vuid_cache_entry *ent = 149 &conn->vuid_cache.array[conn->vuid_cache.next_entry]; 150 151 conn->vuid_cache.next_entry = 152 (conn->vuid_cache.next_entry + 1) % VUID_CACHE_SIZE; 153 154 TALLOC_FREE(ent->session_info); 155 222 ent = &conn->vuid_cache->array[conn->vuid_cache->next_entry]; 223 224 conn->vuid_cache->next_entry = 225 (conn->vuid_cache->next_entry + 1) % VUID_CACHE_SIZE; 226 227 TALLOC_FREE(ent->session_info); 228 229 /* 230 * If force_user was set, all session_info's are based on the same 231 * username-based faked one. 232 */ 233 234 ent->session_info = copy_session_info( 235 conn, conn->force_user ? conn->session_info : session_info); 236 237 if (ent->session_info == NULL) { 238 ent->vuid = UID_FIELD_INVALID; 239 return false; 240 } 241 242 /* 243 * It's actually OK to call check_user_ok() with 244 * vuid == UID_FIELD_INVALID as called from change_to_user_by_session(). 245 * All this will do is throw away one entry in the cache. 246 */ 247 248 ent->vuid = vuid; 249 ent->read_only = readonly_share; 250 ent->share_access = share_access; 251 free_conn_session_info_if_unused(conn); 252 conn->session_info = ent->session_info; 253 if (vuid == UID_FIELD_INVALID) { 156 254 /* 157 * If force_user was set, all session_info's are based on the same158 * username-based faked one.255 * Not strictly needed, just make it really 256 * clear this entry is actually an unused one. 159 257 */ 160 161 ent->session_info = copy_serverinfo( 162 conn, conn->force_user ? conn->session_info : session_info); 163 164 if (ent->session_info == NULL) { 165 ent->vuid = UID_FIELD_INVALID; 166 return false; 167 } 168 169 ent->vuid = vuid; 170 ent->read_only = readonly_share; 171 free_conn_session_info_if_unused(conn); 172 conn->session_info = ent->session_info; 258 ent->read_only = false; 259 ent->share_access = 0; 260 ent->session_info = NULL; 173 261 } 174 262 175 263 conn->read_only = readonly_share; 264 conn->share_access = share_access; 265 176 266 if (admin_user) { 177 267 DEBUG(2,("check_user_ok: user %s is an admin user. " 178 268 "Setting uid as %d\n", 179 conn->session_info->unix_ name,269 conn->session_info->unix_info->unix_name, 180 270 sec_initial_uid() )); 181 conn->session_info->u tok.uid = sec_initial_uid();271 conn->session_info->unix_token->uid = sec_initial_uid(); 182 272 } 183 273 184 274 return(True); 185 }186 187 /****************************************************************************188 Clear a vuid out of the connection's vuid cache189 This is only called on SMBulogoff.190 ****************************************************************************/191 192 void conn_clear_vuid_cache(connection_struct *conn, uint16_t vuid)193 {194 int i;195 196 for (i=0; i<VUID_CACHE_SIZE; i++) {197 struct vuid_cache_entry *ent;198 199 ent = &conn->vuid_cache.array[i];200 201 if (ent->vuid == vuid) {202 ent->vuid = UID_FIELD_INVALID;203 /*204 * We need to keep conn->session_info around205 * if it's equal to ent->session_info as a SMBulogoff206 * is often followed by a SMBtdis (with an invalid207 * vuid). The debug code (or regular code in208 * vfs_full_audit) wants to refer to the209 * conn->session_info pointer to print debug210 * statements. Theoretically this is a bug,211 * as once the vuid is gone the session_info212 * on the conn struct isn't valid any more,213 * but there's enough code that assumes214 * conn->session_info is never null that215 * it's easier to hold onto the old pointer216 * until we get a new sessionsetupX.217 * As everything is hung off the218 * conn pointer as a talloc context we're not219 * leaking memory here. See bug #6315. JRA.220 */221 if (conn->session_info == ent->session_info) {222 ent->session_info = NULL;223 } else {224 TALLOC_FREE(ent->session_info);225 }226 ent->read_only = False;227 }228 }229 275 } 230 276 … … 235 281 236 282 static bool change_to_user_internal(connection_struct *conn, 237 const struct auth_se rversupplied_info *session_info,238 uint 16_t vuid)283 const struct auth_session_info *session_info, 284 uint64_t vuid) 239 285 { 240 286 int snum; … … 252 298 DEBUG(2,("SMB user %s (unix user %s) " 253 299 "not permitted access to share %s.\n", 254 session_info-> sanitized_username,255 session_info->unix_ name,256 lp_servicename( snum)));300 session_info->unix_info->sanitized_username, 301 session_info->unix_info->unix_name, 302 lp_servicename(talloc_tos(), snum))); 257 303 return false; 258 304 } 259 305 260 uid = conn->session_info->u tok.uid;261 gid = conn->session_info->u tok.gid;262 num_groups = conn->session_info->u tok.ngroups;263 group_list = conn->session_info->u tok.groups;306 uid = conn->session_info->unix_token->uid; 307 gid = conn->session_info->unix_token->gid; 308 num_groups = conn->session_info->unix_token->ngroups; 309 group_list = conn->session_info->unix_token->groups; 264 310 265 311 /* … … 267 313 * any group set in the force user code. 268 314 */ 269 if((group_c = *lp_force_group( snum))) {315 if((group_c = *lp_force_group(talloc_tos(), snum))) { 270 316 271 317 SMB_ASSERT(conn->force_group_gid != (gid_t)-1); … … 282 328 for (i = 0; i < num_groups; i++) { 283 329 if (group_list[i] == conn->force_group_gid) { 284 conn->session_info->u tok.gid =330 conn->session_info->unix_token->gid = 285 331 conn->force_group_gid; 286 332 gid = conn->force_group_gid; … … 291 337 } 292 338 } else { 293 conn->session_info->u tok.gid = conn->force_group_gid;339 conn->session_info->unix_token->gid = conn->force_group_gid; 294 340 gid = conn->force_group_gid; 295 341 gid_to_sid(&conn->session_info->security_token->sids[1], … … 320 366 } 321 367 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; 368 bool change_to_user(connection_struct *conn, uint64_t vuid) 369 { 370 struct user_struct *vuser; 326 371 int snum = SNUM(conn); 327 372 … … 333 378 vuser = get_valid_user_struct(conn->sconn, vuid); 334 379 335 /* 336 * We need a separate check in security=share mode due to vuid 337 * always being UID_FIELD_INVALID. If we don't do this then 338 * in share mode security we are *always* changing uid's between 339 * SMB's - this hurts performance - Badly. 340 */ 341 342 if((lp_security() == SEC_SHARE) && (current_user.conn == conn) && 343 (current_user.ut.uid == conn->session_info->utok.uid)) { 380 if ((current_user.conn == conn) && 381 (vuser != NULL) && (current_user.vuid == vuid) && 382 (current_user.ut.uid == vuser->session_info->unix_token->uid)) { 344 383 DEBUG(4,("Skipping user change - already " 345 384 "user\n")); 346 385 return(True); 347 } else if ((current_user.conn == conn) && 348 (vuser != NULL) && (current_user.vuid == vuid) && 349 (current_user.ut.uid == vuser->session_info->utok.uid)) { 350 DEBUG(4,("Skipping user change - already " 351 "user\n")); 352 return(True); 353 } 354 355 session_info = vuser ? vuser->session_info : conn->session_info; 356 357 if (session_info == NULL) { 358 /* Invalid vuid sent - even with security = share. */ 359 DEBUG(2,("Invalid vuid %d used on " 360 "share %s.\n", vuid, lp_servicename(snum) )); 386 } 387 388 if (vuser == NULL) { 389 /* Invalid vuid sent */ 390 DEBUG(2,("Invalid vuid %llu used on share %s.\n", 391 (unsigned long long)vuid, lp_servicename(talloc_tos(), 392 snum))); 361 393 return false; 362 394 } 363 395 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) )); 368 return False; 369 } 370 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) 396 return change_to_user_internal(conn, vuser->session_info, vuid); 397 } 398 399 static bool change_to_user_by_session(connection_struct *conn, 400 const struct auth_session_info *session_info) 376 401 { 377 402 SMB_ASSERT(conn != NULL); … … 379 404 380 405 if ((current_user.conn == conn) && 381 (current_user.ut.uid == session_info->u tok.uid)) {406 (current_user.ut.uid == session_info->unix_token->uid)) { 382 407 DEBUG(7, ("Skipping user change - already user\n")); 383 408 … … 393 418 ****************************************************************************/ 394 419 395 bool change_to_root_user(void)420 bool smbd_change_to_root_user(void) 396 421 { 397 422 set_root_sec_ctx(); … … 412 437 ****************************************************************************/ 413 438 414 bool become_authenticated_pipe_user(struct auth_serversupplied_info *session_info)439 bool smbd_become_authenticated_pipe_user(struct auth_session_info *session_info) 415 440 { 416 441 if (!push_sec_ctx()) 417 442 return False; 418 443 419 set_sec_ctx(session_info->u tok.uid, session_info->utok.gid,420 session_info->u tok.ngroups, session_info->utok.groups,444 set_sec_ctx(session_info->unix_token->uid, session_info->unix_token->gid, 445 session_info->unix_token->ngroups, session_info->unix_token->groups, 421 446 session_info->security_token); 447 448 DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n", 449 (int)getuid(), 450 (int)geteuid(), 451 (int)getgid(), 452 (int)getegid())); 422 453 423 454 return True; … … 431 462 ****************************************************************************/ 432 463 433 bool unbecome_authenticated_pipe_user(void)464 bool smbd_unbecome_authenticated_pipe_user(void) 434 465 { 435 466 return pop_sec_ctx(); … … 457 488 ctx_p->vuid = current_user.vuid; 458 489 459 DEBUG(4, ("push_conn_ctx(% u) : conn_ctx_stack_ndx = %d\n",460 (unsigned int)ctx_p->vuid, conn_ctx_stack_ndx));490 DEBUG(4, ("push_conn_ctx(%llu) : conn_ctx_stack_ndx = %d\n", 491 (unsigned long long)ctx_p->vuid, conn_ctx_stack_ndx)); 461 492 462 493 conn_ctx_stack_ndx++; … … 489 520 ****************************************************************************/ 490 521 491 void become_root(void)522 void smbd_become_root(void) 492 523 { 493 524 /* … … 504 535 /* Unbecome the root user */ 505 536 506 void unbecome_root(void)537 void smbd_unbecome_root(void) 507 538 { 508 539 pop_sec_ctx(); … … 515 546 ****************************************************************************/ 516 547 517 bool become_user(connection_struct *conn, uint 16vuid)548 bool become_user(connection_struct *conn, uint64_t vuid) 518 549 { 519 550 if (!push_sec_ctx()) … … 532 563 533 564 bool become_user_by_session(connection_struct *conn, 534 const struct auth_se rversupplied_info *session_info)565 const struct auth_session_info *session_info) 535 566 { 536 567 if (!push_sec_ctx()) … … 557 588 /**************************************************************************** 558 589 Return the current user we are running effectively as on this connection. 559 I'd like to make this return conn->session_info->u tok.uid, but become_root()590 I'd like to make this return conn->session_info->unix_token->uid, but become_root() 560 591 doesn't alter this value. 561 592 ****************************************************************************/ … … 568 599 /**************************************************************************** 569 600 Return the current group we are running effectively as on this connection. 570 I'd like to make this return conn->session_info->u tok.gid, but become_root()601 I'd like to make this return conn->session_info->unix_token->gid, but become_root() 571 602 doesn't alter this value. 572 603 ****************************************************************************/ … … 579 610 /**************************************************************************** 580 611 Return the UNIX token we are running effectively as on this connection. 581 I'd like to make this return &conn->session_info->u tok,but become_root()612 I'd like to make this return &conn->session_info->unix_token-> but become_root() 582 613 doesn't alter this value. 583 614 ****************************************************************************/ … … 588 619 } 589 620 621 /**************************************************************************** 622 Return the Windows token we are running effectively as on this connection. 623 If this is currently a NULL token as we're inside become_root() - a temporary 624 UNIX security override, then we search up the stack for the previous active 625 token. 626 ****************************************************************************/ 627 590 628 const struct security_token *get_current_nttok(connection_struct *conn) 591 629 { 592 return current_user.nt_user_token; 593 } 594 595 uint16_t get_current_vuid(connection_struct *conn) 630 if (current_user.nt_user_token) { 631 return current_user.nt_user_token; 632 } 633 return sec_ctx_active_token(); 634 } 635 636 uint64_t get_current_vuid(connection_struct *conn) 596 637 { 597 638 return current_user.vuid;
Note:
See TracChangeset
for help on using the changeset viewer.