diff options
Diffstat (limited to 'source3')
| -rw-r--r-- | source3/auth/pass_check.c | 2 | ||||
| -rw-r--r-- | source3/passdb/nispass.c | 2 | ||||
| -rw-r--r-- | source3/passdb/pass_check.c | 2 | ||||
| -rw-r--r-- | source3/printing/nt_printing.c | 13 | ||||
| -rw-r--r-- | source3/rpc_server/srv_netlog_nt.c | 2 | ||||
| -rw-r--r-- | source3/rpc_server/srv_pipe.c | 7 | ||||
| -rw-r--r-- | source3/rpc_server/srv_srvsvc_nt.c | 6 | ||||
| -rw-r--r-- | source3/smbd/blocking.c | 10 | ||||
| -rw-r--r-- | source3/smbd/notify_hash.c | 15 | ||||
| -rw-r--r-- | source3/smbd/oplock.c | 4 | ||||
| -rw-r--r-- | source3/smbd/password.c | 2 | ||||
| -rw-r--r-- | source3/smbd/process.c | 12 | ||||
| -rw-r--r-- | source3/smbd/sec_ctx.c | 4 | ||||
| -rw-r--r-- | source3/smbd/server.c | 9 | ||||
| -rw-r--r-- | source3/smbd/service.c | 58 | ||||
| -rw-r--r-- | source3/smbd/uid.c | 142 | 
16 files changed, 197 insertions, 93 deletions
diff --git a/source3/auth/pass_check.c b/source3/auth/pass_check.c index a57cb2ff06..44b3b9a237 100644 --- a/source3/auth/pass_check.c +++ b/source3/auth/pass_check.c @@ -233,7 +233,7 @@ static BOOL dfs_auth(char *user, char *password)  	}  	/* -	 * NB. I'd like to change these to call something like become_user() +	 * NB. I'd like to change these to call something like change_to_user()  	 * instead but currently we don't have a connection  	 * context to become the correct user. This is already  	 * fairly platform specific code however, so I think diff --git a/source3/passdb/nispass.c b/source3/passdb/nispass.c index 04b3765d59..a595cabb37 100644 --- a/source3/passdb/nispass.c +++ b/source3/passdb/nispass.c @@ -297,7 +297,7 @@ static BOOL make_sam_from_nisp_object(struct sam_passwd *pw_buf, nis_object *obj  	if (pw_buf->smb_name[strlen(pw_buf->smb_name)-1] != '$') {  	  /* XXXX hack to get standard_sub_basic() to use sam logon username */ -	  /* possibly a better way would be to do a become_user() call */ +	  /* possibly a better way would be to do a change_to_user() call */  	  pstrcpy(samlogon_user, pw_buf->smb_name);  	  sam_logon_in_ssb = True; diff --git a/source3/passdb/pass_check.c b/source3/passdb/pass_check.c index a57cb2ff06..44b3b9a237 100644 --- a/source3/passdb/pass_check.c +++ b/source3/passdb/pass_check.c @@ -233,7 +233,7 @@ static BOOL dfs_auth(char *user, char *password)  	}  	/* -	 * NB. I'd like to change these to call something like become_user() +	 * NB. I'd like to change these to call something like change_to_user()  	 * instead but currently we don't have a connection  	 * context to become the correct user. This is already  	 * fairly platform specific code however, so I think diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c index c61893e0fe..9b5f7379f5 100644 --- a/source3/printing/nt_printing.c +++ b/source3/printing/nt_printing.c @@ -944,7 +944,10 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,  	/* connect to the print$ share under the same account as the user connected to the rpc pipe */	  	/* Null password is ok - we are already an authenticated user... */  	*null_pw = '\0'; + +	become_root();  	conn = make_connection("print$", null_pw, 0, "A:", user->vuid, &nt_status); +	unbecome_root();  	if (conn == NULL) {  		DEBUG(0,("get_correct_cversion: Unable to connect\n")); @@ -952,13 +955,9 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,  		return -1;  	} -	/* Save who we are - we are temporarily becoming the connection user. */ -	push_sec_ctx(); -  	if (!become_user(conn, conn->vuid)) {  		DEBUG(0,("get_correct_cversion: Can't become user!\n"));  		*perr = WERR_ACCESS_DENIED; -		pop_sec_ctx();  		return -1;  	} @@ -1017,16 +1016,16 @@ static uint32 get_correct_cversion(fstring architecture, fstring driverpath_in,  	close_file(fsp, True);  	close_cnum(conn, user->vuid); -	pop_sec_ctx(); +	unbecome_user();  	return cversion; +  error_exit: -	error_exit:  	if(fsp)  		close_file(fsp, True);  	close_cnum(conn, user->vuid); -	pop_sec_ctx(); +	unbecome_user();  	return -1;  } diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 678c48ff71..7a7ff09d71 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -708,7 +708,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *  		usr_info->ptr_user_info = 0;  		/* XXXX hack to get standard_sub_basic() to use sam logon username */ -		/* possibly a better way would be to do a become_user() call */ +		/* possibly a better way would be to do a change_to_user() call */  		sam_logon_in_ssb = True;  		pstrcpy(samlogon_user, nt_username); diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 2957d7cc95..7079cc2ca1 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1135,7 +1135,6 @@ BOOL api_pipe_request(pipes_struct *p)  {  	int i = 0;  	BOOL ret = False; -	BOOL changed_user_id = False;  	if (p->ntlmssp_auth_validated) { @@ -1143,8 +1142,6 @@ BOOL api_pipe_request(pipes_struct *p)  			prs_mem_free(&p->out_data.rdata);  			return False;  		} - -		changed_user_id = True;  	}  	for (i = 0; api_fd_commands[i].pipe_clnt_name; i++) { @@ -1157,8 +1154,8 @@ BOOL api_pipe_request(pipes_struct *p)  		}  	} -	if(changed_user_id) -		unbecome_authenticated_pipe_user(p); +	if(p->ntlmssp_auth_validated) +		unbecome_authenticated_pipe_user();  	return ret;  } diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index 2ae4a73874..44e44cfa3a 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -1598,7 +1598,9 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE  	get_current_user(&user, p);	 +	become_root();  	conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status); +	unbecome_root();  	if (conn == NULL) {  		DEBUG(3,("_srv_net_file_query_secdesc: Unable to connect to %s\n", qualname)); @@ -1649,7 +1651,7 @@ NTSTATUS _srv_net_file_query_secdesc(pipes_struct *p, SRV_Q_NET_FILE_QUERY_SECDE  	psd->dacl->revision = (uint16) NT4_ACL_REVISION;  	close_file(fsp, True); - +	unbecome_user();  	close_cnum(conn, user.vuid);  	return r_u->status; @@ -1700,7 +1702,9 @@ NTSTATUS _srv_net_file_set_secdesc(pipes_struct *p, SRV_Q_NET_FILE_SET_SECDESC *  	get_current_user(&user, p);	 +	become_root();  	conn = make_connection(qualname, null_pw, 0, "A:", user.vuid, &nt_status); +	unbecome_root();  	if (conn == NULL) {  		DEBUG(3,("_srv_net_file_set_secdesc: Unable to connect to %s\n", qualname)); diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index a398a4c2a1..252ae6e0ea 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -582,7 +582,7 @@ void process_blocking_lock_queue(time_t t)        continue;      } -    if(!become_user(conn,vuid)) { +    if(!change_to_user(conn,vuid)) {        DEBUG(0,("process_blocking_lock_queue: Unable to become user vuid=%d.\n",              vuid ));        /* @@ -594,7 +594,7 @@ void process_blocking_lock_queue(time_t t)        continue;      } -    if(!become_service(conn,True)) { +    if(!set_current_service(conn,True)) {        DEBUG(0,("process_blocking_lock_queue: Unable to become service Error was %s.\n", strerror(errno) ));        /*         * Remove the entry and return an error to the client. @@ -602,7 +602,7 @@ void process_blocking_lock_queue(time_t t)        blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED);        free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));        blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); -      unbecome_user(); +      change_to_root_user();        continue;      } @@ -615,11 +615,11 @@ void process_blocking_lock_queue(time_t t)      if(blocking_lock_record_process(blr)) {        free_blocking_lock_record((blocking_lock_record *)ubi_slRemNext( &blocking_lock_queue, prev));        blr = (blocking_lock_record *)(prev ? ubi_slNext(prev) : ubi_slFirst(&blocking_lock_queue)); -      unbecome_user(); +      change_to_root_user();        continue;      } -    unbecome_user(); +    change_to_root_user();      /*       * Move to the next in the list. diff --git a/source3/smbd/notify_hash.c b/source3/smbd/notify_hash.c index 0c69dc7876..d398fac214 100644 --- a/source3/smbd/notify_hash.c +++ b/source3/smbd/notify_hash.c @@ -126,16 +126,19 @@ static void *hash_register_notify(connection_struct *conn, char *path, uint32 fl   Check if a change notify should be issued.   A time of zero means instantaneous check - don't modify the last check time.  *****************************************************************************/ +  static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path, uint32 flags, void *datap, time_t t)  {  	struct change_data *data = (struct change_data *)datap;  	struct change_data data2; -	if (t && t < data->last_check_time + lp_change_notify_timeout()) return False; +	if (t && t < data->last_check_time + lp_change_notify_timeout()) +		return False; -	if (!become_user(conn,vuid)) return True; -	if (!become_service(conn,True)) { -		unbecome_user(); +	if (!change_to_user(conn,vuid)) +		return True; +	if (!set_current_service(conn,True)) { +		change_to_root_user();  		return True;  	} @@ -144,14 +147,14 @@ static BOOL hash_check_notify(connection_struct *conn, uint16 vuid, char *path,  	    data2.status_time != data->status_time ||  	    data2.total_time != data->total_time ||  	    data2.num_entries != data->num_entries) { -		unbecome_user(); +		change_to_root_user();  		return True;  	}  	if (t)  		data->last_check_time = t; -	unbecome_user(); +	change_to_root_user();  	return False;  } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index 4e8e36b3aa..927719ac1a 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -750,7 +750,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B    saved_vuid = current_user.vuid;    saved_fsp_conn = fsp->conn;    vfs_GetWd(saved_fsp_conn,saved_dir); -  unbecome_user(); +  change_to_root_user();    /* Save the chain fnum. */    file_chain_save(); @@ -823,7 +823,7 @@ static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, struct timeval *tval, B     * Go back to being the user who requested the oplock     * break.     */ -  if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !become_user(saved_user_conn, saved_vuid)) +  if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid))    {      DEBUG( 0, ( "oplock_break: unable to re-become user!" ) );      DEBUGADD( 0, ( "Shutting down server\n" ) ); diff --git a/source3/smbd/password.c b/source3/smbd/password.c index b074552567..b1739d9bb6 100644 --- a/source3/smbd/password.c +++ b/source3/smbd/password.c @@ -244,7 +244,7 @@ int register_vuid(uid_t uid,gid_t gid, char *unix_name, char *requested_name,  	vuser->groups  = NULL;  	/* Find all the groups this uid is in and store them.  -		Used by become_user() */ +		Used by change_to_user() */  	initialise_groups(vuser->user.unix_name, vuser->uid, vuser->gid);  	get_current_groups( &vuser->n_groups, &vuser->groups); diff --git a/source3/smbd/process.c b/source3/smbd/process.c index cf691ce9f3..edcb6b345f 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -120,7 +120,7 @@ static void async_processing(fd_set *fds, char *buffer, int buffer_len)  	/* check for sighup processing */  	if (reload_after_sighup) { -		unbecome_user(); +		change_to_root_user();  		DEBUG(1,("Reloading services after SIGHUP\n"));  		reload_services(False);  		reload_after_sighup = False; @@ -702,7 +702,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize      /* does this protocol need to be run as root? */      if (!(flags & AS_USER)) -      unbecome_user(); +      change_to_root_user();      /* does this protocol need a valid tree connection? */      if ((flags & AS_USER) && !conn) { @@ -711,7 +711,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize      /* does this protocol need to be run as the connected user? */ -    if ((flags & AS_USER) && !become_user(conn,session_tag)) { +    if ((flags & AS_USER) && !change_to_user(conn,session_tag)) {        if (flags & AS_GUEST)           flags &= ~AS_USER;        else @@ -734,13 +734,13 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize      }      /* load service specific parameters */ -    if (conn && !become_service(conn,(flags & AS_USER)?True:False)) { +    if (conn && !set_current_service(conn,(flags & AS_USER)?True:False)) {        return(ERROR_DOS(ERRSRV,ERRaccess));      }      /* does this protocol need to be run as guest? */      if ((flags & AS_GUEST) &&  -		 (!become_guest() ||  +		 (!change_to_guest() ||   		!check_access(smbd_server_fd(), lp_hostsallow(-1), lp_hostsdeny(-1)))) {        return(ERROR_DOS(ERRSRV,ERRaccess));      } @@ -1096,7 +1096,7 @@ static BOOL timeout_processing(int deadtime, int *select_timeout, time_t *last_t      last_idle_closed_check = t;    /* become root again if waiting */ -  unbecome_user(); +  change_to_root_user();    /* check if we need to reload services */    check_reload(t); diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c index c053a611c2..cea39b82cb 100644 --- a/source3/smbd/sec_ctx.c +++ b/source3/smbd/sec_ctx.c @@ -59,10 +59,8 @@ static BOOL become_uid(uid_t uid)  	/* Set effective user id */  	set_effective_uid(uid); -	current_user.uid = uid;  	DO_PROFILE_INC(uid_changes); -  	return True;  } @@ -88,8 +86,6 @@ static BOOL become_gid(gid_t gid)  	/* Set effective group id */  	set_effective_gid(gid); -	current_user.gid = gid; -	  	return True;  } diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 579649cf0c..2e0fb1868d 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -247,7 +247,7 @@ max can be %d\n",  			/* check for sighup processing */  			if (reload_after_sighup) { -				unbecome_user(); +				change_to_root_user();  				DEBUG(1,("Reloading services after SIGHUP\n"));  				reload_services(False);  				reload_after_sighup = False; @@ -393,7 +393,7 @@ BOOL reload_services(BOOL test)  	reset_stat_cache();  	/* this forces service parameters to be flushed */ -	become_service(NULL,True); +	set_current_service(NULL,True);  	return(ret);  } @@ -479,10 +479,11 @@ void exit_server(char *reason)  	extern char *last_inbuf; -	if (!firsttime) exit(0); +	if (!firsttime) +		exit(0);  	firsttime = 0; -	unbecome_user(); +	change_to_root_user();  	DEBUG(2,("Closing connections\n"));  	conn_close_all(); diff --git a/source3/smbd/service.c b/source3/smbd/service.c index 6f2c28d19c..9e3f3c9f11 100644 --- a/source3/smbd/service.c +++ b/source3/smbd/service.c @@ -34,9 +34,10 @@ extern fstring remote_machine;  /**************************************************************************** -load parameters specific to a connection/service + Load parameters specific to a connection/service.  ****************************************************************************/ -BOOL become_service(connection_struct *conn,BOOL do_chdir) + +BOOL set_current_service(connection_struct *conn,BOOL do_chdir)  {  	extern char magic_char;  	static connection_struct *last_conn; @@ -315,10 +316,10 @@ static void set_admin_user(connection_struct *conn)  #endif  } -  /**************************************************************************** -  make a connection to a service + Make a connection to a service.  ****************************************************************************/ +  connection_struct *make_connection(char *service,char *password,   				   int pwlen, char *dev,uint16 vuid, NTSTATUS *status)  { @@ -327,10 +328,17 @@ connection_struct *make_connection(char *service,char *password,  	BOOL guest = False;  	BOOL force = False;  	connection_struct *conn; +	uid_t euid;  	fstring user;  	ZERO_STRUCT(user); +	/* This must ONLY BE CALLED AS ROOT. As it exits this function as root. */ +	if ((euid = geteuid()) != 0) { +		DEBUG(0,("make_connection: PANIC ERROR. Called as nonroot (%u)\n", (unsigned int)euid )); +		smb_panic("make_connection: PANIC ERROR. Called as nonroot\n"); +	} +  	strlower(service);  	snum = find_service(service); @@ -519,7 +527,7 @@ connection_struct *make_connection(char *service,char *password,  	conn->groups = NULL;  	/* Find all the groups this uid is in and -	   store them. Used by become_user() */ +	   store them. Used by change_to_user() */  	initialise_groups(conn->user, conn->uid, conn->gid);   	get_current_groups(&conn->ngroups,&conn->groups); @@ -557,16 +565,7 @@ connection_struct *make_connection(char *service,char *password,  		return NULL;  	} -	if (!become_user(conn, conn->vuid)) { -		/* No point continuing if they fail the basic checks */ -		DEBUG(0,("Can't become connected user!\n")); -		conn_free(conn); -		*status = NT_STATUS_LOGON_FAILURE; -		return NULL; -	} -  /* ROOT Activities: */	 -	become_root();  	/* check number of connections */  	if (!claim_connection(conn,  			      lp_servicename(SNUM(conn)), @@ -575,8 +574,6 @@ connection_struct *make_connection(char *service,char *password,  		DEBUG(1,("too many connections - rejected\n"));  		*status = NT_STATUS_INSUFFICIENT_RESOURCES;  		conn_free(conn); -		unbecome_root(); -		unbecome_user();  		return NULL;  	}   @@ -596,14 +593,19 @@ connection_struct *make_connection(char *service,char *password,  					 lp_max_connections(SNUM(conn)));  			conn_free(conn);  			*status = NT_STATUS_UNSUCCESSFUL; -			unbecome_root(); -			unbecome_user();  			return NULL;  		}  	} -	unbecome_root();  /* USER Activites: */ +	if (!change_to_user(conn, conn->vuid)) { +		/* No point continuing if they fail the basic checks */ +		DEBUG(0,("Can't become connected user!\n")); +		conn_free(conn); +		*status = NT_STATUS_LOGON_FAILURE; +		return NULL; +	} +  	/* Remember that a different vuid can connect later without these checks... */  	/* Preexecs are done here as they might make the dir we are to ChDir to below */ @@ -616,7 +618,7 @@ connection_struct *make_connection(char *service,char *password,  		ret = smbrun(cmd,NULL);  		if (ret != 0 && lp_preexec_close(SNUM(conn))) {  			DEBUG(1,("preexec gave %d - failing connection\n", ret)); -			unbecome_user(); +			change_to_root_user();  			yield_connection(conn, lp_servicename(SNUM(conn)), lp_max_connections(SNUM(conn)));  			conn_free(conn);  			*status = NT_STATUS_UNSUCCESSFUL; @@ -628,7 +630,7 @@ connection_struct *make_connection(char *service,char *password,  		DEBUG(0,("%s (%s) Can't change directory to %s (%s)\n",  			 remote_machine, conn->client_address,  			 conn->connectpath,strerror(errno))); -		unbecome_user(); +		change_to_root_user();  		yield_connection(conn,  				 lp_servicename(SNUM(conn)),  				 lp_max_connections(SNUM(conn))); @@ -677,14 +679,14 @@ connection_struct *make_connection(char *service,char *password,  		if (conn->vfs_ops.connect(conn, service, user) < 0) {  			DEBUG(0,("make_connection: VFS make connection failed!\n"));  			*status = NT_STATUS_UNSUCCESSFUL; -			unbecome_user(); +			change_to_root_user();  			conn_free(conn);  			return NULL;  		}  	} -	/* we've finished with the sensitive stuff */ -	unbecome_user(); +	/* we've finished with the user stuff - go back to root */ +	change_to_root_user();  	return(conn);  } @@ -697,7 +699,7 @@ void close_cnum(connection_struct *conn, uint16 vuid)  {  	DirCacheFlush(SNUM(conn)); -	unbecome_user(); +	change_to_root_user();  	DEBUG(IS_IPC(conn)?3:1, ("%s (%s) closed connection to service %s\n",  				 remote_machine,conn->client_address, @@ -720,15 +722,15 @@ void close_cnum(connection_struct *conn, uint16 vuid)  	/* execute any "postexec = " line */  	if (*lp_postexec(SNUM(conn)) &&  -	    become_user(conn, vuid))  { +	    change_to_user(conn, vuid))  {  		pstring cmd;  		pstrcpy(cmd,lp_postexec(SNUM(conn)));  		standard_sub_conn(conn,cmd);  		smbrun(cmd,NULL); -		unbecome_user(); +		change_to_root_user();  	} -	unbecome_user(); +	change_to_root_user();  	/* execute any "root postexec = " line */  	if (*lp_rootpostexec(SNUM(conn)))  {  		pstring cmd; diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c index 39bdaaa596..b1012c3c91 100644 --- a/source3/smbd/uid.c +++ b/source3/smbd/uid.c @@ -25,10 +25,10 @@  extern struct current_user current_user;  /**************************************************************************** - Become the guest user. + Become the guest user without changing the security context stack.  ****************************************************************************/ -BOOL become_guest(void) +BOOL change_to_guest(void)  {  	static struct passwd *pass=NULL;  	static uid_t guest_uid = (uid_t)-1; @@ -82,10 +82,11 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)  }  /**************************************************************************** - Become the user of a connection number. + Become the user of a connection number without changing the security context + stack, but modify the currnet_user entries.  ****************************************************************************/ -BOOL become_user(connection_struct *conn, uint16 vuid) +BOOL change_to_user(connection_struct *conn, uint16 vuid)  {  	user_struct *vuser = get_valid_user_struct(vuid);  	int snum; @@ -96,7 +97,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid)  	NT_USER_TOKEN *token = NULL;  	if (!conn) { -		DEBUG(2,("Connection not open\n")); +		DEBUG(2,("change_to_user: Connection not open\n"));  		return(False);  	} @@ -109,12 +110,12 @@ BOOL become_user(connection_struct *conn, uint16 vuid)  	if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&  	   (current_user.uid == conn->uid)) { -		DEBUG(4,("Skipping become_user - already user\n")); +		DEBUG(4,("change_to_user: Skipping user change - already user\n"));  		return(True);  	} else if ((current_user.conn == conn) &&   		   (vuser != 0) && (current_user.vuid == vuid) &&   		   (current_user.uid == vuser->uid)) { -		DEBUG(4,("Skipping become_user - already user\n")); +		DEBUG(4,("change_to_user: Skipping user change - already user\n"));  		return(True);  	} @@ -133,7 +134,7 @@ BOOL become_user(connection_struct *conn, uint16 vuid)  		token = conn->nt_user_token;  	} else {  		if (!vuser) { -			DEBUG(2,("Invalid vuid used %d\n",vuid)); +			DEBUG(2,("change_to_user: Invalid vuid used %d\n",vuid));  			return(False);  		}  		uid = vuser->uid; @@ -196,21 +197,22 @@ BOOL become_user(connection_struct *conn, uint16 vuid)  	current_user.conn = conn;  	current_user.vuid = vuid; -	DEBUG(5,("become_user uid=(%d,%d) gid=(%d,%d)\n", +	DEBUG(5,("change_to_user uid=(%d,%d) gid=(%d,%d)\n",  		 (int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));  	return(True);  }  /**************************************************************************** - Unbecome the user of a connection number. + Go back to being root without changing the security context stack, + but modify the current_user entries.  ****************************************************************************/ -BOOL unbecome_user(void ) +BOOL change_to_root_user(void)  {  	set_root_sec_ctx(); -	DEBUG(5,("unbecome_user now uid=(%d,%d) gid=(%d,%d)\n", +	DEBUG(5,("change_to_root_user: now uid=(%d,%d) gid=(%d,%d)\n",  		(int)getuid(),(int)geteuid(),(int)getgid(),(int)getegid()));  	current_user.conn = NULL; @@ -222,16 +224,13 @@ BOOL unbecome_user(void )  /****************************************************************************   Become the user of an authenticated connected named pipe.   When this is called we are currently running as the connection - user. + user. Doesn't modify current_user.  ****************************************************************************/  BOOL become_authenticated_pipe_user(pipes_struct *p)  { -	BOOL res = push_sec_ctx(); - -	if (!res) { +	if (!push_sec_ctx())  		return False; -	}  	set_sec_ctx(p->pipe_user.uid, p->pipe_user.gid,   		    p->pipe_user.ngroups, p->pipe_user.groups, p->pipe_user.nt_user_token); @@ -242,19 +241,93 @@ BOOL become_authenticated_pipe_user(pipes_struct *p)  /****************************************************************************   Unbecome the user of an authenticated connected named pipe.   When this is called we are running as the authenticated pipe - user and need to go back to being the connection user. + user and need to go back to being the connection user. Doesn't modify + current_user.  ****************************************************************************/ -BOOL unbecome_authenticated_pipe_user(pipes_struct *p) +BOOL unbecome_authenticated_pipe_user(void)  {  	return pop_sec_ctx();  } -/* Temporarily become a root user.  Must match with unbecome_root(). */ +/**************************************************************************** + Utility functions used by become_xxx/unbecome_xxx. +****************************************************************************/ + +struct conn_ctx { +	connection_struct *conn; +	uint16 vuid; +}; +  +/* A stack of current_user connection contexts. */ +  +static struct conn_ctx conn_ctx_stack[MAX_SEC_CTX_DEPTH]; +static int conn_ctx_stack_ndx; + +static void push_conn_ctx(void) +{ +	struct conn_ctx *ctx_p; +  +	/* Check we don't overflow our stack */ +  +	if (conn_ctx_stack_ndx == MAX_SEC_CTX_DEPTH) { +		DEBUG(0, ("Connection context stack overflow!\n")); +		smb_panic("Connection context stack overflow!\n"); +	} +  +	/* Store previous user context */ +	ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx]; +  +	ctx_p->conn = current_user.conn; +	ctx_p->vuid = current_user.vuid; +  +	DEBUG(3, ("push_conn_ctx(%u) : conn_ctx_stack_ndx = %d\n", +		(unsigned int)ctx_p->vuid, conn_ctx_stack_ndx )); + +	conn_ctx_stack_ndx++; +} + +static void pop_conn_ctx(void) +{ +	struct conn_ctx *ctx_p; +  +	/* Check for stack underflow. */ + +	if (conn_ctx_stack_ndx == 0) { +		DEBUG(0, ("Connection context stack underflow!\n")); +		smb_panic("Connection context stack underflow!\n"); +	} + +	conn_ctx_stack_ndx--; +	ctx_p = &conn_ctx_stack[conn_ctx_stack_ndx]; + +	current_user.conn = ctx_p->conn; +	current_user.vuid = ctx_p->vuid; + +	ctx_p->conn = NULL; +	ctx_p->vuid = UID_FIELD_INVALID; +} + +void init_conn_ctx(void) +{ +    int i; +  +    /* Initialise connection context stack */ +	for (i = 0; i < MAX_SEC_CTX_DEPTH; i++) { +		conn_ctx_stack[i].conn = NULL; +		conn_ctx_stack[i].vuid = UID_FIELD_INVALID; +    } +} + +/**************************************************************************** + Temporarily become a root user.  Must match with unbecome_root(). Saves and + restores the connection context. +****************************************************************************/  void become_root(void)  {  	push_sec_ctx(); +	push_conn_ctx();  	set_root_sec_ctx();  } @@ -263,6 +336,35 @@ void become_root(void)  void unbecome_root(void)  {  	pop_sec_ctx(); +	pop_conn_ctx(); +} + +/**************************************************************************** + Push the current security context then force a change via change_to_user(). + Saves and restores the connection context. +****************************************************************************/ + +BOOL become_user(connection_struct *conn, uint16 vuid) +{ +	if (!push_sec_ctx()) +		return False; + +	push_conn_ctx(); + +	if (!change_to_user(conn, vuid)) { +		pop_sec_ctx(); +		pop_conn_ctx(); +		return False; +	} + +	return True; +} + +BOOL unbecome_user() +{ +	pop_sec_ctx(); +	pop_conn_ctx(); +	return True;  }  /*****************************************************************  | 
