static void display_window(TALLOC_CTX *mem_ctx, struct registry_context *ctx)
{
	struct regedit *regedit;
	struct tree_node *root;
	bool colors;
	int key;

	initscr();

	cbreak();
	noecho();

	fault_configure(regedit_panic_handler);

	colors = has_colors();
	if (colors) {
		start_color();
		use_default_colors();
		assume_default_colors(COLOR_WHITE, COLOR_BLUE);
		init_pair(PAIR_YELLOW_CYAN, COLOR_YELLOW, COLOR_CYAN);
		init_pair(PAIR_BLACK_CYAN, COLOR_BLACK, COLOR_CYAN);
		init_pair(PAIR_YELLOW_BLUE, COLOR_YELLOW, COLOR_BLUE);
	}

	regedit = talloc_zero(mem_ctx, struct regedit);
	SMB_ASSERT(regedit != NULL);
	regedit_main = regedit;

	regedit->registry_context = ctx;
	regedit->main_window = stdscr;
	keypad(regedit->main_window, TRUE);

	mvwprintw(regedit->main_window, 0, 0, "Path: ");
	regedit->path_label = newpad(1, PATH_WIDTH_MAX);
	SMB_ASSERT(regedit->path_label);
	wprintw(regedit->path_label, "/");
	show_path(regedit_main);

	root = tree_node_new_root(regedit, ctx);
	SMB_ASSERT(root != NULL);

	regedit->keys = tree_view_new(regedit, root, KEY_HEIGHT, KEY_WIDTH,
				      KEY_START_Y, KEY_START_X);
	SMB_ASSERT(regedit->keys != NULL);

	regedit->vl = value_list_new(regedit, VAL_HEIGHT, VAL_WIDTH,
				     VAL_START_Y, VAL_START_X);
	SMB_ASSERT(regedit->vl != NULL);

	regedit->tree_input = true;
	print_heading(regedit);

	tree_view_show(regedit->keys);
	load_values(regedit);
	value_list_show(regedit->vl);

	update_panels();
	doupdate();

	do {
		key = regedit_getch();

		handle_main_input(regedit, key);
		update_panels();
		doupdate();
	} while (key != 'q' || key == 'Q');

	endwin();
}
Exemplo n.º 2
0
/**
* @brief Check authentication for request/response packets
*
* @param auth		The auth data for the connection
* @param pkt		The actual ncacn_packet
* @param pkt_trailer [in][out]	The stub_and_verifier part of the packet,
* 			the auth_trailer and padding will be removed.
* @param header_size	The header size
* @param raw_pkt	The whole raw packet data blob
*
* @return A NTSTATUS error code
*/
NTSTATUS dcerpc_check_auth(struct pipe_auth_data *auth,
			   struct ncacn_packet *pkt,
			   DATA_BLOB *pkt_trailer,
			   uint8_t header_size,
			   DATA_BLOB *raw_pkt)
{
	struct gensec_security *gensec_security;
	NTSTATUS status;
	struct dcerpc_auth auth_info;
	uint32_t auth_length;
	DATA_BLOB full_pkt;
	DATA_BLOB data;

	/*
	 * These check should be done in the caller.
	 */
	SMB_ASSERT(raw_pkt->length == pkt->frag_length);
	SMB_ASSERT(header_size <= pkt->frag_length);
	SMB_ASSERT(pkt_trailer->length < pkt->frag_length);
	SMB_ASSERT((pkt_trailer->length + header_size) <= pkt->frag_length);

	switch (auth->auth_level) {
	case DCERPC_AUTH_LEVEL_PRIVACY:
		DEBUG(10, ("Requested Privacy.\n"));
		break;

	case DCERPC_AUTH_LEVEL_INTEGRITY:
		DEBUG(10, ("Requested Integrity.\n"));
		break;

	case DCERPC_AUTH_LEVEL_CONNECT:
		if (pkt->auth_length != 0) {
			break;
		}
		return NT_STATUS_OK;

	case DCERPC_AUTH_LEVEL_NONE:
		if (pkt->auth_length != 0) {
			DEBUG(3, ("Got non-zero auth len on non "
				  "authenticated connection!\n"));
			return NT_STATUS_INVALID_PARAMETER;
		}
		return NT_STATUS_OK;

	default:
		DEBUG(3, ("Unimplemented Auth Level %d",
			  auth->auth_level));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (pkt->auth_length == 0) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	status = dcerpc_pull_auth_trailer(pkt, pkt, pkt_trailer,
					  &auth_info, &auth_length, false);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	if (auth_info.auth_type != auth->auth_type) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (auth_info.auth_level != auth->auth_level) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (auth_info.auth_context_id != auth->auth_context_id) {
		return NT_STATUS_INVALID_PARAMETER;
	}

	pkt_trailer->length -= auth_length;
	data = data_blob_const(raw_pkt->data + header_size,
			       pkt_trailer->length);
	full_pkt = data_blob_const(raw_pkt->data, raw_pkt->length);
	full_pkt.length -= auth_info.credentials.length;

	switch (auth->auth_type) {
	case DCERPC_AUTH_TYPE_NONE:
		return NT_STATUS_OK;

	default:
		DEBUG(10, ("GENSEC auth\n"));

		gensec_security = auth->auth_ctx;
		status = get_generic_auth_footer(gensec_security,
						 auth->auth_level,
						 &data, &full_pkt,
						 &auth_info.credentials);
		if (!NT_STATUS_IS_OK(status)) {
			return status;
		}
		break;
	}

	/* TODO: remove later
	 * this is still needed because in the server code the
	 * pkt_trailer actually has a copy of the raw data, and they
	 * are still both used in later calls */
	if (auth->auth_level == DCERPC_AUTH_LEVEL_PRIVACY) {
		if (pkt_trailer->length != data.length) {
			return NT_STATUS_INVALID_PARAMETER;
		}
		memcpy(pkt_trailer->data, data.data, data.length);
	}

	pkt_trailer->length -= auth_info.auth_pad_length;
	data_blob_free(&auth_info.credentials);
	return NT_STATUS_OK;
}
Exemplo n.º 3
0
Arquivo: auth.c Projeto: aosm/samba
static const uint8 *get_ntlm_challenge(struct auth_context *auth_context) 
{
	DATA_BLOB challenge = data_blob(NULL, 0);
	const char *challenge_set_by = NULL;
	auth_methods *auth_method;
	TALLOC_CTX *mem_ctx;

	if (auth_context->challenge.length) {
		DEBUG(5, ("get_ntlm_challenge (auth subsystem): returning previous challenge by module %s (normal)\n", 
			  auth_context->challenge_set_by));
		return auth_context->challenge.data;
	}

	auth_context->challenge_may_be_modified = False;

	for (auth_method = auth_context->auth_method_list; auth_method; auth_method = auth_method->next) {
		if (auth_method->get_chal == NULL) {
			DEBUG(5, ("auth_get_challenge: module %s did not want to specify a challenge\n", auth_method->name));
			continue;
		}

		DEBUG(5, ("auth_get_challenge: getting challenge from module %s\n", auth_method->name));
		if (challenge_set_by != NULL) {
			DEBUG(1, ("auth_get_challenge: CONFIGURATION ERROR: authentication method %s has already specified a challenge.  Challenge by %s ignored.\n", 
				  challenge_set_by, auth_method->name));
			continue;
		}

		mem_ctx = talloc_init("auth_get_challenge for module %s", auth_method->name);
		if (!mem_ctx) {
			smb_panic("talloc_init() failed!");
		}
		
		challenge = auth_method->get_chal(auth_context, &auth_method->private_data, mem_ctx);
		if (!challenge.length) {
			DEBUG(3, ("auth_get_challenge: getting challenge from authentication method %s FAILED.\n", 
				  auth_method->name));
		} else {
			DEBUG(5, ("auth_get_challenge: sucessfully got challenge from module %s\n", auth_method->name));
			auth_context->challenge = challenge;
			challenge_set_by = auth_method->name;
			auth_context->challenge_set_method = auth_method;
		}
		talloc_destroy(mem_ctx);
	}
	
	if (!challenge_set_by) {
		uchar chal[8];
		
		generate_random_buffer(chal, sizeof(chal));
		auth_context->challenge = data_blob_talloc(auth_context->mem_ctx, 
							   chal, sizeof(chal));
		
		challenge_set_by = "random";
		auth_context->challenge_may_be_modified = True;
	} 
	
	DEBUG(5, ("auth_context challenge created by %s\n", challenge_set_by));
	DEBUG(5, ("challenge is: \n"));
	dump_data(5, (const char *)auth_context->challenge.data, auth_context->challenge.length);
	
	SMB_ASSERT(auth_context->challenge.length == 8);

	auth_context->challenge_set_by=challenge_set_by;

	return auth_context->challenge.data;
}
Exemplo n.º 4
0
static NTSTATUS rmdir_internals(TALLOC_CTX *ctx, files_struct *fsp)
{
	connection_struct *conn = fsp->conn;
	struct smb_filename *smb_dname = fsp->fsp_name;
	int ret;

	SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));

	/* Might be a symlink. */
	if(SMB_VFS_LSTAT(conn, smb_dname) != 0) {
		return map_nt_error_from_unix(errno);
	}

	if (S_ISLNK(smb_dname->st.st_ex_mode)) {
		/* Is what it points to a directory ? */
		if(SMB_VFS_STAT(conn, smb_dname) != 0) {
			return map_nt_error_from_unix(errno);
		}
		if (!(S_ISDIR(smb_dname->st.st_ex_mode))) {
			return NT_STATUS_NOT_A_DIRECTORY;
		}
		ret = SMB_VFS_UNLINK(conn, smb_dname);
	} else {
		ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
	}
	if (ret == 0) {
		notify_fname(conn, NOTIFY_ACTION_REMOVED,
			     FILE_NOTIFY_CHANGE_DIR_NAME,
			     smb_dname->base_name);
		return NT_STATUS_OK;
	}

	if(((errno == ENOTEMPTY)||(errno == EEXIST)) && *lp_veto_files(talloc_tos(), SNUM(conn))) {
		/*
		 * Check to see if the only thing in this directory are
		 * vetoed files/directories. If so then delete them and
		 * retry. If we fail to delete any of them (and we *don't*
		 * do a recursive delete) then fail the rmdir.
		 */
		SMB_STRUCT_STAT st;
		const char *dname = NULL;
		char *talloced = NULL;
		long dirpos = 0;
		struct smb_Dir *dir_hnd = OpenDir(talloc_tos(), conn,
						  smb_dname->base_name, NULL,
						  0);

		if(dir_hnd == NULL) {
			errno = ENOTEMPTY;
			goto err;
		}

		while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
					    &talloced)) != NULL) {
			if((strcmp(dname, ".") == 0) || (strcmp(dname, "..")==0)) {
				TALLOC_FREE(talloced);
				continue;
			}
			if (!is_visible_file(conn, smb_dname->base_name, dname,
					     &st, false)) {
				TALLOC_FREE(talloced);
				continue;
			}
			if(!IS_VETO_PATH(conn, dname)) {
				TALLOC_FREE(dir_hnd);
				TALLOC_FREE(talloced);
				errno = ENOTEMPTY;
				goto err;
			}
			TALLOC_FREE(talloced);
		}

		/* We only have veto files/directories.
		 * Are we allowed to delete them ? */

		if(!lp_delete_veto_files(SNUM(conn))) {
			TALLOC_FREE(dir_hnd);
			errno = ENOTEMPTY;
			goto err;
		}

		/* Do a recursive delete. */
		RewindDir(dir_hnd,&dirpos);
		while ((dname = ReadDirName(dir_hnd, &dirpos, &st,
					    &talloced)) != NULL) {
			struct smb_filename *smb_dname_full = NULL;
			char *fullname = NULL;
			bool do_break = true;

			if (ISDOT(dname) || ISDOTDOT(dname)) {
				TALLOC_FREE(talloced);
				continue;
			}
			if (!is_visible_file(conn, smb_dname->base_name, dname,
					     &st, false)) {
				TALLOC_FREE(talloced);
				continue;
			}

			fullname = talloc_asprintf(ctx,
					"%s/%s",
					smb_dname->base_name,
					dname);

			if(!fullname) {
				errno = ENOMEM;
				goto err_break;
			}

			smb_dname_full = synthetic_smb_fname(
				talloc_tos(), fullname, NULL, NULL);
			if (smb_dname_full == NULL) {
				errno = ENOMEM;
				goto err_break;
			}

			if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
				goto err_break;
			}
			if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
				if(!recursive_rmdir(ctx, conn,
						    smb_dname_full)) {
					goto err_break;
				}
				if(SMB_VFS_RMDIR(conn,
					smb_dname_full->base_name) != 0) {
					goto err_break;
				}
			} else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
				goto err_break;
			}

			/* Successful iteration. */
			do_break = false;

		 err_break:
			TALLOC_FREE(fullname);
			TALLOC_FREE(smb_dname_full);
			TALLOC_FREE(talloced);
			if (do_break)
				break;
		}
		TALLOC_FREE(dir_hnd);
		/* Retry the rmdir */
		ret = SMB_VFS_RMDIR(conn, smb_dname->base_name);
	}

  err:

	if (ret != 0) {
		DEBUG(3,("rmdir_internals: couldn't remove directory %s : "
			 "%s\n", smb_fname_str_dbg(smb_dname),
			 strerror(errno)));
		return map_nt_error_from_unix(errno);
	}

	notify_fname(conn, NOTIFY_ACTION_REMOVED,
		     FILE_NOTIFY_CHANGE_DIR_NAME,
		     smb_dname->base_name);

	return NT_STATUS_OK;
}
Exemplo n.º 5
0
static int copy_files(void)
{
	uint8_t *	iobuf;	/* IO buffer. */
	uint64_t	iomax;	/* Size of the IO buffer. */
	uint64_t	data_size; /* Amount of data in the IO buffer. */

	uint64_t	ibs;
	uint64_t	obs;
	uint64_t	count;

	struct dd_iohandle *	ifile;
	struct dd_iohandle *	ofile;

	ibs = check_arg_numeric("ibs");
	obs = check_arg_numeric("obs");
	count = check_arg_numeric("count");

	/* Allocate IO buffer. We need more than the max IO size because we
	 * could accumulate a remainder if ibs and obs don't match.
	 */
	iomax = 2 * MAX(ibs, obs);
	if ((iobuf = malloc(iomax)) == NULL) {
		fprintf(stderr,
			"%s: failed to allocate IO buffer of %llu bytes\n",
			PROGNAME, (unsigned long long)iomax);
		return(EOM_EXIT_CODE);
	}

	set_max_xmit(MAX(ibs, obs));

	DEBUG(4, ("IO buffer size is %llu, max xmit is %d\n",
			(unsigned long long)iomax, lp_max_xmit()));

	if (!(ifile = open_file("if"))) {
		return(FILESYS_EXIT_CODE);
	}

	if (!(ofile = open_file("of"))) {
		return(FILESYS_EXIT_CODE);
	}

	/* Seek the files to their respective starting points. */
	ifile->io_seek(ifile, check_arg_numeric("skip") * ibs);
	ofile->io_seek(ofile, check_arg_numeric("seek") * obs);

	DEBUG(4, ("max xmit was negotiated to be %d\n", lp_max_xmit()));

	for (data_size = 0;;) {

		/* Handle signals. We are somewhat compatible with GNU dd.
		 * SIGINT makes us stop, but still print transfer statistics.
		 * SIGUSR1 makes us print transfer statistics but we continue
		 * copying.
		 */
		if (dd_sigint) {
			break;
		}

		if (dd_sigusr1) {
			print_transfer_stats();
			dd_sigusr1 = 0;
		}

		if (ifile->io_flags & DD_END_OF_FILE) {
			DEBUG(4, ("flushing %llu bytes at EOF\n",
					(unsigned long long)data_size));
			while (data_size > 0) {
				if (!dd_flush_block(ofile, iobuf,
							&data_size, obs)) {
					return(IOERROR_EXIT_CODE);
				}
			}
			goto done;
		}

		/* Try and read enough blocks of ibs bytes to be able write
		 * out one of obs bytes.
		 */
		if (!dd_fill_block(ifile, iobuf, &data_size, obs, ibs)) {
			return(IOERROR_EXIT_CODE);
		}

		if (data_size == 0) {
			/* Done. */
			SMB_ASSERT(ifile->io_flags & DD_END_OF_FILE);
		}

		/* Stop reading when we hit the block count. */
		if (dd_stats.in.bytes >= (ibs * count)) {
			ifile->io_flags |= DD_END_OF_FILE;
		}

		/* If we wanted to be a legitimate dd, we would do character
		 * conversions and other shenanigans here.
		 */

		/* Flush what we read in units of obs bytes. We want to have
		 * at least obs bytes in the IO buffer but might not if the
		 * file is too small.
		 */
		if (data_size && 
		    !dd_flush_block(ofile, iobuf, &data_size, obs)) {
			return(IOERROR_EXIT_CODE);
		}
	}

done:
	print_transfer_stats();
	return(0);
}
Exemplo n.º 6
0
/* call-back function processing the NT acl -> ZFS acl using NFSv4 conv. */
static bool zfs_process_smbacl(files_struct *fsp, SMB4ACL_T *smbacl)
{
	int naces = smb_get_naces(smbacl), i;
	ace_t *acebuf;
	SMB4ACE_T *smbace;
	TALLOC_CTX	*mem_ctx;
	bool have_special_id = false;

	/* allocate the field of ZFS aces */
	mem_ctx = talloc_tos();
	acebuf = (ace_t *) talloc_size(mem_ctx, sizeof(ace_t)*naces);
	if(acebuf == NULL) {
		errno = ENOMEM;
		return False;
	}
	/* handle all aces */
	for(smbace = smb_first_ace4(smbacl), i = 0;
			smbace!=NULL;
			smbace = smb_next_ace4(smbace), i++) {
		SMB_ACE4PROP_T *aceprop = smb_get_ace4(smbace);

		acebuf[i].a_type        = aceprop->aceType;
		acebuf[i].a_flags       = aceprop->aceFlags;
		acebuf[i].a_access_mask = aceprop->aceMask;
		/* SYNC on acls is a no-op on ZFS.
		   See bug #7909. */
		acebuf[i].a_access_mask &= ~SMB_ACE4_SYNCHRONIZE;
		acebuf[i].a_who         = aceprop->who.id;
		if(aceprop->flags & SMB_ACE4_ID_SPECIAL) {
			switch(aceprop->who.special_id) {
			case SMB_ACE4_WHO_EVERYONE:
				acebuf[i].a_flags |= ACE_EVERYONE;
				break;
			case SMB_ACE4_WHO_OWNER:
				acebuf[i].a_flags |= ACE_OWNER;
				break;
			case SMB_ACE4_WHO_GROUP:
				acebuf[i].a_flags |= ACE_GROUP;
				break;
			default:
				DEBUG(8, ("unsupported special_id %d\n", \
					aceprop->who.special_id));
				continue; /* don't add it !!! */
			}
			have_special_id = true;
		}
	}

	if (!have_special_id
	    && lp_parm_bool(fsp->conn->params->service, "zfsacl",
			    "denymissingspecial", false)) {
		errno = EACCES;
		return false;
	}

	SMB_ASSERT(i == naces);

	/* store acl */
	if(acl(fsp->fsp_name->base_name, ACE_SETACL, naces, acebuf)) {
		if(errno == ENOSYS) {
			DEBUG(9, ("acl(ACE_SETACL, %s): Operation is not "
				  "supported on the filesystem where the file "
				  "reside", fsp_str_dbg(fsp)));
		} else {
			DEBUG(9, ("acl(ACE_SETACL, %s): %s ", fsp_str_dbg(fsp),
				  strerror(errno)));
		}
		return 0;
	}

	return True;
}
Exemplo n.º 7
0
static NTSTATUS close_remove_share_mode(files_struct *fsp,
					enum file_close_type close_type)
{
	connection_struct *conn = fsp->conn;
	struct server_id self = messaging_server_id(conn->sconn->msg_ctx);
	bool delete_file = false;
	bool changed_user = false;
	struct share_mode_lock *lck = NULL;
	NTSTATUS status = NT_STATUS_OK;
	NTSTATUS tmp_status;
	struct file_id id;
	const struct security_unix_token *del_token = NULL;
	const struct security_token *del_nt_token = NULL;
	bool got_tokens = false;
	bool normal_close;
	int ret_flock;

	/* Ensure any pending write time updates are done. */
	if (fsp->update_write_time_event) {
		update_write_time_handler(fsp->conn->sconn->ev_ctx,
					fsp->update_write_time_event,
					timeval_current(),
					(void *)fsp);
	}

	/*
	 * Lock the share entries, and determine if we should delete
	 * on close. If so delete whilst the lock is still in effect.
	 * This prevents race conditions with the file being created. JRA.
	 */

	lck = get_existing_share_mode_lock(talloc_tos(), fsp->file_id);
	if (lck == NULL) {
		DEBUG(0, ("close_remove_share_mode: Could not get share mode "
			  "lock for file %s\n", fsp_str_dbg(fsp)));
		return NT_STATUS_INVALID_PARAMETER;
	}

	if (fsp->write_time_forced) {
		DEBUG(10,("close_remove_share_mode: write time forced "
			"for file %s\n",
			fsp_str_dbg(fsp)));
		set_close_write_time(fsp, lck->data->changed_write_time);
	} else if (fsp->update_write_time_on_close) {
		/* Someone had a pending write. */
		if (null_timespec(fsp->close_write_time)) {
			DEBUG(10,("close_remove_share_mode: update to current time "
				"for file %s\n",
				fsp_str_dbg(fsp)));
			/* Update to current time due to "normal" write. */
			set_close_write_time(fsp, timespec_current());
		} else {
			DEBUG(10,("close_remove_share_mode: write time pending "
				"for file %s\n",
				fsp_str_dbg(fsp)));
			/* Update to time set on close call. */
			set_close_write_time(fsp, fsp->close_write_time);
		}
	}

	if (fsp->initial_delete_on_close &&
			!is_delete_on_close_set(lck, fsp->name_hash)) {
		bool became_user = False;

		/* Initial delete on close was set and no one else
		 * wrote a real delete on close. */

		if (get_current_vuid(conn) != fsp->vuid) {
			become_user(conn, fsp->vuid);
			became_user = True;
		}
		fsp->delete_on_close = true;
		set_delete_on_close_lck(fsp, lck,
				get_current_nttok(conn),
				get_current_utok(conn));
		if (became_user) {
			unbecome_user();
		}
	}

	delete_file = is_delete_on_close_set(lck, fsp->name_hash);

	if (delete_file) {
		int i;
		/* See if others still have the file open via this pathname.
		   If this is the case, then don't delete. If all opens are
		   POSIX delete now. */
		for (i=0; i<lck->data->num_share_modes; i++) {
			struct share_mode_entry *e = &lck->data->share_modes[i];

			if (!is_valid_share_mode_entry(e)) {
				continue;
			}
			if (e->name_hash != fsp->name_hash) {
				continue;
			}
			if ((fsp->posix_flags & FSP_POSIX_FLAGS_OPEN)
			    && (e->flags & SHARE_MODE_FLAG_POSIX_OPEN)) {
				continue;
			}
			if (serverid_equal(&self, &e->pid) &&
			    (e->share_file_id == fsp->fh->gen_id)) {
				continue;
			}
			if (share_mode_stale_pid(lck->data, i)) {
				continue;
			}
			delete_file = False;
			break;
		}
	}

	/*
	 * NT can set delete_on_close of the last open
	 * reference to a file.
	 */

	normal_close = (close_type == NORMAL_CLOSE || close_type == SHUTDOWN_CLOSE);

	if (!normal_close || !delete_file) {
		status = NT_STATUS_OK;
		goto done;
	}

	/*
	 * Ok, we have to delete the file
	 */

	DEBUG(5,("close_remove_share_mode: file %s. Delete on close was set "
		 "- deleting file.\n", fsp_str_dbg(fsp)));

	/*
	 * Don't try to update the write time when we delete the file
	 */
	fsp->update_write_time_on_close = false;

	got_tokens = get_delete_on_close_token(lck, fsp->name_hash,
					&del_nt_token, &del_token);
	SMB_ASSERT(got_tokens);

	if (!unix_token_equal(del_token, get_current_utok(conn))) {
		/* Become the user who requested the delete. */

		DEBUG(5,("close_remove_share_mode: file %s. "
			"Change user to uid %u\n",
			fsp_str_dbg(fsp),
			(unsigned int)del_token->uid));

		if (!push_sec_ctx()) {
			smb_panic("close_remove_share_mode: file %s. failed to push "
				  "sec_ctx.\n");
		}

		set_sec_ctx(del_token->uid,
			    del_token->gid,
			    del_token->ngroups,
			    del_token->groups,
			    del_nt_token);

		changed_user = true;
	}

	/* We can only delete the file if the name we have is still valid and
	   hasn't been renamed. */

	tmp_status = vfs_stat_fsp(fsp);
	if (!NT_STATUS_IS_OK(tmp_status)) {
		DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
			 "was set and stat failed with error %s\n",
			 fsp_str_dbg(fsp), nt_errstr(tmp_status)));
		/*
		 * Don't save the errno here, we ignore this error
		 */
		goto done;
	}

	id = vfs_file_id_from_sbuf(conn, &fsp->fsp_name->st);

	if (!file_id_equal(&fsp->file_id, &id)) {
		DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
			 "was set and dev and/or inode does not match\n",
			 fsp_str_dbg(fsp)));
		DEBUG(5,("close_remove_share_mode: file %s. stored file_id %s, "
			 "stat file_id %s\n",
			 fsp_str_dbg(fsp),
			 file_id_string_tos(&fsp->file_id),
			 file_id_string_tos(&id)));
		/*
		 * Don't save the errno here, we ignore this error
		 */
		goto done;
	}

	if ((conn->fs_capabilities & FILE_NAMED_STREAMS)
	    && !is_ntfs_stream_smb_fname(fsp->fsp_name)) {

		status = delete_all_streams(conn, fsp->fsp_name->base_name);

		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(5, ("delete_all_streams failed: %s\n",
				  nt_errstr(status)));
			goto done;
		}
	}


	if (SMB_VFS_UNLINK(conn, fsp->fsp_name) != 0) {
		/*
		 * This call can potentially fail as another smbd may
		 * have had the file open with delete on close set and
		 * deleted it when its last reference to this file
		 * went away. Hence we log this but not at debug level
		 * zero.
		 */

		DEBUG(5,("close_remove_share_mode: file %s. Delete on close "
			 "was set and unlink failed with error %s\n",
			 fsp_str_dbg(fsp), strerror(errno)));

		status = map_nt_error_from_unix(errno);
	}

	/* As we now have POSIX opens which can unlink
 	 * with other open files we may have taken
 	 * this code path with more than one share mode
 	 * entry - ensure we only delete once by resetting
 	 * the delete on close flag. JRA.
 	 */

	fsp->delete_on_close = false;
	reset_delete_on_close_lck(fsp, lck);

 done:

	if (changed_user) {
		/* unbecome user. */
		pop_sec_ctx();
	}

	/* remove filesystem sharemodes */
	ret_flock = SMB_VFS_KERNEL_FLOCK(fsp, 0, 0);
	if (ret_flock == -1) {
		DEBUG(2, ("close_remove_share_mode: removing kernel flock for "
					"%s failed: %s\n", fsp_str_dbg(fsp),
					strerror(errno)));
	}

	if (!del_share_mode(lck, fsp)) {
		DEBUG(0, ("close_remove_share_mode: Could not delete share "
			  "entry for file %s\n", fsp_str_dbg(fsp)));
	}

	TALLOC_FREE(lck);

	if (delete_file) {
		/*
		 * Do the notification after we released the share
		 * mode lock. Inside notify_fname we take out another
		 * tdb lock. With ctdb also accessing our databases,
		 * this can lead to deadlocks. Putting this notify
		 * after the TALLOC_FREE(lck) above we avoid locking
		 * two records simultaneously. Notifies are async and
		 * informational only, so calling the notify_fname
		 * without holding the share mode lock should not do
		 * any harm.
		 */
		notify_fname(conn, NOTIFY_ACTION_REMOVED,
			     FILE_NOTIFY_CHANGE_FILE_NAME,
			     fsp->fsp_name->base_name);
	}

	return status;
}
Exemplo n.º 8
0
static NTSTATUS set_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB *challenge)
{
	SMB_ASSERT(challenge->length == 8);
	return NT_STATUS_OK;
}
Exemplo n.º 9
0
static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state,
				    const DATA_BLOB request, DATA_BLOB *reply) 
{
	DATA_BLOB encrypted_session_key = data_blob(NULL, 0);
	DATA_BLOB user_session_key = data_blob(NULL, 0);
	DATA_BLOB lm_session_key = data_blob(NULL, 0);
	DATA_BLOB session_key = data_blob(NULL, 0);
	uint32 ntlmssp_command, auth_flags;
	NTSTATUS nt_status;

	/* used by NTLM2 */
	BOOL doing_ntlm2 = False;

	uchar session_nonce[16];
	uchar session_nonce_hash[16];

	const char *parse_string;
	char *domain = NULL;
	char *user = NULL;
	char *workstation = NULL;

	/* parse the NTLMSSP packet */
	*reply = data_blob(NULL, 0);

#if 0
	file_save("ntlmssp_auth.dat", request.data, request.length);
#endif

	if (ntlmssp_state->unicode) {
		parse_string = "CdBBUUUBd";
	} else {
		parse_string = "CdBBAAABd";
	}

	data_blob_free(&ntlmssp_state->lm_resp);
	data_blob_free(&ntlmssp_state->nt_resp);

	ntlmssp_state->user = NULL;
	ntlmssp_state->domain = NULL;
	ntlmssp_state->workstation = NULL;

	/* now the NTLMSSP encoded auth hashes */
	if (!msrpc_parse(&request, parse_string,
			 "NTLMSSP", 
			 &ntlmssp_command, 
			 &ntlmssp_state->lm_resp,
			 &ntlmssp_state->nt_resp,
			 &domain, 
			 &user, 
			 &workstation,
			 &encrypted_session_key,
			 &auth_flags)) {
		SAFE_FREE(domain);
		SAFE_FREE(user);
		SAFE_FREE(workstation);
		data_blob_free(&encrypted_session_key);
		auth_flags = 0;
		
		/* Try again with a shorter string (Win9X truncates this packet) */
		if (ntlmssp_state->unicode) {
			parse_string = "CdBBUUU";
		} else {
			parse_string = "CdBBAAA";
		}

		/* now the NTLMSSP encoded auth hashes */
		if (!msrpc_parse(&request, parse_string,
				 "NTLMSSP", 
				 &ntlmssp_command, 
				 &ntlmssp_state->lm_resp,
				 &ntlmssp_state->nt_resp,
				 &domain, 
				 &user, 
				 &workstation)) {
			DEBUG(1, ("ntlmssp_server_auth: failed to parse NTLMSSP (tried both formats):\n"));
			dump_data(2, (const char *)request.data, request.length);
			SAFE_FREE(domain);
			SAFE_FREE(user);
			SAFE_FREE(workstation);

			return NT_STATUS_INVALID_PARAMETER;
		}
	}

	if (auth_flags)
		ntlmssp_handle_neg_flags(ntlmssp_state, auth_flags, lp_lanman_auth());

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_domain(ntlmssp_state, domain))) {
		SAFE_FREE(domain);
		SAFE_FREE(user);
		SAFE_FREE(workstation);
		data_blob_free(&encrypted_session_key);
		return nt_status;
	}

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_username(ntlmssp_state, user))) {
		SAFE_FREE(domain);
		SAFE_FREE(user);
		SAFE_FREE(workstation);
		data_blob_free(&encrypted_session_key);
		return nt_status;
	}

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_set_workstation(ntlmssp_state, workstation))) {
		SAFE_FREE(domain);
		SAFE_FREE(user);
		SAFE_FREE(workstation);
		data_blob_free(&encrypted_session_key);
		return nt_status;
	}

	SAFE_FREE(domain);
	SAFE_FREE(user);
	SAFE_FREE(workstation);

	DEBUG(3,("Got user=[%s] domain=[%s] workstation=[%s] len1=%lu len2=%lu\n",
		 ntlmssp_state->user, ntlmssp_state->domain, ntlmssp_state->workstation, (unsigned long)ntlmssp_state->lm_resp.length, (unsigned long)ntlmssp_state->nt_resp.length));

#if 0
	file_save("nthash1.dat",  &ntlmssp_state->nt_resp.data,  &ntlmssp_state->nt_resp.length);
	file_save("lmhash1.dat",  &ntlmssp_state->lm_resp.data,  &ntlmssp_state->lm_resp.length);
#endif

	/* NTLM2 uses a 'challenge' that is made of up both the server challenge, and a 
	   client challenge 
	
	   However, the NTLM2 flag may still be set for the real NTLMv2 logins, be careful.
	*/
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) {
		if (ntlmssp_state->nt_resp.length == 24 && ntlmssp_state->lm_resp.length == 24) {
			struct MD5Context md5_session_nonce_ctx;
			SMB_ASSERT(ntlmssp_state->internal_chal.data && ntlmssp_state->internal_chal.length == 8);
			
			doing_ntlm2 = True;

			memcpy(session_nonce, ntlmssp_state->internal_chal.data, 8);
			memcpy(&session_nonce[8], ntlmssp_state->lm_resp.data, 8);
			
			MD5Init(&md5_session_nonce_ctx);
			MD5Update(&md5_session_nonce_ctx, session_nonce, 16);
			MD5Final(session_nonce_hash, &md5_session_nonce_ctx);
			
			ntlmssp_state->chal = data_blob_talloc(ntlmssp_state->mem_ctx, session_nonce_hash, 8);

			/* LM response is no longer useful */
			data_blob_free(&ntlmssp_state->lm_resp);

			/* We changed the effective challenge - set it */
			if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->set_challenge(ntlmssp_state, &ntlmssp_state->chal))) {
				data_blob_free(&encrypted_session_key);
				return nt_status;
			}
		}
	}

	/*
	 * Note we don't check here for NTLMv2 auth settings. If NTLMv2 auth
	 * is required (by "ntlm auth = no" and "lm auth = no" being set in the
	 * smb.conf file) and no NTLMv2 response was sent then the password check
	 * will fail here. JRA.
	 */

	/* Finally, actually ask if the password is OK */

	if (!NT_STATUS_IS_OK(nt_status = ntlmssp_state->check_password(ntlmssp_state, 
								       &user_session_key, &lm_session_key))) {
		data_blob_free(&encrypted_session_key);
		return nt_status;
	}

	dump_data_pw("NT session key:\n", user_session_key.data, user_session_key.length);
	dump_data_pw("LM first-8:\n", lm_session_key.data, lm_session_key.length);

	/* Handle the different session key derivation for NTLM2 */
	if (doing_ntlm2) {
		if (user_session_key.data && user_session_key.length == 16) {
			session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
			hmac_md5(user_session_key.data, session_nonce, 
				 sizeof(session_nonce), session_key.data);
			DEBUG(10,("ntlmssp_server_auth: Created NTLM2 session key.\n"));
			dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length);
			
		} else {
			DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM2 session key.\n"));
			session_key = data_blob(NULL, 0);
		}
	} else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) {
		if (lm_session_key.data && lm_session_key.length >= 8) {
			if (ntlmssp_state->lm_resp.data && ntlmssp_state->lm_resp.length == 24) {
				session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16);
				SMBsesskeygen_lm_sess_key(lm_session_key.data, ntlmssp_state->lm_resp.data, 
							  session_key.data);
				DEBUG(10,("ntlmssp_server_auth: Created NTLM session key.\n"));
				dump_data_pw("LM session key:\n", session_key.data, session_key.length);
			} else {
				/* use the key unmodified - it's
				 * probably a NULL key from the guest
				 * login */
				session_key = lm_session_key;
			}
		} else {
			DEBUG(10,("ntlmssp_server_auth: Failed to create NTLM session key.\n"));
			session_key = data_blob(NULL, 0);
		}
	} else if (user_session_key.data) {
		session_key = user_session_key;
		DEBUG(10,("ntlmssp_server_auth: Using unmodified nt session key.\n"));
		dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
	} else if (lm_session_key.data) {
		session_key = lm_session_key;
		DEBUG(10,("ntlmssp_server_auth: Using unmodified lm session key.\n"));
		dump_data_pw("unmodified session key:\n", session_key.data, session_key.length);
	} else {
		DEBUG(10,("ntlmssp_server_auth: Failed to create unmodified session key.\n"));
		session_key = data_blob(NULL, 0);
	}

	/* With KEY_EXCH, the client supplies the proposed session key, 
	   but encrypts it with the long-term key */
	if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) {
		if (!encrypted_session_key.data || encrypted_session_key.length != 16) {
			data_blob_free(&encrypted_session_key);
			DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", 
				  encrypted_session_key.length));
			return NT_STATUS_INVALID_PARAMETER;
		} else if (!session_key.data || session_key.length != 16) {
			DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", 
				  session_key.length));
			ntlmssp_state->session_key = session_key;
		} else {
			dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length);
			SamOEMhash(encrypted_session_key.data, 
				   session_key.data, 
				   encrypted_session_key.length);
			ntlmssp_state->session_key = data_blob_talloc(ntlmssp_state->mem_ctx, 
								      encrypted_session_key.data, 
								      encrypted_session_key.length);
			dump_data_pw("KEY_EXCH session key:\n", encrypted_session_key.data, 
				     encrypted_session_key.length);
		}
	} else {
		ntlmssp_state->session_key = session_key;
	}

	if (!NT_STATUS_IS_OK(nt_status)) {
		ntlmssp_state->session_key = data_blob(NULL, 0);
	} else if (ntlmssp_state->session_key.length) {
		nt_status = ntlmssp_sign_init(ntlmssp_state);
	}

	data_blob_free(&encrypted_session_key);
	
	/* allow arbitarily many authentications */
	ntlmssp_state->expected_state = NTLMSSP_AUTH;

	return nt_status;
}
Exemplo n.º 10
0
NTSTATUS unix_convert(TALLOC_CTX *ctx,
			connection_struct *conn,
			const char *orig_path,
			bool allow_wcard_last_component,
			char **pp_conv_path,
			char **pp_saved_last_component,
			SMB_STRUCT_STAT *pst)
{
	SMB_STRUCT_STAT st;
	char *start, *end;
	char *dirpath = NULL;
	char *name = NULL;
	char *stream = NULL;
	bool component_was_mangled = False;
	bool name_has_wildcard = False;
	bool posix_pathnames = false;
	NTSTATUS result;
	int ret = -1;

	SET_STAT_INVALID(*pst);
	*pp_conv_path = NULL;
	if(pp_saved_last_component) {
		*pp_saved_last_component = NULL;
	}

	if (conn->printer) {
		/* we don't ever use the filenames on a printer share as a
			filename - so don't convert them */
		if (!(*pp_conv_path = talloc_strdup(ctx,orig_path))) {
			return NT_STATUS_NO_MEMORY;
		}
		return NT_STATUS_OK;
	}

	DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));

	/*
	 * Conversion to basic unix format is already done in
	 * check_path_syntax().
	 */

	/*
	 * Names must be relative to the root of the service - any leading /.
	 * and trailing /'s should have been trimmed by check_path_syntax().
	 */

#ifdef DEVELOPER
	SMB_ASSERT(*orig_path != '/');
#endif

	/*
	 * If we trimmed down to a single '\0' character
	 * then we should use the "." directory to avoid
	 * searching the cache, but not if we are in a
	 * printing share.
	 * As we know this is valid we can return true here.
	 */

	if (!*orig_path) {
		if (!(name = talloc_strdup(ctx,"."))) {
			return NT_STATUS_NO_MEMORY;
		}
		if (SMB_VFS_STAT(conn,name,&st) == 0) {
			*pst = st;
		} else {
			return map_nt_error_from_unix(errno);
		}
		DEBUG(5,("conversion finished \"\" -> %s\n",name));
		goto done;
	}

	if (orig_path[0] == '.' && (orig_path[1] == '/' ||
				orig_path[1] == '\0')) {
		/* Start of pathname can't be "." only. */
		if (orig_path[1] == '\0' || orig_path[2] == '\0') {
			result = NT_STATUS_OBJECT_NAME_INVALID;
		} else {
			result =determine_path_error(
				&orig_path[2], allow_wcard_last_component);
		}
		return result;
	}

	if (!(name = talloc_strdup(ctx, orig_path))) {
		DEBUG(0, ("talloc_strdup failed\n"));
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * Large directory fix normalization. If we're case sensitive, and
	 * the case preserving parameters are set to "no", normalize the case of
	 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
	 * This is in conflict with the current (3.0.20) man page, but is
	 * what people expect from the "large directory howto". I'll update
	 * the man page. Thanks to [email protected] for finding this. JRA.
	 */

	if (conn->case_sensitive && !conn->case_preserve &&
			!conn->short_case_preserve) {
		strnorm(name, lp_defaultcase(SNUM(conn)));
	}

	/*
	 * Ensure saved_last_component is valid even if file exists.
	 */

	if(pp_saved_last_component) {
		end = strrchr_m(name, '/');
		if (end) {
			*pp_saved_last_component = talloc_strdup(ctx, end + 1);
		} else {
			*pp_saved_last_component = talloc_strdup(ctx,
							name);
		}
	}

	posix_pathnames = lp_posix_pathnames();

	if (!posix_pathnames) {
		stream = strchr_m(name, ':');

		if (stream != NULL) {
			char *tmp = talloc_strdup(ctx, stream);
			if (tmp == NULL) {
				TALLOC_FREE(name);
				return NT_STATUS_NO_MEMORY;
			}
			*stream = '\0';
			stream = tmp;
		}
	}

	start = name;

	/* If we're providing case insentive semantics or
	 * the underlying filesystem is case insensitive,
	 * then a case-normalized hit in the stat-cache is
	 * authoratitive. JRA.
	 */

	if((!conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
			stat_cache_lookup(conn, &name, &dirpath, &start, &st)) {
		*pst = st;
		goto done;
	}

	/*
	 * Make sure "dirpath" is an allocated string, we use this for
	 * building the directories with asprintf and free it.
	 */

	if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
		DEBUG(0, ("talloc_strdup failed\n"));
		TALLOC_FREE(name);
		return NT_STATUS_NO_MEMORY;
	}

	/*
	 * stat the name - if it exists then we are all done!
	 */

	if (posix_pathnames) {
		ret = SMB_VFS_LSTAT(conn,name,&st);
	} else {
		ret = SMB_VFS_STAT(conn,name,&st);
	}

	if (ret == 0) {
		/* Ensure we catch all names with in "/."
		   this is disallowed under Windows. */
		const char *p = strstr(name, "/."); /* mb safe. */
		if (p) {
			if (p[2] == '/') {
				/* Error code within a pathname. */
				result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
				goto fail;
			} else if (p[2] == '\0') {
				/* Error code at the end of a pathname. */
				result = NT_STATUS_OBJECT_NAME_INVALID;
				goto fail;
			}
		}
		stat_cache_add(orig_path, name, conn->case_sensitive);
		DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
		*pst = st;
		goto done;
	}

	DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
				name, dirpath, start));

	/*
	 * A special case - if we don't have any mangling chars and are case
	 * sensitive or the underlying filesystem is case insentive then searching
	 * won't help.
	 */

	if ((conn->case_sensitive || !(conn->fs_capabilities & FILE_CASE_SENSITIVE_SEARCH)) &&
			!mangle_is_mangled(name, conn->params)) {
		goto done;
	}

	/*
	 * is_mangled() was changed to look at an entire pathname, not
	 * just a component. JRA.
	 */

	if (mangle_is_mangled(start, conn->params)) {
		component_was_mangled = True;
	}

	/*
	 * Now we need to recursively match the name against the real
	 * directory structure.
	 */

	/*
	 * Match each part of the path name separately, trying the names
	 * as is first, then trying to scan the directory for matching names.
	 */

	for (; start ; start = (end?end+1:(char *)NULL)) {
		/*
		 * Pinpoint the end of this section of the filename.
		 */
		/* mb safe. '/' can't be in any encoded char. */
		end = strchr(start, '/');

		/*
		 * Chop the name at this point.
		 */
		if (end) {
			*end = 0;
		}

		if (pp_saved_last_component) {
			TALLOC_FREE(*pp_saved_last_component);
			*pp_saved_last_component = talloc_strdup(ctx,
							end ? end + 1 : start);
			if (!*pp_saved_last_component) {
				DEBUG(0, ("talloc failed\n"));
				return NT_STATUS_NO_MEMORY;
			}
		}

		/* The name cannot have a component of "." */

		if (ISDOT(start)) {
			if (!end)  {
				/* Error code at the end of a pathname. */
				result = NT_STATUS_OBJECT_NAME_INVALID;
			} else {
				result = determine_path_error(end+1,
						allow_wcard_last_component);
			}
			goto fail;
		}

		/* The name cannot have a wildcard if it's not
		   the last component. */

		name_has_wildcard = ms_has_wild(start);

		/* Wildcard not valid anywhere. */
		if (name_has_wildcard && !allow_wcard_last_component) {
			result = NT_STATUS_OBJECT_NAME_INVALID;
			goto fail;
		}

		/* Wildcards never valid within a pathname. */
		if (name_has_wildcard && end) {
			result = NT_STATUS_OBJECT_NAME_INVALID;
			goto fail;
		}

		/*
		 * Check if the name exists up to this point.
		 */

		if (posix_pathnames) {
			ret = SMB_VFS_LSTAT(conn,name, &st);
		} else {
			ret = SMB_VFS_STAT(conn,name, &st);
		}

		if (ret == 0) {
			/*
			 * It exists. it must either be a directory or this must
			 * be the last part of the path for it to be OK.
			 */
			if (end && !(st.st_mode & S_IFDIR)) {
				/*
				 * An intermediate part of the name isn't
				 * a directory.
				 */
				DEBUG(5,("Not a dir %s\n",start));
				*end = '/';
				/*
				 * We need to return the fact that the
				 * intermediate name resolution failed. This
				 * is used to return an error of ERRbadpath
				 * rather than ERRbadfile. Some Windows
				 * applications depend on the difference between
				 * these two errors.
				 */
				result = NT_STATUS_OBJECT_PATH_NOT_FOUND;
				goto fail;
			}

			if (!end) {
				/*
				 * We just scanned for, and found the end of
				 * the path. We must return the valid stat
				 * struct. JRA.
				 */

				*pst = st;
			}

		} else {
			char *found_name = NULL;

			/* Stat failed - ensure we don't use it. */
			SET_STAT_INVALID(st);

			/*
			 * Reset errno so we can detect
			 * directory open errors.
			 */
			errno = 0;

			/*
			 * Try to find this part of the path in the directory.
			 */

			if (name_has_wildcard ||
			    (get_real_filename_mangled(
				     conn, dirpath, start,
				     talloc_tos(), &found_name) == -1)) {
				char *unmangled;

				if (end) {
					/*
					 * An intermediate part of the name
					 * can't be found.
					 */
					DEBUG(5,("Intermediate not found %s\n",
							start));
					*end = '/';

					/*
					 * We need to return the fact that the
					 * intermediate name resolution failed.
					 * This is used to return an error of
					 * ERRbadpath rather than ERRbadfile.
					 * Some Windows applications depend on
					 * the difference between these two
					 * errors.
					 */

					/*
					 * ENOENT, ENOTDIR and ELOOP all map
					 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
					 * in the filename walk.
					 */

					if (errno == ENOENT ||
							errno == ENOTDIR ||
							errno == ELOOP) {
						result =
						NT_STATUS_OBJECT_PATH_NOT_FOUND;
					}
					else {
						result =
						map_nt_error_from_unix(errno);
					}
					goto fail;
				}

				/* ENOENT is the only valid error here. */
				if ((errno != 0) && (errno != ENOENT)) {
					/*
					 * ENOTDIR and ELOOP both map to
					 * NT_STATUS_OBJECT_PATH_NOT_FOUND
					 * in the filename walk.
					 */
					if (errno == ENOTDIR ||
							errno == ELOOP) {
						result =
						NT_STATUS_OBJECT_PATH_NOT_FOUND;
					}
					else {
						result =
						map_nt_error_from_unix(errno);
					}
					goto fail;
				}

				/*
				 * Just the last part of the name doesn't exist.
				 * We need to strupper() or strlower() it as
				 * this conversion may be used for file creation
				 * purposes. Fix inspired by
				 * Thomas Neumann <*****@*****.**>.
				 */
				if (!conn->case_preserve ||
				    (mangle_is_8_3(start, False,
						   conn->params) &&
						 !conn->short_case_preserve)) {
					strnorm(start,
						lp_defaultcase(SNUM(conn)));
				}

				/*
				 * check on the mangled stack to see if we can
				 * recover the base of the filename.
				 */

				if (mangle_is_mangled(start, conn->params)
				    && mangle_lookup_name_from_8_3(ctx,
					    		start,
							&unmangled,
							conn->params)) {
					char *tmp;
					size_t start_ofs = start - name;

					if (*dirpath != '\0') {
						tmp = talloc_asprintf(ctx,
							"%s/%s", dirpath,
							unmangled);
						TALLOC_FREE(unmangled);
					}
					else {
						tmp = unmangled;
					}
					if (tmp == NULL) {
						DEBUG(0, ("talloc failed\n"));
						return NT_STATUS_NO_MEMORY;
					}
					TALLOC_FREE(name);
					name = tmp;
					start = name + start_ofs;
					end = start + strlen(start);
				}

				DEBUG(5,("New file %s\n",start));
				goto done;
			}


			/*
			 * Restore the rest of the string. If the string was
			 * mangled the size may have changed.
			 */
			if (end) {
				char *tmp;
				size_t start_ofs = start - name;

				if (*dirpath != '\0') {
					tmp = talloc_asprintf(ctx,
						"%s/%s/%s", dirpath,
						found_name, end+1);
				}
				else {
					tmp = talloc_asprintf(ctx,
						"%s/%s", found_name,
						end+1);
				}
				if (tmp == NULL) {
					DEBUG(0, ("talloc_asprintf failed\n"));
					return NT_STATUS_NO_MEMORY;
				}
				TALLOC_FREE(name);
				name = tmp;
				start = name + start_ofs;
				end = start + strlen(found_name);
				*end = '\0';
			} else {
				char *tmp;
				size_t start_ofs = start - name;

				if (*dirpath != '\0') {
					tmp = talloc_asprintf(ctx,
						"%s/%s", dirpath,
						found_name);
				} else {
					tmp = talloc_strdup(ctx,
						found_name);
				}
				if (tmp == NULL) {
					DEBUG(0, ("talloc failed\n"));
					return NT_STATUS_NO_MEMORY;
				}
				TALLOC_FREE(name);
				name = tmp;
				start = name + start_ofs;

				/*
				 * We just scanned for, and found the end of
				 * the path. We must return a valid stat struct
				 * if it exists. JRA.
				 */

				if (posix_pathnames) {
					ret = SMB_VFS_LSTAT(conn,name, &st);
				} else {
					ret = SMB_VFS_STAT(conn,name, &st);
				}

				if (ret == 0) {
					*pst = st;
				} else {
					SET_STAT_INVALID(st);
				}
			}

			TALLOC_FREE(found_name);
		} /* end else */

#ifdef DEVELOPER
		/*
		 * This sucks!
		 * We should never provide different behaviors
		 * depending on DEVELOPER!!!
		 */
		if (VALID_STAT(st)) {
			bool delete_pending;
			get_file_infos(vfs_file_id_from_sbuf(conn, &st),
				       &delete_pending, NULL);
			if (delete_pending) {
				result = NT_STATUS_DELETE_PENDING;
				goto fail;
			}
		}
#endif

		/*
		 * Add to the dirpath that we have resolved so far.
		 */

		if (*dirpath != '\0') {
			char *tmp = talloc_asprintf(ctx,
					"%s/%s", dirpath, start);
			if (!tmp) {
				DEBUG(0, ("talloc_asprintf failed\n"));
				return NT_STATUS_NO_MEMORY;
			}
			TALLOC_FREE(dirpath);
			dirpath = tmp;
		}
		else {
			TALLOC_FREE(dirpath);
			if (!(dirpath = talloc_strdup(ctx,start))) {
				DEBUG(0, ("talloc_strdup failed\n"));
				return NT_STATUS_NO_MEMORY;
			}
		}

		/*
		 * Don't cache a name with mangled or wildcard components
		 * as this can change the size.
		 */

		if(!component_was_mangled && !name_has_wildcard) {
			stat_cache_add(orig_path, dirpath,
					conn->case_sensitive);
		}

		/*
		 * Restore the / that we wiped out earlier.
		 */
		if (end) {
			*end = '/';
		}
	}

	/*
	 * Don't cache a name with mangled or wildcard components
	 * as this can change the size.
	 */

	if(!component_was_mangled && !name_has_wildcard) {
		stat_cache_add(orig_path, name, conn->case_sensitive);
	}

	/*
	 * The name has been resolved.
	 */

	DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));

 done:
	if (stream != NULL) {
		char *tmp = NULL;

		result = build_stream_path(ctx, conn, orig_path, name, stream,
					   pst, &tmp);
		if (!NT_STATUS_IS_OK(result)) {
			goto fail;
		}

		DEBUG(10, ("build_stream_path returned %s\n", tmp));

		TALLOC_FREE(name);
		name = tmp;
	}
	*pp_conv_path = name;
	TALLOC_FREE(dirpath);
	return NT_STATUS_OK;
 fail:
	DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
	if (*dirpath != '\0') {
		*pp_conv_path = talloc_asprintf(ctx,
				"%s/%s", dirpath, start);
	} else {
		*pp_conv_path = talloc_strdup(ctx, start);
	}
	if (!*pp_conv_path) {
		DEBUG(0, ("talloc_asprintf failed\n"));
		return NT_STATUS_NO_MEMORY;
	}
	TALLOC_FREE(name);
	TALLOC_FREE(dirpath);
	return result;
}
Exemplo n.º 11
0
NTSTATUS unix_convert(connection_struct *conn,
			pstring name,
			BOOL allow_wcard_last_component,
			char *saved_last_component, 
			SMB_STRUCT_STAT *pst)
{
	SMB_STRUCT_STAT st;
	char *start, *end;
	pstring dirpath;
	pstring orig_path;
	BOOL component_was_mangled = False;
	BOOL name_has_wildcard = False;

	SET_STAT_INVALID(*pst);

	*dirpath = 0;

	if(saved_last_component) {
		*saved_last_component = 0;
	}

	if (conn->printer) {
		/* we don't ever use the filenames on a printer share as a
			filename - so don't convert them */
		return NT_STATUS_OK;
	}

	DEBUG(5, ("unix_convert called on file \"%s\"\n", name));

	/* 
	 * Conversion to basic unix format is already done in check_path_syntax().
	 */

	/* 
	 * Names must be relative to the root of the service - any leading /.
	 * and trailing /'s should have been trimmed by check_path_syntax().
	 */

#ifdef DEVELOPER
	SMB_ASSERT(*name != '/');
#endif

	/*
	 * If we trimmed down to a single '\0' character
	 * then we should use the "." directory to avoid
	 * searching the cache, but not if we are in a
	 * printing share.
	 * As we know this is valid we can return true here.
	 */

	if (!*name) {
		name[0] = '.';
		name[1] = '\0';
		if (SMB_VFS_STAT(conn,name,&st) == 0) {
			*pst = st;
		}
		DEBUG(5,("conversion finished \"\" -> %s\n",name));
		return NT_STATUS_OK;
	}

	if (name[0] == '.' && (name[1] == '/' || name[1] == '\0')) {
		/* Start of pathname can't be "." only. */
		if (name[1] == '\0' || name[2] == '\0') {
			return NT_STATUS_OBJECT_NAME_INVALID;
		} else {
			return determine_path_error(&name[2], allow_wcard_last_component);
		}
	}

	/*
	 * Ensure saved_last_component is valid even if file exists.
	 */

	if(saved_last_component) {
		end = strrchr_m(name, '/');
		if (end) {
			pstrcpy(saved_last_component, end + 1);
		} else {
			pstrcpy(saved_last_component, name);
		}
	}

	/*
	 * Large directory fix normalization. If we're case sensitive, and
	 * the case preserving parameters are set to "no", normalize the case of
	 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
	 * This is in conflict with the current (3.0.20) man page, but is
	 * what people expect from the "large directory howto". I'll update
	 * the man page. Thanks to [email protected] for finding this. JRA.
	 */

	if (conn->case_sensitive && !conn->case_preserve && !conn->short_case_preserve) {
		strnorm(name, lp_defaultcase(SNUM(conn)));
	}
	
	start = name;
	pstrcpy(orig_path, name);

	if(!conn->case_sensitive && stat_cache_lookup(conn, name, dirpath, &start, &st)) {
		*pst = st;
		return NT_STATUS_OK;
	}

	/* 
	 * stat the name - if it exists then we are all done!
	 */

	if (SMB_VFS_STAT(conn,name,&st) == 0) {
		/* Ensure we catch all names with in "/."
		   this is disallowed under Windows. */
		const char *p = strstr(name, "/."); /* mb safe. */
		if (p) {
			if (p[2] == '/') {
				/* Error code within a pathname. */
				return NT_STATUS_OBJECT_PATH_NOT_FOUND;
			} else if (p[2] == '\0') {
				/* Error code at the end of a pathname. */
				return NT_STATUS_OBJECT_NAME_INVALID;
			}
		}
		stat_cache_add(orig_path, name, conn->case_sensitive);
		DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
		*pst = st;
		return NT_STATUS_OK;
	}

	DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n", name, dirpath, start));

	/* 
	 * A special case - if we don't have any mangling chars and are case
	 * sensitive then searching won't help.
	 */

	if (conn->case_sensitive && 
			!mangle_is_mangled(name, conn->params) &&
			!*lp_mangled_map(conn->params)) {
		return NT_STATUS_OK;
	}

	/* 
	 * is_mangled() was changed to look at an entire pathname, not 
	 * just a component. JRA.
	 */

	if (mangle_is_mangled(start, conn->params)) {
		component_was_mangled = True;
	}

	/* 
	 * Now we need to recursively match the name against the real 
	 * directory structure.
	 */

	/* 
	 * Match each part of the path name separately, trying the names
	 * as is first, then trying to scan the directory for matching names.
	 */

	for (; start ; start = (end?end+1:(char *)NULL)) {
		/* 
		 * Pinpoint the end of this section of the filename.
		 */
		end = strchr(start, '/'); /* mb safe. '/' can't be in any encoded char. */

		/* 
		 * Chop the name at this point.
		 */
		if (end) {
			*end = 0;
		}

		if (saved_last_component != 0) {
			pstrcpy(saved_last_component, end ? end + 1 : start);
		}

		/* The name cannot have a component of "." */

		if (ISDOT(start)) {
			if (!end)  {
				/* Error code at the end of a pathname. */
				return NT_STATUS_OBJECT_NAME_INVALID;
			}
			return determine_path_error(end+1, allow_wcard_last_component);
		}

		/* The name cannot have a wildcard if it's not
		   the last component. */

		name_has_wildcard = ms_has_wild(start);

		/* Wildcard not valid anywhere. */
		if (name_has_wildcard && !allow_wcard_last_component) {
			return NT_STATUS_OBJECT_NAME_INVALID;
		}

		/* Wildcards never valid within a pathname. */
		if (name_has_wildcard && end) {
			return NT_STATUS_OBJECT_NAME_INVALID;
		}

		/* 
		 * Check if the name exists up to this point.
		 */

		if (SMB_VFS_STAT(conn,name, &st) == 0) {
			/*
			 * It exists. it must either be a directory or this must be
			 * the last part of the path for it to be OK.
			 */
			if (end && !(st.st_mode & S_IFDIR)) {
				/*
				 * An intermediate part of the name isn't a directory.
				 */
				DEBUG(5,("Not a dir %s\n",start));
				*end = '/';
				/* 
				 * We need to return the fact that the intermediate
				 * name resolution failed. This is used to return an
				 * error of ERRbadpath rather than ERRbadfile. Some
				 * Windows applications depend on the difference between
				 * these two errors.
				 */
				return NT_STATUS_OBJECT_PATH_NOT_FOUND;
			}

			if (!end) {
				/*
				 * We just scanned for, and found the end of the path.
				 * We must return the valid stat struct.
				 * JRA.
				 */

				*pst = st;
			}

		} else {
			pstring rest;

			/* Stat failed - ensure we don't use it. */
			SET_STAT_INVALID(st);
			*rest = 0;

			/*
			 * Remember the rest of the pathname so it can be restored
			 * later.
			 */

			if (end) {
				pstrcpy(rest,end+1);
			}

			/* Reset errno so we can detect directory open errors. */
			errno = 0;

			/*
			 * Try to find this part of the path in the directory.
			 */

			if (name_has_wildcard || 
			    !scan_directory(conn, dirpath, start, sizeof(pstring) - 1 - (start - name))) {
				if (end) {
					/*
					 * An intermediate part of the name can't be found.
					 */
					DEBUG(5,("Intermediate not found %s\n",start));
					*end = '/';

					/* 
					 * We need to return the fact that the intermediate
					 * name resolution failed. This is used to return an
					 * error of ERRbadpath rather than ERRbadfile. Some
					 * Windows applications depend on the difference between
					 * these two errors.
					 */

					/* ENOENT, ENOTDIR and ELOOP all map to
					 * NT_STATUS_OBJECT_PATH_NOT_FOUND
					 * in the filename walk. */

					if (errno == ENOENT ||
							errno == ENOTDIR ||
							errno == ELOOP) {
						return NT_STATUS_OBJECT_PATH_NOT_FOUND;
					}
					return map_nt_error_from_unix(errno);
				}

				/* ENOENT is the only valid error here. */
				if (errno != ENOENT) {
					/* ENOTDIR and ELOOP both map to
					 * NT_STATUS_OBJECT_PATH_NOT_FOUND
					 * in the filename walk. */
					if (errno == ENOTDIR ||
							errno == ELOOP) {
						return NT_STATUS_OBJECT_PATH_NOT_FOUND;
					}
					return map_nt_error_from_unix(errno);
				}

				/*
				 * Just the last part of the name doesn't exist.
				 * We need to strupper() or strlower() it as
				 * this conversion may be used for file creation 
				 * purposes. Fix inspired by Thomas Neumann <*****@*****.**>.
				 */
				if (!conn->case_preserve ||
				    (mangle_is_8_3(start, False, conn->params) &&
						 !conn->short_case_preserve)) {
					strnorm(start, lp_defaultcase(SNUM(conn)));
				}

				/*
				 * check on the mangled stack to see if we can recover the 
				 * base of the filename.
				 */

				if (mangle_is_mangled(start, conn->params)) {
					mangle_check_cache( start, sizeof(pstring) - 1 - (start - name), conn->params);
				}

				DEBUG(5,("New file %s\n",start));
				return NT_STATUS_OK;
			}

			/* 
			 * Restore the rest of the string. If the string was mangled the size
			 * may have changed.
			 */
			if (end) {
				end = start + strlen(start);
				if (!safe_strcat(start, "/", sizeof(pstring) - 1 - (start - name)) ||
				    !safe_strcat(start, rest, sizeof(pstring) - 1 - (start - name))) {
					return map_nt_error_from_unix(ENAMETOOLONG);
				}
				*end = '\0';
			} else {
				/*
				 * We just scanned for, and found the end of the path.
				 * We must return a valid stat struct if it exists.
				 * JRA.
				 */

				if (SMB_VFS_STAT(conn,name, &st) == 0) {
					*pst = st;
				} else {
					SET_STAT_INVALID(st);
				}
			}
		} /* end else */

#ifdef DEVELOPER
		if (VALID_STAT(st) && get_delete_on_close_flag(st.st_dev, st.st_ino)) {
			return NT_STATUS_DELETE_PENDING;
		}
#endif

		/* 
		 * Add to the dirpath that we have resolved so far.
		 */
		if (*dirpath) {
			pstrcat(dirpath,"/");
		}

		pstrcat(dirpath,start);

		/*
		 * Don't cache a name with mangled or wildcard components
		 * as this can change the size.
		 */
		
		if(!component_was_mangled && !name_has_wildcard) {
			stat_cache_add(orig_path, dirpath, conn->case_sensitive);
		}
	
		/* 
		 * Restore the / that we wiped out earlier.
		 */
		if (end) {
			*end = '/';
		}
	}
  
	/*
	 * Don't cache a name with mangled or wildcard components
	 * as this can change the size.
	 */

	if(!component_was_mangled && !name_has_wildcard) {
		stat_cache_add(orig_path, name, conn->case_sensitive);
	}

	/* 
	 * The name has been resolved.
	 */

	DEBUG(5,("conversion finished %s -> %s\n",orig_path, name));
	return NT_STATUS_OK;
}
Exemplo n.º 12
0
/*
  search for attrs on one DN, in the modules below
 */
int dsdb_module_search_dn(struct ldb_module *module,
			  TALLOC_CTX *mem_ctx,
			  struct ldb_result **_res,
			  struct ldb_dn *basedn,
			  const char * const *attrs,
			  uint32_t dsdb_flags,
			  struct ldb_request *parent)
{
	int ret;
	struct ldb_request *req;
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;

	tmp_ctx = talloc_new(mem_ctx);

	res = talloc_zero(tmp_ctx, struct ldb_result);
	if (!res) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb_module_get_ctx(module));
	}

	ret = ldb_build_search_req(&req, ldb_module_get_ctx(module), tmp_ctx,
				   basedn,
				   LDB_SCOPE_BASE,
				   NULL,
				   attrs,
				   NULL,
				   res,
				   ldb_search_default_callback,
				   parent);
	LDB_REQ_SET_LOCATION(req);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_request_add_controls(req, dsdb_flags);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	if (dsdb_flags & DSDB_FLAG_TRUSTED) {
		ldb_req_mark_trusted(req);
	}

	/* Run the new request */
	if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
		ret = ldb_next_request(module, req);
	} else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
		ret = ldb_request(ldb_module_get_ctx(module), req);
	} else {
		const struct ldb_module_ops *ops = ldb_module_get_ops(module);
		SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
		ret = ops->search(module, req);
	}
	if (ret == LDB_SUCCESS) {
		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
	}

	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	if (res->count != 1) {
		/* we may be reading a DB that does not have the 'check base on search' option... */
		ret = LDB_ERR_NO_SUCH_OBJECT;
		ldb_asprintf_errstring(ldb_module_get_ctx(module), 
				       "dsdb_module_search_dn: did not find base dn %s (%d results)", 
				       ldb_dn_get_linearized(basedn), res->count);
	} else {
		*_res = talloc_steal(mem_ctx, res);
	}
	talloc_free(tmp_ctx);
	return ret;
}
Exemplo n.º 13
0
int dsdb_module_search_tree(struct ldb_module *module,
		       TALLOC_CTX *mem_ctx,
		       struct ldb_result **_res,
		       struct ldb_dn *basedn,
		       enum ldb_scope scope,
		       struct ldb_parse_tree *tree,
		       const char * const *attrs,
		       int dsdb_flags,
		       struct ldb_request *parent)
{
	int ret;
	struct ldb_request *req;
	TALLOC_CTX *tmp_ctx;
	struct ldb_result *res;

	tmp_ctx = talloc_new(mem_ctx);

	/* cross-partitions searches with a basedn break multi-domain support */
	SMB_ASSERT(basedn == NULL || (dsdb_flags & DSDB_SEARCH_SEARCH_ALL_PARTITIONS) == 0);

	res = talloc_zero(tmp_ctx, struct ldb_result);
	if (!res) {
		talloc_free(tmp_ctx);
		return ldb_oom(ldb_module_get_ctx(module));
	}

	ret = ldb_build_search_req_ex(&req, ldb_module_get_ctx(module), tmp_ctx,
				   basedn,
				   scope,
				   tree,
				   attrs,
				   NULL,
				   res,
				   ldb_search_default_callback,
				   parent);
	LDB_REQ_SET_LOCATION(req);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	ret = dsdb_request_add_controls(req, dsdb_flags);
	if (ret != LDB_SUCCESS) {
		talloc_free(tmp_ctx);
		return ret;
	}

	if (dsdb_flags & DSDB_FLAG_TRUSTED) {
		ldb_req_mark_trusted(req);
	}

	if (dsdb_flags & DSDB_FLAG_NEXT_MODULE) {
		ret = ldb_next_request(module, req);
	} else if (dsdb_flags & DSDB_FLAG_TOP_MODULE) {
		ret = ldb_request(ldb_module_get_ctx(module), req);
	} else {
		const struct ldb_module_ops *ops = ldb_module_get_ops(module);
		SMB_ASSERT(dsdb_flags & DSDB_FLAG_OWN_MODULE);
		ret = ops->search(module, req);
	}
	if (ret == LDB_SUCCESS) {
		ret = ldb_wait(req->handle, LDB_WAIT_ALL);
	}

	talloc_free(req);
	if (ret == LDB_SUCCESS) {
		*_res = talloc_steal(mem_ctx, res);
	}
	talloc_free(tmp_ctx);
	return ret;
}
Exemplo n.º 14
0
/**
 * Provision a Samba installation using @param setupdir_script and start smbd.
 */
NTSTATUS torture_setup_server(TALLOC_CTX *mem_ctx, 
							  const char *prefix,
							  const char *setupdir_script,
							  const char *smbd_path,
							  pid_t *smbd_pid)
{
	char *tempdir;
	NTSTATUS status;
	pid_t pid;
	int child_status;
	char *configfile, *configparam;
	pid_t closed_pid;

	*smbd_pid = -1;

	status = torture_temp_dir(mem_ctx, prefix, &tempdir);
	if (NT_STATUS_IS_ERR(status)) {
		return status;
	}

	if ((pid = fork()) == 0) {
		execl(setupdir_script, setupdir_script, tempdir, NULL);
		exit(1);
	} else if (pid == -1) {
		DEBUG(0, ("Unable to fork()\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	closed_pid = waitpid(pid, &child_status, 0);

	if (closed_pid == -1) {
		DEBUG(1, ("Error waiting for child"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	SMB_ASSERT(closed_pid == pid);

	if (!WIFEXITED(child_status) || WEXITSTATUS(child_status) != 0) {
		DEBUG(1, ("Invalid return code from setup script %s: %d\n", 
				  setupdir_script,
				  WEXITSTATUS(child_status)));
		return NT_STATUS_UNSUCCESSFUL;
	}

	configfile = talloc_asprintf(mem_ctx, "%s/etc/smb.conf", 
								 tempdir);
	if (!file_exist(configfile)) {
		DEBUG(1, ("Setup script didn't create %s\n", configfile));
		return NT_STATUS_UNSUCCESSFUL;
	}

	configparam = talloc_asprintf(mem_ctx, "--configfile=%s", configfile);
	talloc_free(configfile);

	if ((pid = fork()) == 0) {
		execl(smbd_path, smbd_path, "-i", "--model=single", 
						configparam, NULL);
		exit(1);
	} else if (pid == -1) {
		DEBUG(0, ("Unable to fork()\n"));
		return NT_STATUS_UNSUCCESSFUL;
	}

	*smbd_pid = pid;

	return NT_STATUS_OK;
}
Exemplo n.º 15
0
NTSTATUS file_new(connection_struct *conn, files_struct **result)
{
	int i;
	static int first_file;
	files_struct *fsp;

	/* we want to give out file handles differently on each new
	   connection because of a common bug in MS clients where they try to
	   reuse a file descriptor from an earlier smb connection. This code
	   increases the chance that the errant client will get an error rather
	   than causing corruption */
	if (first_file == 0) {
		first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files;
	}

	/* TODO: Port the id-tree implementation from Samba4 */

	i = bitmap_find(file_bmap, first_file);
	if (i == -1) {
		DEBUG(0,("ERROR! Out of file structures\n"));
		/* TODO: We have to unconditionally return a DOS error here,
		 * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with
		 * NTSTATUS negotiated */
		return NT_STATUS_TOO_MANY_OPENED_FILES;
	}

	fsp = SMB_MALLOC_P(files_struct);
	if (!fsp) {
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCTP(fsp);

	fsp->fh = SMB_MALLOC_P(struct fd_handle);
	if (!fsp->fh) {
		SAFE_FREE(fsp);
		return NT_STATUS_NO_MEMORY;
	}

	ZERO_STRUCTP(fsp->fh);

	fsp->fh->ref_count = 1;
	fsp->fh->fd = -1;

	fsp->conn = conn;
	fsp->fh->file_id = get_gen_count();
	GetTimeOfDay(&fsp->open_time);

	first_file = (i+1) % real_max_open_files;

	bitmap_set(file_bmap, i);
	files_used++;

	fsp->fnum = i + FILE_HANDLE_OFFSET;
	SMB_ASSERT(fsp->fnum < 65536);

	string_set(&fsp->fsp_name,"");
	
	DLIST_ADD(Files, fsp);

	DEBUG(5,("allocated file structure %d, fnum = %d (%d used)\n",
		 i, fsp->fnum, files_used));

	chain_fsp = fsp;

	/* A new fsp invalidates the positive and
	   negative fsp_fi_cache as the new fsp is pushed
	   at the start of the list and we search from
	   a cache hit to the *end* of the list. */

	ZERO_STRUCT(fsp_fi_cache);

	*result = fsp;
	return NT_STATUS_OK;
}
Exemplo n.º 16
0
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                        int p_idx, int opnum, void *data,
                        ndr_pull_flags_fn_t pull_fn, ndr_push_flags_fn_t push_fn)
{
    prs_struct q_ps, r_ps;
    struct ndr_pull *pull;
    DATA_BLOB blob;
    struct ndr_push *push;
    NTSTATUS status;

    SMB_ASSERT(cli->pipe_idx == p_idx);

    push = ndr_push_init_ctx(mem_ctx);
    if (!push) {
        return NT_STATUS_NO_MEMORY;
    }

    status = push_fn(push, NDR_IN, data);
    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }

    blob = ndr_push_blob(push);

    if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) {
        return NT_STATUS_NO_MEMORY;
    }

    talloc_free(push);

    if (!prs_init( &r_ps, 0, mem_ctx, UNMARSHALL )) {
        prs_mem_free( &q_ps );
        return NT_STATUS_NO_MEMORY;
    }

    status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps);

    prs_mem_free( &q_ps );

    if (!NT_STATUS_IS_OK(status)) {
        prs_mem_free( &r_ps );
        return status;
    }

    if (!prs_data_blob(&r_ps, &blob, mem_ctx)) {
        prs_mem_free( &r_ps );
        return NT_STATUS_NO_MEMORY;
    }

    prs_mem_free( &r_ps );

    pull = ndr_pull_init_blob(&blob, mem_ctx);
    if (pull == NULL) {
        return NT_STATUS_NO_MEMORY;
    }

    /* have the ndr parser alloc memory for us */
    pull->flags |= LIBNDR_FLAG_REF_ALLOC;
    status = pull_fn(pull, NDR_OUT, data);
    talloc_free(pull);

    if (!NT_STATUS_IS_OK(status)) {
        return status;
    }

    return NT_STATUS_OK;
}
Exemplo n.º 17
0
ELOG_TDB *elog_open_tdb( const char *logname, bool force_clear, bool read_only )
{
	TDB_CONTEXT *tdb = NULL;
	uint32_t vers_id;
	ELOG_TDB *ptr;
	char *tdbpath = NULL;
	ELOG_TDB *tdb_node = NULL;
	char *eventlogdir;
	TALLOC_CTX *ctx = talloc_tos();

	/* check for invalid options */

	if (force_clear && read_only) {
		DEBUG(1,("elog_open_tdb: Invalid flags\n"));
		return NULL;
	}

	/* first see if we have an open context */

	for ( ptr=open_elog_list; ptr; ptr=ptr->next ) {
		if ( strequal( ptr->name, logname ) ) {
			ptr->ref_count++;

			/* trick to alow clearing of the eventlog tdb.
			   The force_clear flag should imply that someone
			   has done a force close.  So make sure the tdb
			   is NULL.  If this is a normal open, then just
			   return the existing reference */

			if ( force_clear ) {
				SMB_ASSERT( ptr->tdb == NULL );
				break;
			}
			else
				return ptr;
		}
	}

	/* make sure that the eventlog dir exists */

	eventlogdir = state_path( "eventlog" );
	if ( !directory_exist( eventlogdir ) )
		mkdir( eventlogdir, 0755 );

	/* get the path on disk */

	tdbpath = elog_tdbname(ctx, logname);
	if (!tdbpath) {
		return NULL;
	}

	DEBUG(7,("elog_open_tdb: Opening %s...(force_clear == %s)\n",
		tdbpath, force_clear?"True":"False" ));

	/* the tdb wasn't already open or this is a forced clear open */

	if ( !force_clear ) {

		tdb = tdb_open_log( tdbpath, 0, TDB_DEFAULT, read_only ? O_RDONLY : O_RDWR , 0 );
		if ( tdb ) {
			vers_id = tdb_fetch_int32( tdb, EVT_VERSION );

			if ( vers_id != EVENTLOG_DATABASE_VERSION_V1 ) {
				DEBUG(1,("elog_open_tdb: Invalid version [%d] on file [%s].\n",
					vers_id, tdbpath));
				tdb_close( tdb );
				tdb = elog_init_tdb( tdbpath );
			}
		}
	}

	if ( !tdb )
		tdb = elog_init_tdb( tdbpath );

	/* if we got a valid context, then add it to the list */

	if ( tdb ) {
		/* on a forced clear, just reset the tdb context if we already
		   have an open entry in the list */

		if ( ptr ) {
			ptr->tdb = tdb;
			return ptr;
		}

		if ( !(tdb_node = TALLOC_ZERO_P( NULL, ELOG_TDB)) ) {
			DEBUG(0,("elog_open_tdb: talloc() failure!\n"));
			tdb_close( tdb );
			return NULL;
		}

		tdb_node->name = talloc_strdup( tdb_node, logname );
		tdb_node->tdb = tdb;
		tdb_node->ref_count = 1;

		DLIST_ADD( open_elog_list, tdb_node );
	}

	return tdb_node;
}
Exemplo n.º 18
0
static bool smbd_scavenger_start(struct smbd_scavenger_state *state)
{
	struct server_id self = messaging_server_id(state->msg);
	struct tevent_fd *fde = NULL;
	int fds[2];
	int ret;
	uint64_t unique_id;
	bool ok;

	SMB_ASSERT(server_id_equal(&state->parent_id, &self));

	if (smbd_scavenger_running(state)) {
		struct server_id_buf tmp;
		DEBUG(10, ("scavenger %s already running\n",
			   server_id_str_buf(*state->scavenger_id,
					     &tmp)));
		return true;
	}

	if (state->scavenger_id != NULL) {
		struct server_id_buf tmp;
		DEBUG(10, ("scavenger zombie %s, cleaning up\n",
			   server_id_str_buf(*state->scavenger_id,
					     &tmp)));
		TALLOC_FREE(state->scavenger_id);
	}

	state->scavenger_id = talloc_zero(state, struct server_id);
	if (state->scavenger_id == NULL) {
		DEBUG(2, ("Out of memory\n"));
		goto fail;
	}
	talloc_set_destructor(state->scavenger_id,
			      smbd_scavenger_server_id_destructor);

	ret = socketpair(AF_UNIX, SOCK_STREAM, 0, fds);
	if (ret == -1) {
		DEBUG(2, ("socketpair failed: %s", strerror(errno)));
		goto fail;
	}

	smb_set_close_on_exec(fds[0]);
	smb_set_close_on_exec(fds[1]);

	unique_id = serverid_get_random_unique_id();

	ret = fork();
	if (ret == -1) {
		int err = errno;
		close(fds[0]);
		close(fds[1]);
		DEBUG(0, ("fork failed: %s", strerror(err)));
		goto fail;
	}

	if (ret == 0) {
		/* child */

		NTSTATUS status;

		close(fds[0]);

		set_my_unique_id(unique_id);

		status = smbd_reinit_after_fork(state->msg, state->ev, true);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2, ("reinit_after_fork failed: %s\n",
				  nt_errstr(status)));
			exit_server("reinit_after_fork failed");
			return false;
		}

		prctl_set_comment("smbd-scavenger");

		state->am_scavenger = true;
		*state->scavenger_id = messaging_server_id(state->msg);

		scavenger_setup_sig_term_handler(state->ev);

		serverid_register(*state->scavenger_id, FLAG_MSG_GENERAL);

		ok = scavenger_say_hello(fds[1], *state->scavenger_id);
		if (!ok) {
			DEBUG(2, ("scavenger_say_hello failed\n"));
			exit_server("scavenger_say_hello failed");
			return false;
		}

		fde = tevent_add_fd(state->ev, state->scavenger_id,
				    fds[1], TEVENT_FD_READ,
				    smbd_scavenger_parent_dead, state);
		if (fde == NULL) {
			DEBUG(2, ("tevent_add_fd(smbd_scavenger_parent_dead) "
				  "failed\n"));
			exit_server("tevent_add_fd(smbd_scavenger_parent_dead) "
				    "failed");
			return false;
		}
		tevent_fd_set_auto_close(fde);

		ret = smbd_scavenger_main(state);

		DEBUG(10, ("scavenger ended: %d\n", ret));
		exit_server_cleanly("scavenger ended");
		return false;
	}

	/* parent */
	close(fds[1]);

	ok = scavenger_wait_hello(fds[0], state->scavenger_id);
	if (!ok) {
		close(fds[0]);
		goto fail;
	}

	fde = tevent_add_fd(state->ev, state->scavenger_id,
			    fds[0], TEVENT_FD_READ,
			    smbd_scavenger_done, state);
	if (fde == NULL) {
		close(fds[0]);
		goto fail;
	}
	tevent_fd_set_auto_close(fde);

	return true;
fail:
	TALLOC_FREE(state->scavenger_id);
	return false;
}
Exemplo n.º 19
0
NTSTATUS unix_convert(TALLOC_CTX *ctx,
		      connection_struct *conn,
		      const char *orig_path,
		      struct smb_filename **smb_fname_out,
		      uint32_t ucf_flags)
{
	struct smb_filename *smb_fname = NULL;
	char *start, *end;
	char *dirpath = NULL;
	char *stream = NULL;
	bool component_was_mangled = False;
	bool name_has_wildcard = False;
	bool posix_pathnames = false;
	bool allow_wcard_last_component =
	    (ucf_flags & UCF_ALWAYS_ALLOW_WCARD_LCOMP);
	bool save_last_component = ucf_flags & UCF_SAVE_LCOMP;
	NTSTATUS status;
	int ret = -1;

	*smb_fname_out = NULL;

	smb_fname = talloc_zero(ctx, struct smb_filename);
	if (smb_fname == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	if (conn->printer) {
		/* we don't ever use the filenames on a printer share as a
			filename - so don't convert them */
		if (!(smb_fname->base_name = talloc_strdup(smb_fname,
							   orig_path))) {
			status = NT_STATUS_NO_MEMORY;
			goto err;
		}
		goto done;
	}

	DEBUG(5, ("unix_convert called on file \"%s\"\n", orig_path));

	/*
	 * Conversion to basic unix format is already done in
	 * check_path_syntax().
	 */

	/*
	 * Names must be relative to the root of the service - any leading /.
	 * and trailing /'s should have been trimmed by check_path_syntax().
	 */

#ifdef DEVELOPER
	SMB_ASSERT(*orig_path != '/');
#endif

	/*
	 * If we trimmed down to a single '\0' character
	 * then we should use the "." directory to avoid
	 * searching the cache, but not if we are in a
	 * printing share.
	 * As we know this is valid we can return true here.
	 */

	if (!*orig_path) {
		if (!(smb_fname->base_name = talloc_strdup(smb_fname, "."))) {
			status = NT_STATUS_NO_MEMORY;
			goto err;
		}
		if (SMB_VFS_STAT(conn, smb_fname) != 0) {
			status = map_nt_error_from_unix(errno);
			goto err;
		}
		DEBUG(5, ("conversion finished \"\" -> %s\n",
			  smb_fname->base_name));
		goto done;
	}

	if (orig_path[0] == '.' && (orig_path[1] == '/' ||
				orig_path[1] == '\0')) {
		/* Start of pathname can't be "." only. */
		if (orig_path[1] == '\0' || orig_path[2] == '\0') {
			status = NT_STATUS_OBJECT_NAME_INVALID;
		} else {
			status =determine_path_error(&orig_path[2],
			    allow_wcard_last_component);
		}
		goto err;
	}

	/* Start with the full orig_path as given by the caller. */
	if (!(smb_fname->base_name = talloc_strdup(smb_fname, orig_path))) {
		DEBUG(0, ("talloc_strdup failed\n"));
		status = NT_STATUS_NO_MEMORY;
		goto err;
	}

	/*
	 * Large directory fix normalization. If we're case sensitive, and
	 * the case preserving parameters are set to "no", normalize the case of
	 * the incoming filename from the client WHETHER IT EXISTS OR NOT !
	 * This is in conflict with the current (3.0.20) man page, but is
	 * what people expect from the "large directory howto". I'll update
	 * the man page. Thanks to [email protected] for finding this. JRA.
	 */

	if (conn->case_sensitive && !conn->case_preserve &&
			!conn->short_case_preserve) {
		if (!strnorm(smb_fname->base_name, lp_defaultcase(SNUM(conn)))) {
			DEBUG(0, ("strnorm %s failed\n", smb_fname->base_name));
			status = NT_STATUS_INVALID_PARAMETER;
			goto err;
		}
	}

	/*
	 * Ensure saved_last_component is valid even if file exists.
	 */

	if(save_last_component) {
		end = strrchr_m(smb_fname->base_name, '/');
		if (end) {
			smb_fname->original_lcomp = talloc_strdup(smb_fname,
								  end + 1);
		} else {
			smb_fname->original_lcomp =
			    talloc_strdup(smb_fname, smb_fname->base_name);
		}
		if (smb_fname->original_lcomp == NULL) {
			status = NT_STATUS_NO_MEMORY;
			goto err;
		}
	}

	posix_pathnames = (lp_posix_pathnames() ||
				(ucf_flags & UCF_POSIX_PATHNAMES));

	/*
	 * Strip off the stream, and add it back when we're done with the
	 * base_name.
	 */
	if (!posix_pathnames) {
		stream = strchr_m(smb_fname->base_name, ':');

		if (stream != NULL) {
			char *tmp = talloc_strdup(smb_fname, stream);
			if (tmp == NULL) {
				status = NT_STATUS_NO_MEMORY;
				goto err;
			}
			/*
			 * Since this is actually pointing into
			 * smb_fname->base_name this truncates base_name.
			 */
			*stream = '\0';
			stream = tmp;
		}
	}

	start = smb_fname->base_name;

	/*
	 * If we're providing case insensitive semantics or
	 * the underlying filesystem is case insensitive,
	 * then a case-normalized hit in the stat-cache is
	 * authoratitive. JRA.
	 *
	 * Note: We're only checking base_name.  The stream_name will be
	 * added and verified in build_stream_path().
	 */

	if((!conn->case_sensitive || !(conn->fs_capabilities &
				       FILE_CASE_SENSITIVE_SEARCH)) &&
	    stat_cache_lookup(conn, posix_pathnames, &smb_fname->base_name, &dirpath, &start,
			      &smb_fname->st)) {
		goto done;
	}

	/*
	 * Make sure "dirpath" is an allocated string, we use this for
	 * building the directories with talloc_asprintf and free it.
	 */

	if ((dirpath == NULL) && (!(dirpath = talloc_strdup(ctx,"")))) {
		DEBUG(0, ("talloc_strdup failed\n"));
		status = NT_STATUS_NO_MEMORY;
		goto err;
	}

	/*
	 * If we have a wildcard we must walk the path to
	 * find where the error is, even if case sensitive
	 * is true.
	 */

	name_has_wildcard = ms_has_wild(smb_fname->base_name);
	if (name_has_wildcard && !allow_wcard_last_component) {
		/* Wildcard not valid anywhere. */
		status = NT_STATUS_OBJECT_NAME_INVALID;
		goto fail;
	}

	DEBUG(5,("unix_convert begin: name = %s, dirpath = %s, start = %s\n",
		 smb_fname->base_name, dirpath, start));

	if (!name_has_wildcard) {
		/*
		 * stat the name - if it exists then we can add the stream back (if
		 * there was one) and be done!
		 */

		if (posix_pathnames) {
			ret = SMB_VFS_LSTAT(conn, smb_fname);
		} else {
			ret = SMB_VFS_STAT(conn, smb_fname);
		}

		if (ret == 0) {
			status = check_for_dot_component(smb_fname);
			if (!NT_STATUS_IS_OK(status)) {
				goto fail;
			}
			/* Add the path (not including the stream) to the cache. */
			stat_cache_add(orig_path, smb_fname->base_name,
				       conn->case_sensitive);
			DEBUG(5,("conversion of base_name finished %s -> %s\n",
				 orig_path, smb_fname->base_name));
			goto done;
		}

		/* Stat failed - ensure we don't use it. */
		SET_STAT_INVALID(smb_fname->st);

		if (errno == ENOENT) {
			/* Optimization when creating a new file - only
			   the last component doesn't exist.
			   NOTE : check_parent_exists() doesn't preserve errno.
			*/
			int saved_errno = errno;
			status = check_parent_exists(ctx,
						conn,
						posix_pathnames,
						smb_fname,
						&dirpath,
						&start);
			errno = saved_errno;
			if (!NT_STATUS_IS_OK(status)) {
				goto fail;
			}
		}

		/*
		 * A special case - if we don't have any wildcards or mangling chars and are case
		 * sensitive or the underlying filesystem is case insensitive then searching
		 * won't help.
		 */

		if ((conn->case_sensitive || !(conn->fs_capabilities &
					FILE_CASE_SENSITIVE_SEARCH)) &&
				!mangle_is_mangled(smb_fname->base_name, conn->params)) {

			status = check_for_dot_component(smb_fname);
			if (!NT_STATUS_IS_OK(status)) {
				goto fail;
			}

			/*
			 * The stat failed. Could be ok as it could be
 			 * a new file.
 			 */

			if (errno == ENOTDIR || errno == ELOOP) {
				status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
				goto fail;
			} else if (errno == ENOENT) {
				/*
				 * Was it a missing last component ?
				 * or a missing intermediate component ?
				 */
				struct smb_filename parent_fname;
				const char *last_component = NULL;

				ZERO_STRUCT(parent_fname);
				if (!parent_dirname(ctx, smb_fname->base_name,
							&parent_fname.base_name,
							&last_component)) {
					status = NT_STATUS_NO_MEMORY;
					goto fail;
				}
				if (posix_pathnames) {
					ret = SMB_VFS_LSTAT(conn, &parent_fname);
				} else {
					ret = SMB_VFS_STAT(conn, &parent_fname);
				}
				if (ret == -1) {
					if (errno == ENOTDIR ||
							errno == ENOENT ||
							errno == ELOOP) {
						status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
						goto fail;
					}
				}

				/*
				 * Missing last component is ok - new file.
				 * Also deal with permission denied elsewhere.
				 * Just drop out to done.
				 */
				goto done;
			}
		}
	} else {
		/*
		 * We have a wildcard in the pathname.
		 *
		 * Optimization for common case where the wildcard
		 * is in the last component and the client already
		 * sent the correct case.
		 * NOTE : check_parent_exists() doesn't preserve errno.
		 */
		int saved_errno = errno;
		status = check_parent_exists(ctx,
					conn,
					posix_pathnames,
					smb_fname,
					&dirpath,
					&start);
		errno = saved_errno;
		if (!NT_STATUS_IS_OK(status)) {
			goto fail;
		}
	}

	/*
	 * is_mangled() was changed to look at an entire pathname, not
	 * just a component. JRA.
	 */

	if (mangle_is_mangled(start, conn->params)) {
		component_was_mangled = True;
	}

	/*
	 * Now we need to recursively match the name against the real
	 * directory structure.
	 */

	/*
	 * Match each part of the path name separately, trying the names
	 * as is first, then trying to scan the directory for matching names.
	 */

	for (; start ; start = (end?end+1:(char *)NULL)) {
		/*
		 * Pinpoint the end of this section of the filename.
		 */
		/* mb safe. '/' can't be in any encoded char. */
		end = strchr(start, '/');

		/*
		 * Chop the name at this point.
		 */
		if (end) {
			*end = 0;
		}

		if (save_last_component) {
			TALLOC_FREE(smb_fname->original_lcomp);
			smb_fname->original_lcomp = talloc_strdup(smb_fname,
							end ? end + 1 : start);
			if (!smb_fname->original_lcomp) {
				DEBUG(0, ("talloc failed\n"));
				status = NT_STATUS_NO_MEMORY;
				goto err;
			}
		}

		/* The name cannot have a component of "." */

		if (ISDOT(start)) {
			if (!end)  {
				/* Error code at the end of a pathname. */
				status = NT_STATUS_OBJECT_NAME_INVALID;
			} else {
				status = determine_path_error(end+1,
						allow_wcard_last_component);
			}
			goto fail;
		}

		/* The name cannot have a wildcard if it's not
		   the last component. */

		name_has_wildcard = ms_has_wild(start);

		/* Wildcards never valid within a pathname. */
		if (name_has_wildcard && end) {
			status = NT_STATUS_OBJECT_NAME_INVALID;
			goto fail;
		}

		/* Skip the stat call if it's a wildcard end. */
		if (name_has_wildcard) {
			DEBUG(5,("Wildcard %s\n",start));
			goto done;
		}

		/*
		 * Check if the name exists up to this point.
		 */

		if (posix_pathnames) {
			ret = SMB_VFS_LSTAT(conn, smb_fname);
		} else {
			ret = SMB_VFS_STAT(conn, smb_fname);
		}

		if (ret == 0) {
			/*
			 * It exists. it must either be a directory or this must
			 * be the last part of the path for it to be OK.
			 */
			if (end && !S_ISDIR(smb_fname->st.st_ex_mode)) {
				/*
				 * An intermediate part of the name isn't
				 * a directory.
				 */
				DEBUG(5,("Not a dir %s\n",start));
				*end = '/';
				/*
				 * We need to return the fact that the
				 * intermediate name resolution failed. This
				 * is used to return an error of ERRbadpath
				 * rather than ERRbadfile. Some Windows
				 * applications depend on the difference between
				 * these two errors.
				 */
				status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
				goto fail;
			}

		} else {
			char *found_name = NULL;

			/* Stat failed - ensure we don't use it. */
			SET_STAT_INVALID(smb_fname->st);

			/*
			 * Reset errno so we can detect
			 * directory open errors.
			 */
			errno = 0;

			/*
			 * Try to find this part of the path in the directory.
			 */

			if (name_has_wildcard ||
			    (get_real_filename(conn, dirpath, start,
					       talloc_tos(),
					       &found_name) == -1)) {
				char *unmangled;

				if (end) {
					/*
					 * An intermediate part of the name
					 * can't be found.
					 */
					DEBUG(5,("Intermediate not found %s\n",
							start));
					*end = '/';

					/*
					 * We need to return the fact that the
					 * intermediate name resolution failed.
					 * This is used to return an error of
					 * ERRbadpath rather than ERRbadfile.
					 * Some Windows applications depend on
					 * the difference between these two
					 * errors.
					 */

					/*
					 * ENOENT, ENOTDIR and ELOOP all map
					 * to NT_STATUS_OBJECT_PATH_NOT_FOUND
					 * in the filename walk.
					 */

					if (errno == ENOENT ||
							errno == ENOTDIR ||
							errno == ELOOP) {
						status =
						NT_STATUS_OBJECT_PATH_NOT_FOUND;
					}
					else {
						status =
						map_nt_error_from_unix(errno);
					}
					goto fail;
				}

				/*
				 * ENOENT/EACCESS are the only valid errors
				 * here.
				 */

				if (errno == EACCES) {
					if (ucf_flags & UCF_CREATING_FILE) {
						/*
						 * This is the dropbox
						 * behaviour. A dropbox is a
						 * directory with only -wx
						 * permissions, so
						 * get_real_filename fails
						 * with EACCESS, it needs to
						 * list the directory. We
						 * nevertheless want to allow
						 * users creating a file.
						 */
						status = NT_STATUS_OBJECT_PATH_NOT_FOUND;
					} else {
						status = NT_STATUS_ACCESS_DENIED;
					}
					goto fail;
				}

				if ((errno != 0) && (errno != ENOENT)) {
					/*
					 * ENOTDIR and ELOOP both map to
					 * NT_STATUS_OBJECT_PATH_NOT_FOUND
					 * in the filename walk.
					 */
					if (errno == ENOTDIR ||
							errno == ELOOP) {
						status =
						NT_STATUS_OBJECT_PATH_NOT_FOUND;
					} else {
						status =
						map_nt_error_from_unix(errno);
					}
					goto fail;
				}

				/*
				 * Just the last part of the name doesn't exist.
				 * We need to strupper() or strlower() it as
				 * this conversion may be used for file creation
				 * purposes. Fix inspired by
				 * Thomas Neumann <*****@*****.**>.
				 */
				if (!conn->case_preserve ||
				    (mangle_is_8_3(start, False,
						   conn->params) &&
						 !conn->short_case_preserve)) {
					if (!strnorm(start,
							lp_defaultcase(SNUM(conn)))) {
						DEBUG(0, ("strnorm %s failed\n",
							start));
						status = NT_STATUS_INVALID_PARAMETER;
						goto err;
					}
				}

				/*
				 * check on the mangled stack to see if we can
				 * recover the base of the filename.
				 */

				if (mangle_is_mangled(start, conn->params)
				    && mangle_lookup_name_from_8_3(ctx,
					    		start,
							&unmangled,
							conn->params)) {
					char *tmp;
					size_t start_ofs =
					    start - smb_fname->base_name;

					if (*dirpath != '\0') {
						tmp = talloc_asprintf(
							smb_fname, "%s/%s",
							dirpath, unmangled);
						TALLOC_FREE(unmangled);
					}
					else {
						tmp = unmangled;
					}
					if (tmp == NULL) {
						DEBUG(0, ("talloc failed\n"));
						status = NT_STATUS_NO_MEMORY;
						goto err;
					}
					TALLOC_FREE(smb_fname->base_name);
					smb_fname->base_name = tmp;
					start =
					    smb_fname->base_name + start_ofs;
					end = start + strlen(start);
				}

				DEBUG(5,("New file %s\n",start));
				goto done;
			}


			/*
			 * Restore the rest of the string. If the string was
			 * mangled the size may have changed.
			 */
			if (end) {
				char *tmp;
				size_t start_ofs =
				    start - smb_fname->base_name;

				if (*dirpath != '\0') {
					tmp = talloc_asprintf(smb_fname,
						"%s/%s/%s", dirpath,
						found_name, end+1);
				}
				else {
					tmp = talloc_asprintf(smb_fname,
						"%s/%s", found_name,
						end+1);
				}
				if (tmp == NULL) {
					DEBUG(0, ("talloc_asprintf failed\n"));
					status = NT_STATUS_NO_MEMORY;
					goto err;
				}
				TALLOC_FREE(smb_fname->base_name);
				smb_fname->base_name = tmp;
				start = smb_fname->base_name + start_ofs;
				end = start + strlen(found_name);
				*end = '\0';
			} else {
				char *tmp;
				size_t start_ofs =
				    start - smb_fname->base_name;

				if (*dirpath != '\0') {
					tmp = talloc_asprintf(smb_fname,
						"%s/%s", dirpath,
						found_name);
				} else {
					tmp = talloc_strdup(smb_fname,
						found_name);
				}
				if (tmp == NULL) {
					DEBUG(0, ("talloc failed\n"));
					status = NT_STATUS_NO_MEMORY;
					goto err;
				}
				TALLOC_FREE(smb_fname->base_name);
				smb_fname->base_name = tmp;
				start = smb_fname->base_name + start_ofs;

				/*
				 * We just scanned for, and found the end of
				 * the path. We must return a valid stat struct
				 * if it exists. JRA.
				 */

				if (posix_pathnames) {
					ret = SMB_VFS_LSTAT(conn, smb_fname);
				} else {
					ret = SMB_VFS_STAT(conn, smb_fname);
				}

				if (ret != 0) {
					SET_STAT_INVALID(smb_fname->st);
				}
			}

			TALLOC_FREE(found_name);
		} /* end else */

#ifdef DEVELOPER
		/*
		 * This sucks!
		 * We should never provide different behaviors
		 * depending on DEVELOPER!!!
		 */
		if (VALID_STAT(smb_fname->st)) {
			bool delete_pending;
			uint32_t name_hash;

			status = file_name_hash(conn,
					smb_fname_str_dbg(smb_fname),
					&name_hash);
			if (!NT_STATUS_IS_OK(status)) {
				goto fail;
			}

			get_file_infos(vfs_file_id_from_sbuf(conn,
							     &smb_fname->st),
				       name_hash,
				       &delete_pending, NULL);
			if (delete_pending) {
				status = NT_STATUS_DELETE_PENDING;
				goto fail;
			}
		}
#endif

		/*
		 * Add to the dirpath that we have resolved so far.
		 */

		if (*dirpath != '\0') {
			char *tmp = talloc_asprintf(ctx,
					"%s/%s", dirpath, start);
			if (!tmp) {
				DEBUG(0, ("talloc_asprintf failed\n"));
				status = NT_STATUS_NO_MEMORY;
				goto err;
			}
			TALLOC_FREE(dirpath);
			dirpath = tmp;
		}
		else {
			TALLOC_FREE(dirpath);
			if (!(dirpath = talloc_strdup(ctx,start))) {
				DEBUG(0, ("talloc_strdup failed\n"));
				status = NT_STATUS_NO_MEMORY;
				goto err;
			}
		}

		/*
		 * Cache the dirpath thus far. Don't cache a name with mangled
		 * or wildcard components as this can change the size.
		 */
		if(!component_was_mangled && !name_has_wildcard) {
			stat_cache_add(orig_path, dirpath,
					conn->case_sensitive);
		}

		/*
		 * Restore the / that we wiped out earlier.
		 */
		if (end) {
			*end = '/';
		}
	}

	/*
	 * Cache the full path. Don't cache a name with mangled or wildcard
	 * components as this can change the size.
	 */

	if(!component_was_mangled && !name_has_wildcard) {
		stat_cache_add(orig_path, smb_fname->base_name,
			       conn->case_sensitive);
	}

	/*
	 * The name has been resolved.
	 */

	DEBUG(5,("conversion finished %s -> %s\n", orig_path,
		 smb_fname->base_name));

 done:
	/* Add back the stream if one was stripped off originally. */
	if (stream != NULL) {
		smb_fname->stream_name = stream;

		/* Check path now that the base_name has been converted. */
		status = build_stream_path(ctx, conn, orig_path, smb_fname);
		if (!NT_STATUS_IS_OK(status)) {
			goto fail;
		}
	}
	TALLOC_FREE(dirpath);
	*smb_fname_out = smb_fname;
	return NT_STATUS_OK;
 fail:
	DEBUG(10, ("dirpath = [%s] start = [%s]\n", dirpath, start));
	if (*dirpath != '\0') {
		smb_fname->base_name = talloc_asprintf(smb_fname, "%s/%s",
						       dirpath, start);
	} else {
		smb_fname->base_name = talloc_strdup(smb_fname, start);
	}
	if (!smb_fname->base_name) {
		DEBUG(0, ("talloc_asprintf failed\n"));
		status = NT_STATUS_NO_MEMORY;
		goto err;
	}

	*smb_fname_out = smb_fname;
	TALLOC_FREE(dirpath);
	return status;
 err:
	TALLOC_FREE(smb_fname);
	return status;
}
Exemplo n.º 20
0
static bool change_to_user_internal(connection_struct *conn,
				    const struct auth_session_info *session_info,
				    uint64_t vuid)
{
	int snum;
	gid_t gid;
	uid_t uid;
	char group_c;
	int num_groups = 0;
	gid_t *group_list = NULL;
	bool ok;

	snum = SNUM(conn);

	ok = check_user_ok(conn, vuid, session_info, snum);
	if (!ok) {
		DEBUG(2,("SMB user %s (unix user %s) "
			 "not permitted access to share %s.\n",
			 session_info->unix_info->sanitized_username,
			 session_info->unix_info->unix_name,
			 lp_servicename(talloc_tos(), snum)));
		return false;
	}

	uid = conn->session_info->unix_token->uid;
	gid = conn->session_info->unix_token->gid;
	num_groups = conn->session_info->unix_token->ngroups;
	group_list  = conn->session_info->unix_token->groups;

	/*
	 * See if we should force group for this service. If so this overrides
	 * any group set in the force user code.
	 */
	if((group_c = *lp_force_group(talloc_tos(), snum))) {

		SMB_ASSERT(conn->force_group_gid != (gid_t)-1);

		if (group_c == '+') {
			int i;

			/*
			 * Only force group if the user is a member of the
			 * service group. Check the group memberships for this
			 * user (we already have this) to see if we should force
			 * the group.
			 */
			for (i = 0; i < num_groups; i++) {
				if (group_list[i] == conn->force_group_gid) {
					conn->session_info->unix_token->gid =
						conn->force_group_gid;
					gid = conn->force_group_gid;
					gid_to_sid(&conn->session_info->security_token
						   ->sids[1], gid);
					break;
				}
			}
		} else {
			conn->session_info->unix_token->gid = conn->force_group_gid;
			gid = conn->force_group_gid;
			gid_to_sid(&conn->session_info->security_token->sids[1],
				   gid);
		}
	}

	/*Set current_user since we will immediately also call set_sec_ctx() */
	current_user.ut.ngroups = num_groups;
	current_user.ut.groups  = group_list;

	set_sec_ctx(uid,
		    gid,
		    current_user.ut.ngroups,
		    current_user.ut.groups,
		    conn->session_info->security_token);

	current_user.conn = conn;
	current_user.vuid = vuid;

	DEBUG(5, ("Impersonated user: uid=(%d,%d), gid=(%d,%d)\n",
		 (int)getuid(),
		 (int)geteuid(),
		 (int)getgid(),
		 (int)getegid()));

	return true;
}
Exemplo n.º 21
0
bool recursive_rmdir(TALLOC_CTX *ctx,
		     connection_struct *conn,
		     struct smb_filename *smb_dname)
{
	const char *dname = NULL;
	char *talloced = NULL;
	bool ret = True;
	long offset = 0;
	SMB_STRUCT_STAT st;
	struct smb_Dir *dir_hnd;

	SMB_ASSERT(!is_ntfs_stream_smb_fname(smb_dname));

	dir_hnd = OpenDir(talloc_tos(), conn, smb_dname->base_name, NULL, 0);
	if(dir_hnd == NULL)
		return False;

	while((dname = ReadDirName(dir_hnd, &offset, &st, &talloced))) {
		struct smb_filename *smb_dname_full = NULL;
		char *fullname = NULL;
		bool do_break = true;

		if (ISDOT(dname) || ISDOTDOT(dname)) {
			TALLOC_FREE(talloced);
			continue;
		}

		if (!is_visible_file(conn, smb_dname->base_name, dname, &st,
				     false)) {
			TALLOC_FREE(talloced);
			continue;
		}

		/* Construct the full name. */
		fullname = talloc_asprintf(ctx,
				"%s/%s",
				smb_dname->base_name,
				dname);
		if (!fullname) {
			errno = ENOMEM;
			goto err_break;
		}

		smb_dname_full = synthetic_smb_fname(talloc_tos(), fullname,
						     NULL, NULL);
		if (smb_dname_full == NULL) {
			errno = ENOMEM;
			goto err_break;
		}

		if(SMB_VFS_LSTAT(conn, smb_dname_full) != 0) {
			goto err_break;
		}

		if(smb_dname_full->st.st_ex_mode & S_IFDIR) {
			if(!recursive_rmdir(ctx, conn, smb_dname_full)) {
				goto err_break;
			}
			if(SMB_VFS_RMDIR(conn,
					 smb_dname_full->base_name) != 0) {
				goto err_break;
			}
		} else if(SMB_VFS_UNLINK(conn, smb_dname_full) != 0) {
			goto err_break;
		}

		/* Successful iteration. */
		do_break = false;

	 err_break:
		TALLOC_FREE(smb_dname_full);
		TALLOC_FREE(fullname);
		TALLOC_FREE(talloced);
		if (do_break) {
			ret = false;
			break;
		}
	}
	TALLOC_FREE(dir_hnd);
	return ret;
}
Exemplo n.º 22
0
const uint8 *pdb_get_nt_passwd(const struct samu *sampass)
{
	SMB_ASSERT((!sampass->nt_pw.data) 
		   || sampass->nt_pw.length == NT_HASH_LEN);
	return (uint8 *)sampass->nt_pw.data;
}
Exemplo n.º 23
0
static WERROR cmd_witness_GetInterfaceList(struct rpc_pipe_client *cli,
					   TALLOC_CTX *mem_ctx, int argc,
					   const char **argv)
{
	NTSTATUS status;
	WERROR result;
	TALLOC_CTX *frame = talloc_stackframe();
	struct witness_interfaceList *interface_list = NULL;
	uint32_t num_interfaces, n;
	struct witness_interfaceInfo *interfaces;

	use_only_one_rpc_pipe_hack(cli);

	status = dcerpc_witness_GetInterfaceList(cli->binding_handle, frame,
						 &interface_list, &result);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("dcerpc_witness_GetInterfaceList failed, status: %s\n", nt_errstr(status)));
		result = ntstatus_to_werror(status);
		goto done;
	}
	if (!W_ERROR_IS_OK(result)) {
		DEBUG(0, ("dcerpc_witness_GetInterfaceList failed, error: %s\n", win_errstr(result)));
		goto done;
	}

	SMB_ASSERT(interface_list);
	interfaces = interface_list->interfaces;
	num_interfaces = interface_list->num_interfaces;

	for (n=0; n < num_interfaces; n++) {
		char wif = (interfaces[n].flags & WITNESS_INFO_WITNESS_IF) ? '*' : ' ';
		char state = 'X';

		if (interfaces[n].state == WITNESS_STATE_AVAILABLE) {
			state = '+';
		} else if (interfaces[n].state == WITNESS_STATE_UNAVAILABLE) {
			state = '-';
		} else if (interfaces[n].state == WITNESS_STATE_UNKNOWN) {
			state = '?';
		}

		d_printf("%c%c %s", wif, state, interfaces[n].group_name);

		if (interfaces[n].flags & WITNESS_INFO_IPv4_VALID) {
			d_printf(" %s", interfaces[n].ipv4);
		}

		if (interfaces[n].flags & WITNESS_INFO_IPv6_VALID) {
			d_printf(" %s", interfaces[n].ipv6);
		}

		switch (interfaces[n].version) {
		case WITNESS_V1:
			d_printf(" V1");
			break;
		case WITNESS_V2:
			d_printf(" V2");
			break;
		default:
			d_printf(" Unsuported Version (0x%08x)", interfaces[n].version);
		}

		d_printf("\n");
	}

done:
	talloc_free(frame);
	return result;
}
Exemplo n.º 24
0
const uint8 *pdb_get_lanman_passwd(const struct samu *sampass)
{
	SMB_ASSERT((!sampass->lm_pw.data) 
		   || sampass->lm_pw.length == LM_HASH_LEN);
	return (uint8 *)sampass->lm_pw.data;
}
Exemplo n.º 25
0
/**
* @brief   Append an auth footer according to what is the current mechanism
*
* @param auth		The pipe_auth_data associated with the connection
* @param pad_len	The padding used in the packet
* @param rpc_out	Packet blob up to and including the auth header
*
* @return A NTSTATUS error code.
*/
NTSTATUS dcerpc_add_auth_footer(struct pipe_auth_data *auth,
				size_t pad_len, DATA_BLOB *rpc_out)
{
	struct gensec_security *gensec_security;
	const char pad[DCERPC_AUTH_PAD_ALIGNMENT] = { 0, };
	DATA_BLOB auth_info;
	DATA_BLOB auth_blob;
	NTSTATUS status;

	if (auth->auth_type == DCERPC_AUTH_TYPE_NONE) {
		return NT_STATUS_OK;
	}

	if (pad_len) {
		SMB_ASSERT(pad_len <= ARRAY_SIZE(pad));

		/* Copy the sign/seal padding data. */
		if (!data_blob_append(NULL, rpc_out, pad, pad_len)) {
			return NT_STATUS_NO_MEMORY;
		}
	}

	/* marshall the dcerpc_auth with an actually empty auth_blob.
	 * This is needed because the ntmlssp signature includes the
	 * auth header. We will append the actual blob later. */
	auth_blob = data_blob_null;
	status = dcerpc_push_dcerpc_auth(rpc_out->data,
					 auth->auth_type,
					 auth->auth_level,
					 pad_len,
					 auth->auth_context_id,
					 &auth_blob,
					 &auth_info);
	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	/* append the header */
	if (!data_blob_append(NULL, rpc_out,
				auth_info.data, auth_info.length)) {
		DEBUG(0, ("Failed to add %u bytes auth blob.\n",
			  (unsigned int)auth_info.length));
		return NT_STATUS_NO_MEMORY;
	}
	data_blob_free(&auth_info);

	/* Generate any auth sign/seal and add the auth footer. */
	switch (auth->auth_type) {
	case DCERPC_AUTH_TYPE_NONE:
		status = NT_STATUS_OK;
		break;
	default:
		gensec_security = auth->auth_ctx;
		status = add_generic_auth_footer(gensec_security,
						 auth->auth_level,
						 rpc_out);
		break;
	}

	return status;
}
Exemplo n.º 26
0
NTSTATUS cli_do_rpc_ndr(struct rpc_pipe_client *cli,
			TALLOC_CTX *mem_ctx,
			const struct ndr_interface_table *table,
			uint32 opnum, void *r)
{
#ifdef AVM_SMALL
	return NT_STATUS_NO_MEMORY;
#else
	prs_struct q_ps, r_ps;
	const struct ndr_interface_call *call;
	struct ndr_pull *pull;
	DATA_BLOB blob;
	struct ndr_push *push;
	NTSTATUS status;
	enum ndr_err_code ndr_err;

	SMB_ASSERT(ndr_syntax_id_equal(&table->syntax_id,
				       &cli->abstract_syntax));
	SMB_ASSERT(table->num_calls > opnum);

	call = &table->calls[opnum];

	push = ndr_push_init_ctx(mem_ctx);
	if (!push) {
		return NT_STATUS_NO_MEMORY;
	}

	ndr_err = call->ndr_push(push, NDR_IN, r);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ndr_map_error2ntstatus(ndr_err);
	}

	blob = ndr_push_blob(push);

	if (!prs_init_data_blob(&q_ps, &blob, mem_ctx)) {
		return NT_STATUS_NO_MEMORY;
	}

	talloc_free(push);

	prs_init_empty( &r_ps, mem_ctx, UNMARSHALL );
	
	status = rpc_api_pipe_req(cli, opnum, &q_ps, &r_ps); 

	prs_mem_free( &q_ps );

	if (!NT_STATUS_IS_OK(status)) {
		prs_mem_free( &r_ps );
		return status;
	}

	if (!prs_data_blob(&r_ps, &blob, mem_ctx)) {
		prs_mem_free( &r_ps );
		return NT_STATUS_NO_MEMORY;
	}

	prs_mem_free( &r_ps );

	pull = ndr_pull_init_blob(&blob, mem_ctx);
	if (pull == NULL) {
		return NT_STATUS_NO_MEMORY;
	}

	/* have the ndr parser alloc memory for us */
	pull->flags |= LIBNDR_FLAG_REF_ALLOC;
	ndr_err = call->ndr_pull(pull, NDR_OUT, r);
	talloc_free(pull);

	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		return ndr_map_error2ntstatus(ndr_err);
	}

	return NT_STATUS_OK;
#endif
}
Exemplo n.º 27
0
const char *cli_errstr(struct cli_state *cli)
{
    fstring cli_error_message;
    uint32 flgs2 = SVAL(cli->inbuf,smb_flg2), errnum;
    uint8 errclass;
    int i;
    char *result;

    if (!cli->initialised) {
        fstrcpy(cli_error_message, "[Programmer's error] cli_errstr called on unitialized cli_stat struct!\n");
        goto done;
    }

    /* Was it server socket error ? */
    if (cli->fd == -1 && cli->smb_rw_error) {
        switch(cli->smb_rw_error) {
        case SMB_READ_TIMEOUT:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Call timed out: server did not respond after %d milliseconds",
                     cli->timeout);
            break;
        case SMB_READ_EOF:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Call returned zero bytes (EOF)" );
            break;
        case SMB_READ_ERROR:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Read error: %s", strerror(errno) );
            break;
        case SMB_WRITE_ERROR:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Write error: %s", strerror(errno) );
            break;
        case SMB_READ_BAD_SIG:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Server packet had invalid SMB signature!");
            break;
        case SMB_NO_MEMORY:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Out of memory");
            break;
        default:
            slprintf(cli_error_message, sizeof(cli_error_message) - 1,
                     "Unknown error code %d\n", cli->smb_rw_error );
            break;
        }
        goto done;
    }

    /* Case #1: RAP error */
    if (cli->rap_error) {
        for (i = 0; rap_errmap[i].message != NULL; i++) {
            if (rap_errmap[i].err == cli->rap_error) {
                return rap_errmap[i].message;
            }
        }

        slprintf(cli_error_message, sizeof(cli_error_message) - 1, "RAP code %d",
                 cli->rap_error);

        goto done;
    }

    /* Case #2: 32-bit NT errors */
    if (flgs2 & FLAGS2_32_BIT_ERROR_CODES) {
        NTSTATUS status = NT_STATUS(IVAL(cli->inbuf,smb_rcls));

        return nt_errstr(status);
    }

    cli_dos_error(cli, &errclass, &errnum);

    /* Case #3: SMB error */

    return cli_smb_errstr(cli);

done:
    result = talloc_strdup(talloc_tos(), cli_error_message);
    SMB_ASSERT(result);
    return result;
}
Exemplo n.º 28
0
static NTSTATUS ipv4_connect(struct socket_context *sock,
			     const struct socket_address *my_address, 
			     const struct socket_address *srv_address,
			     uint32_t flags)
{
	struct sockaddr_in srv_addr;
	struct in_addr my_ip;
	struct in_addr srv_ip;
	int ret;

	if (my_address && my_address->sockaddr) {
		ret = bind(sock->fd, my_address->sockaddr, my_address->sockaddrlen);
		if (ret == -1) {
			return map_nt_error_from_unix(errno);
		}
	} else if (my_address) {
		my_ip = interpret_addr2(my_address->addr);
		
		if (my_ip.s_addr != 0 || my_address->port != 0) {
			struct sockaddr_in my_addr;
			ZERO_STRUCT(my_addr);
#ifdef HAVE_SOCK_SIN_LEN
			my_addr.sin_len		= sizeof(my_addr);
#endif
			my_addr.sin_addr.s_addr	= my_ip.s_addr;
			my_addr.sin_port	= htons(my_address->port);
			my_addr.sin_family	= PF_INET;
			
			ret = bind(sock->fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
			if (ret == -1) {
				return map_nt_error_from_unix(errno);
			}
		}
	}

	if (srv_address->sockaddr) {
		ret = connect(sock->fd, srv_address->sockaddr, srv_address->sockaddrlen);
		if (ret == -1) {
			return map_nt_error_from_unix(errno);
		}
	} else {
		srv_ip = interpret_addr2(srv_address->addr);
		if (!srv_ip.s_addr) {
			return NT_STATUS_BAD_NETWORK_NAME;
		}

		SMB_ASSERT(srv_address->port != 0);
		
		ZERO_STRUCT(srv_addr);
#ifdef HAVE_SOCK_SIN_LEN
		srv_addr.sin_len	= sizeof(srv_addr);
#endif
		srv_addr.sin_addr.s_addr= srv_ip.s_addr;
		srv_addr.sin_port	= htons(srv_address->port);
		srv_addr.sin_family	= PF_INET;

		ret = connect(sock->fd, (const struct sockaddr *)&srv_addr, sizeof(srv_addr));
		if (ret == -1) {
			return map_nt_error_from_unix(errno);
		}
	}

	return ip_connect_complete(sock, flags);
}
Exemplo n.º 29
0
/* This function MUST only used to create the cached server_info for
 * guest.
 *
 * This is a lossy conversion.  Variables known to be lost so far
 * include:
 *
 * - nss_token (not needed because the only read doesn't happen
 * for the GUEST user, as this routine populates ->security_token
 *
 * - extra (not needed because the guest account must have valid RIDs per the output of get_guest_info3())
 *
 * - The 'server_info' parameter allows the missing 'info3' to be copied across.
 */
static struct auth_serversupplied_info *copy_session_info_serverinfo_guest(TALLOC_CTX *mem_ctx,
									   const struct auth_session_info *src,
									   struct auth_serversupplied_info *server_info)
{
	struct auth_serversupplied_info *dst;

	dst = make_server_info(mem_ctx);
	if (dst == NULL) {
		return NULL;
	}

	/* This element must be provided to convert back to an auth_serversupplied_info */
	SMB_ASSERT(src->unix_info);

	dst->guest = true;
	dst->system = false;

	/* This element must be provided to convert back to an
	 * auth_serversupplied_info.  This needs to be from the
	 * auth_session_info because the group values in particular
	 * may change during create_local_token() processing */
	SMB_ASSERT(src->unix_token);
	dst->utok.uid = src->unix_token->uid;
	dst->utok.gid = src->unix_token->gid;
	dst->utok.ngroups = src->unix_token->ngroups;
	if (src->unix_token->ngroups != 0) {
		dst->utok.groups = (gid_t *)talloc_memdup(
			dst, src->unix_token->groups,
			sizeof(gid_t)*dst->utok.ngroups);
	} else {
		dst->utok.groups = NULL;
	}

	/* We must have a security_token as otherwise the lossy
	 * conversion without nss_token would cause create_local_token
	 * to take the wrong path */
	SMB_ASSERT(src->security_token);

	dst->security_token = dup_nt_token(dst, src->security_token);
	if (!dst->security_token) {
		TALLOC_FREE(dst);
		return NULL;
	}

	dst->session_key = data_blob_talloc( dst, src->session_key.data,
						src->session_key.length);

	/* This is OK because this functions is only used for the
	 * GUEST account, which has all-zero keys for both values */
	dst->lm_session_key = data_blob_talloc(dst, src->session_key.data,
						src->session_key.length);

	dst->info3 = copy_netr_SamInfo3(dst, server_info->info3);
	if (!dst->info3) {
		TALLOC_FREE(dst);
		return NULL;
	}

	dst->unix_name = talloc_strdup(dst, src->unix_info->unix_name);
	if (!dst->unix_name) {
		TALLOC_FREE(dst);
		return NULL;
	}

	return dst;
}
Exemplo n.º 30
0
static void handle_main_input(struct regedit *regedit, int c)
{
	switch (c) {
	case 18: { /* CTRL-R */
		struct tree_node *root, *node;
		const char **path;

		node = tree_view_get_current_node(regedit->keys);
		path = tree_node_get_path(regedit, node);
		SMB_ASSERT(path != NULL);

		root = tree_node_new_root(regedit, regedit->registry_context);
		SMB_ASSERT(root != NULL);

		tree_view_set_root(regedit->keys, root);
		tree_view_set_path(regedit->keys, path);
		node = tree_view_get_current_node(regedit->keys);
		value_list_load(regedit->vl, node->key);
		tree_view_show(regedit->keys);
		value_list_show(regedit->vl);
		print_path(regedit, node);
		talloc_free(discard_const(path));
		break;
	}
	case 'f':
	case 'F':
	case '/': {
		int rv;
		struct regedit_search_opts *opts;
		struct tree_node *node;

		opts = &regedit->active_search;
		rv = dialog_search_input(regedit, opts);
		if (rv == DIALOG_OK) {
			SMB_ASSERT(opts->query != NULL);
			opts->match = find_substring_nocase;
			node = regedit->keys->root->child_head;
			if (opts->search_case) {
				opts->match = find_substring;
			}
			if (!opts->search_recursive) {
				node = tree_view_get_current_node(regedit->keys);
				node = tree_node_first(node);
			}
			regedit_search(regedit, node, NULL, SEARCH_NEXT);
		}
		break;
	}
	case 'x':
		regedit_search_repeat(regedit, SEARCH_NEXT);
		break;
	case 'X':
		regedit_search_repeat(regedit, SEARCH_PREV);
		break;
	case '\t':
		regedit->tree_input = !regedit->tree_input;
		print_heading(regedit);
		break;
	default:
		if (regedit->tree_input) {
			handle_tree_input(regedit, c);
		} else {
			handle_value_input(regedit, c);
		}
	}
}