示例#1
0
文件: server.c 项目: aoa141/samba
static void msg_inject_fault(struct messaging_context *msg,
			     void *private_data,
			     uint32_t msg_type,
			     struct server_id src,
			     DATA_BLOB *data)
{
	int sig;
	struct server_id_buf tmp;

	if (data->length != sizeof(sig)) {
		DEBUG(0, ("Process %s sent bogus signal injection request\n",
			  server_id_str_buf(src, &tmp)));
		return;
	}

	sig = *(int *)data->data;
	if (sig == -1) {
		exit_server("internal error injected");
		return;
	}

#if HAVE_STRSIGNAL
	DEBUG(0, ("Process %s requested injection of signal %d (%s)\n",
		  server_id_str_buf(src, &tmp), sig, strsignal(sig)));
#else
	DEBUG(0, ("Process %s requested injection of signal %d\n",
		  server_id_str_buf(src, &tmp), sig));
#endif

	kill(getpid(), sig);
}
示例#2
0
static int smbd_scavenger_main(struct smbd_scavenger_state *state)
{
	struct server_id_buf tmp1, tmp2;

	DEBUG(10, ("scavenger: %s started, parent: %s\n",
		   server_id_str_buf(*state->scavenger_id, &tmp1),
		   server_id_str_buf(state->parent_id, &tmp2)));

	while (true) {
		TALLOC_CTX *frame = talloc_stackframe();
		int ret;

		ret = tevent_loop_once(state->ev);
		if (ret != 0) {
			DEBUG(2, ("tevent_loop_once failed: %s\n",
				  strerror(errno)));
			TALLOC_FREE(frame);
			return 1;
		}

		DEBUG(10, ("scavenger: %s event loop iteration\n",
			   server_id_str_buf(*state->scavenger_id, &tmp1)));
		TALLOC_FREE(frame);
	}

	return 0;
}
示例#3
0
static void smbd_scavenger_msg(struct messaging_context *msg_ctx,
			       void *private_data,
			       uint32_t msg_type,
			       struct server_id src,
			       DATA_BLOB *data)
{
	struct smbd_scavenger_state *state =
		talloc_get_type_abort(private_data,
				      struct smbd_scavenger_state);
	TALLOC_CTX *frame = talloc_stackframe();
	struct server_id self = messaging_server_id(msg_ctx);
	struct scavenger_message *msg = NULL;
	struct server_id_buf tmp1, tmp2;

	DEBUG(10, ("smbd_scavenger_msg: %s got message from %s\n",
		   server_id_str_buf(self, &tmp1),
		   server_id_str_buf(src, &tmp2)));

	if (server_id_equal(&state->parent_id, &self)) {
		NTSTATUS status;

		if (!smbd_scavenger_running(state) &&
		    !smbd_scavenger_start(state))
		{
			DEBUG(2, ("Failed to start scavenger\n"));
			goto done;
		}
		DEBUG(10, ("forwarding message to scavenger\n"));

		status = messaging_send(msg_ctx,
					*state->scavenger_id, msg_type, data);
		if (!NT_STATUS_IS_OK(status)) {
			DEBUG(2, ("forwarding message to scavenger failed: "
				  "%s\n", nt_errstr(status)));
			goto done;
		}
		goto done;
	}

	if (!state->am_scavenger) {
		DEBUG(10, ("im not the scavenger: ignore message\n"));
		goto done;
	}

	if (!server_id_equal(&state->parent_id, &src)) {
		DEBUG(10, ("scavenger: ignore spurious message\n"));
		goto done;
	}

	DEBUG(10, ("scavenger: got a message\n"));
	msg = (struct scavenger_message*)data->data;
	scavenger_add_timer(state, msg);
done:
	talloc_free(frame);
}
示例#4
0
void scavenger_schedule_disconnected(struct files_struct *fsp)
{
	NTSTATUS status;
	struct server_id self = messaging_server_id(fsp->conn->sconn->msg_ctx);
	struct timeval disconnect_time, until;
	uint64_t timeout_usec;
	struct scavenger_message msg;
	DATA_BLOB msg_blob;
	struct server_id_buf tmp;

	if (fsp->op == NULL) {
		return;
	}
	nttime_to_timeval(&disconnect_time, fsp->op->global->disconnect_time);
	timeout_usec = 1000 * fsp->op->global->durable_timeout_msec;
	until = timeval_add(&disconnect_time,
			    timeout_usec / 1000000,
			    timeout_usec % 1000000);

	ZERO_STRUCT(msg);
	msg.file_id = fsp->file_id;
	msg.open_persistent_id = fsp->op->global->open_persistent_id;
	msg.until = timeval_to_nttime(&until);

	DEBUG(10, ("smbd: %s mark file %s as disconnected at %s with timeout "
		   "at %s in %fs\n",
		   server_id_str_buf(self, &tmp),
		   file_id_string_tos(&fsp->file_id),
		   timeval_string(talloc_tos(), &disconnect_time, true),
		   timeval_string(talloc_tos(), &until, true),
		   fsp->op->global->durable_timeout_msec/1000.0));

	SMB_ASSERT(server_id_is_disconnected(&fsp->op->global->server_id));
	SMB_ASSERT(!server_id_equal(&self, &smbd_scavenger_state->parent_id));
	SMB_ASSERT(!smbd_scavenger_state->am_scavenger);

	msg_blob = data_blob_const(&msg, sizeof(msg));
	DEBUG(10, ("send message to scavenger\n"));

	status = messaging_send(smbd_scavenger_state->msg,
				smbd_scavenger_state->parent_id,
				MSG_SMB_SCAVENGER,
				&msg_blob);
	if (!NT_STATUS_IS_OK(status)) {
		struct server_id_buf tmp1, tmp2;
		DEBUG(2, ("Failed to send message to parent smbd %s "
			  "from %s: %s\n",
			  server_id_str_buf(smbd_scavenger_state->parent_id,
					    &tmp1),
			  server_id_str_buf(self, &tmp2),
			  nt_errstr(status)));
	}
}
示例#5
0
static void smbd_scavenger_parent_dead(struct tevent_context *event_ctx,
				       struct tevent_fd *fde,
				       uint16_t flags, void *private_data)
{
	struct smbd_scavenger_state *state = talloc_get_type_abort(
		private_data, struct smbd_scavenger_state);
	struct server_id_buf tmp1, tmp2;

	DEBUG(2, ("scavenger: %s parent %s died\n",
		  server_id_str_buf(*state->scavenger_id, &tmp1),
		  server_id_str_buf(state->parent_id, &tmp2)));

	exit_server("smbd_scavenger_parent_dead");
}
/*
   return the path to a messaging socket
*/
static char *imessaging_path(struct imessaging_context *msg, struct server_id server_id)
{
	struct server_id_buf buf;

	return talloc_asprintf(msg, "%s/msg.%s", msg->base_path,
			       server_id_str_buf(server_id, &buf));
}
示例#7
0
static int net_serverid_list_fn(const struct server_id *id,
				uint32_t msg_flags, void *priv)
{
	struct server_id_buf idbuf;
	d_printf("%s %llu 0x%x\n", server_id_str_buf(*id, &idbuf),
		 (unsigned long long)id->unique_id,
		 (unsigned int)msg_flags);
	return 0;
}
/*
 A useful function for testing the message system.
*/
static void ping_message(struct imessaging_context *msg, void *private_data,
			 uint32_t msg_type, struct server_id src, DATA_BLOB *data)
{
	struct server_id_buf idbuf;
	DEBUG(1,("INFO: Received PING message from server %s [%.*s]\n",
		 server_id_str_buf(src, &idbuf), (int)data->length,
		 data->data?(const char *)data->data:""));
	imessaging_send(msg, src, MSG_PONG, data);
}
示例#9
0
static void pong_cb(struct messaging_context *msg,
		    void *private_data, 
		    uint32_t msg_type, 
		    struct server_id pid,
		    DATA_BLOB *data)
{
	struct server_id_buf src_string;
	printf("PONG from pid %s\n", server_id_str_buf(pid, &src_string));
	num_replies++;
}
示例#10
0
static void smbd_scavenger_done(struct tevent_context *event_ctx, struct tevent_fd *fde,
			        uint16_t flags, void *private_data)
{
	struct smbd_scavenger_state *state = talloc_get_type_abort(
		private_data, struct smbd_scavenger_state);
	struct server_id_buf tmp;

	DEBUG(2, ("scavenger: %s died\n",
		  server_id_str_buf(*state->scavenger_id, &tmp)));

	TALLOC_FREE(state->scavenger_id);
}
示例#11
0
static void print_pid_string_cb(struct messaging_context *msg,
				void *private_data, 
				uint32_t msg_type, 
				struct server_id pid,
				DATA_BLOB *data)
{
	struct server_id_buf pidstr;

	printf("PID %s: %.*s", server_id_str_buf(pid, &pidstr),
	       (int)data->length, (const char *)data->data);
	num_replies++;
}
示例#12
0
static bool print_notify_rec(const char *path, struct server_id server,
			     const struct notify_instance *instance,
			     void *private_data)
{
	struct server_id_buf idbuf;

	d_printf("%s\\%s\\%x\\%x\n", path, server_id_str_buf(server, &idbuf),
		 (unsigned)instance->filter,
		 (unsigned)instance->subdir_filter);

	return true;
}
示例#13
0
/*
  make a IRPC call to the drepl task to ask it to get the RID
  Manager to give us another RID pool.

  This function just sends the message to the drepl task then
  returns immediately. It should be called well before we
  completely run out of RIDs
 */
static int ridalloc_poke_rid_manager(struct ldb_module *module)
{
	struct imessaging_context *msg;
	unsigned num_servers;
	struct server_id *servers;
	struct ldb_context *ldb = ldb_module_get_ctx(module);
	struct loadparm_context *lp_ctx =
		(struct loadparm_context *)ldb_get_opaque(ldb, "loadparm");
	TALLOC_CTX *tmp_ctx = talloc_new(module);
	NTSTATUS status;

	msg = imessaging_client_init(tmp_ctx, lp_ctx,
				    ldb_get_event_context(ldb));
	if (!msg) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID, "
				"unable init client messaging context");
		DEBUG(3,(__location__ ": Failed to create messaging context\n"));
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	status = irpc_servers_byname(msg, msg, "dreplsrv",
				     &num_servers, &servers);
	if (!NT_STATUS_IS_OK(status)) {
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID, "
				"unable to locate dreplsrv");
		/* this means the drepl service is not running */
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	status = imessaging_send(msg, servers[0], MSG_DREPL_ALLOCATE_RID, NULL);

	/* Only error out if an error happened, not on STATUS_MORE_ENTRIES, ie a delayed message */
	if (NT_STATUS_IS_ERR(status)) {
		struct server_id_buf idbuf;
		ldb_asprintf_errstring(ldb_module_get_ctx(module),
				"Failed to send MSG_DREPL_ALLOCATE_RID to dreplsrv at %s: %s",
				server_id_str_buf(*servers, &idbuf),
				nt_errstr(status));
		talloc_free(tmp_ctx);
		return LDB_ERR_UNWILLING_TO_PERFORM;
	}

	talloc_free(tmp_ctx);
	return LDB_SUCCESS;
}
示例#14
0
文件: server_id.c 项目: hef/samba
char *server_id_str(TALLOC_CTX *mem_ctx, const struct server_id *id)
{
	struct server_id_buf tmp;
	char *result;

	result = talloc_strdup(mem_ctx, server_id_str_buf(*id, &tmp));
	if (result == NULL) {
		return NULL;
	}

	/*
	 * beautify the talloc_report output
	 */
	talloc_set_name_const(result, result);
	return result;
}
示例#15
0
static int net_serverid_wipe_fn(struct db_record *rec,
				const struct server_id *id,
				uint32_t msg_flags, void *private_data)
{
	NTSTATUS status;

	if (!procid_is_local(id)) {
		return 0;
	}
	status = dbwrap_record_delete(rec);
	if (!NT_STATUS_IS_OK(status)) {
		struct server_id_buf idbuf;
		DEBUG(1, ("Could not delete serverid.tdb record %s: %s\n",
			  server_id_str_buf(*id, &idbuf), nt_errstr(status)));
	}
	return 0;
}
示例#16
0
size_t server_id_str_buf_unique(struct server_id id, char *buf, size_t buflen)
{
	struct server_id_buf idbuf;
	char unique_buf[21];	/* 2^64 is 18446744073709551616, 20 chars */
	size_t idlen, unique_len, needed;

	server_id_str_buf(id, &idbuf);

	idlen = strlen(idbuf.buf);
	unique_len = snprintf(unique_buf, sizeof(unique_buf), "%"PRIu64,
			      id.unique_id);
	needed = idlen + unique_len + 2;

	if (buflen >= needed) {
		memcpy(buf, idbuf.buf, idlen);
		buf[idlen] = '/';
		memcpy(buf + idlen + 1, unique_buf, unique_len+1);
	}

	return needed;
}
示例#17
0
static bool scavenger_wait_hello(int fd, struct server_id *child)
{
	uint8_t *msg = (uint8_t *)child;
	size_t remaining = sizeof(*child);
	size_t ofs = 0;
	struct server_id_buf tmp;

	while (remaining > 0) {
		ssize_t ret;

		ret = sys_read(fd, msg + ofs, remaining);
		if (ret == -1) {
			DEBUG(2, ("Failed to read from pipe: %s\n",
				  strerror(errno)));
			return false;
		}
		remaining -= ret;
	}

	DEBUG(4, ("scavenger_say_hello: child[%s]\n",
		  server_id_str_buf(*child, &tmp)));
	return true;
}
示例#18
0
static bool scavenger_say_hello(int fd, struct server_id self)
{
	const uint8_t *msg = (const uint8_t *)&self;
	size_t remaining = sizeof(self);
	size_t ofs = 0;
	struct server_id_buf tmp;

	while (remaining > 0) {
		ssize_t ret;

		ret = sys_write(fd, msg + ofs, remaining);
		if (ret == -1) {
			DEBUG(2, ("Failed to write to pipe: %s\n",
				  strerror(errno)));
			return false;
		}
		remaining -= ret;
	}

	DEBUG(4, ("scavenger_say_hello: self[%s]\n",
		  server_id_str_buf(self, &tmp)));
	return true;
}
示例#19
0
static void print_brl(struct file_id id,
			struct server_id pid, 
			enum brl_type lock_type,
			enum brl_flavour lock_flav,
			br_off start,
			br_off size,
			void *private_data)
{
	static int count;
	unsigned int i;
	static const struct {
		enum brl_type lock_type;
		const char *desc;
	} lock_types[] = {
		{ READ_LOCK, "R" },
		{ WRITE_LOCK, "W" },
		{ PENDING_READ_LOCK, "PR" },
		{ PENDING_WRITE_LOCK, "PW" },
		{ UNLOCK_LOCK, "U" }
	};
	const char *desc="X";
	const char *sharepath = "";
	char *fname = NULL;
	struct share_mode_lock *share_mode;
	struct server_id_buf tmp;

	if (count==0) {
		d_printf("Byte range locks:\n");
		d_printf("Pid        dev:inode       R/W  start     size      SharePath               Name\n");
		d_printf("--------------------------------------------------------------------------------\n");
	}
	count++;

	share_mode = fetch_share_mode_unlocked(NULL, id);
	if (share_mode) {
		bool has_stream = share_mode->data->stream_name != NULL;

		fname = talloc_asprintf(NULL, "%s%s%s",
					share_mode->data->base_name,
					has_stream ? ":" : "",
					has_stream ?
					share_mode->data->stream_name :
					"");
	} else {
		fname = talloc_strdup(NULL, "");
		if (fname == NULL) {
			return;
		}
	}

	for (i=0;i<ARRAY_SIZE(lock_types);i++) {
		if (lock_type == lock_types[i].lock_type) {
			desc = lock_types[i].desc;
		}
	}

	d_printf("%-10s %-15s %-4s %-9jd %-9jd %-24s %-24s\n",
		 server_id_str_buf(pid, &tmp), file_id_string_tos(&id),
		 desc,
		 (intmax_t)start, (intmax_t)size,
		 sharepath, fname);

	TALLOC_FREE(fname);
	TALLOC_FREE(share_mode);
}
示例#20
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;
}
示例#21
0
static bool do_winbind_offline(struct tevent_context *ev_ctx,
			       struct messaging_context *msg_ctx,
			       const struct server_id pid,
			       const int argc, const char **argv)
{
	TDB_CONTEXT *tdb;
	bool ret = False;
	int retry = 0;
	char *db_path;

	if (argc != 1) {
		fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
		return False;
	}

	db_path = state_path("winbindd_cache.tdb");
	if (db_path == NULL) {
		return false;
	}

	/* Create an entry in the winbindd_cache tdb to tell a later
	   starting winbindd that we're offline. We may actually create
	   it here... */

	tdb = tdb_open_log(db_path,
				WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
				TDB_DEFAULT|TDB_INCOMPATIBLE_HASH /* TDB_CLEAR_IF_FIRST */,
				O_RDWR|O_CREAT, 0600);

	if (!tdb) {
		fprintf(stderr, "Cannot open the tdb %s for writing.\n",
			db_path);
		TALLOC_FREE(db_path);
		return False;
	}
	TALLOC_FREE(db_path);

	/* There's a potential race condition that if a child
	   winbindd detects a domain is online at the same time
	   we're trying to tell it to go offline that it might 
	   delete the record we add between us adding it and
	   sending the message. Minimize this by retrying up to
	   5 times. */

	for (retry = 0; retry < 5; retry++) {
		uint8_t buf[4];
		TDB_DATA d = { .dptr = buf, .dsize = sizeof(buf) };

		SIVAL(buf, 0, time(NULL));

		tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);

		ret = send_message(msg_ctx, pid, MSG_WINBIND_OFFLINE,
				   NULL, 0);

		/* Check that the entry "WINBINDD_OFFLINE" still exists. */
		d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );

		if (!d.dptr || d.dsize != 4) {
			SAFE_FREE(d.dptr);
			DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
		} else {
			SAFE_FREE(d.dptr);
			break;
		}
	}

	tdb_close(tdb);
	return ret;
}

static bool do_winbind_onlinestatus(struct tevent_context *ev_ctx,
				    struct messaging_context *msg_ctx,
				    const struct server_id pid,
				    const int argc, const char **argv)
{
	struct server_id myid;

	myid = messaging_server_id(msg_ctx);

	if (argc != 1) {
		fprintf(stderr, "Usage: smbcontrol winbindd onlinestatus\n");
		return False;
	}

	messaging_register(msg_ctx, NULL, MSG_WINBIND_ONLINESTATUS,
			   print_pid_string_cb);

	if (!send_message(msg_ctx, pid, MSG_WINBIND_ONLINESTATUS, &myid,
			  sizeof(myid)))
		return False;

	wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);

	/* No replies were received within the timeout period */

	if (num_replies == 0)
		printf("No replies received\n");

	messaging_deregister(msg_ctx, MSG_WINBIND_ONLINESTATUS, NULL);

	return num_replies;
}

static bool do_dump_event_list(struct tevent_context *ev_ctx,
			       struct messaging_context *msg_ctx,
			       const struct server_id pid,
			       const int argc, const char **argv)
{
	if (argc != 1) {
		fprintf(stderr, "Usage: smbcontrol <dest> dump-event-list\n");
		return False;
	}

	return send_message(msg_ctx, pid, MSG_DUMP_EVENT_LIST, NULL, 0);
}

static bool do_winbind_dump_domain_list(struct tevent_context *ev_ctx,
					struct messaging_context *msg_ctx,
					const struct server_id pid,
					const int argc, const char **argv)
{
	const char *domain = NULL;
	int domain_len = 0;
	struct server_id myid;
	uint8_t *buf = NULL;
	int buf_len = 0;

	myid = messaging_server_id(msg_ctx);

	if (argc < 1 || argc > 2) {
		fprintf(stderr, "Usage: smbcontrol <dest> dump-domain-list "
			"<domain>\n");
		return false;
	}

	if (argc == 2) {
		domain = argv[1];
		domain_len = strlen(argv[1]) + 1;
	}

	messaging_register(msg_ctx, NULL, MSG_WINBIND_DUMP_DOMAIN_LIST,
			   print_pid_string_cb);

	buf_len = sizeof(myid)+domain_len;
	buf = SMB_MALLOC_ARRAY(uint8_t, buf_len);
	if (!buf) {
		return false;
	}

	memcpy(buf, &myid, sizeof(myid));
	memcpy(&buf[sizeof(myid)], domain, domain_len);

	if (!send_message(msg_ctx, pid, MSG_WINBIND_DUMP_DOMAIN_LIST,
			  buf, buf_len))
	{
		SAFE_FREE(buf);
		return false;
	}

	wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);

	/* No replies were received within the timeout period */

	SAFE_FREE(buf);
	if (num_replies == 0) {
		printf("No replies received\n");
	}

	messaging_deregister(msg_ctx, MSG_WINBIND_DUMP_DOMAIN_LIST, NULL);

	return num_replies;
}

static void winbind_validate_cache_cb(struct messaging_context *msg,
				      void *private_data,
				      uint32_t msg_type,
				      struct server_id pid,
				      DATA_BLOB *data)
{
	struct server_id_buf src_string;
	printf("Winbindd cache is %svalid. (answer from pid %s)\n",
	       (*(data->data) == 0 ? "" : "NOT "),
	       server_id_str_buf(pid, &src_string));
	num_replies++;
}

static bool do_winbind_validate_cache(struct tevent_context *ev_ctx,
				      struct messaging_context *msg_ctx,
				      const struct server_id pid,
				      const int argc, const char **argv)
{
	struct server_id myid;

	myid = messaging_server_id(msg_ctx);

	if (argc != 1) {
		fprintf(stderr, "Usage: smbcontrol winbindd validate-cache\n");
		return False;
	}

	messaging_register(msg_ctx, NULL, MSG_WINBIND_VALIDATE_CACHE,
			   winbind_validate_cache_cb);

	if (!send_message(msg_ctx, pid, MSG_WINBIND_VALIDATE_CACHE, &myid,
			  sizeof(myid))) {
		return False;
	}

	wait_replies(ev_ctx, msg_ctx, procid_to_pid(&pid) == 0);

	if (num_replies == 0) {
		printf("No replies received\n");
	}

	messaging_deregister(msg_ctx, MSG_WINBIND_VALIDATE_CACHE, NULL);

	return num_replies;
}

static bool do_reload_config(struct tevent_context *ev_ctx,
			     struct messaging_context *msg_ctx,
			     const struct server_id pid,
			     const int argc, const char **argv)
{
	if (argc != 1) {
		fprintf(stderr, "Usage: smbcontrol <dest> reload-config\n");
		return False;
	}

	return send_message(msg_ctx, pid, MSG_SMB_CONF_UPDATED, NULL, 0);
}

static bool do_reload_printers(struct tevent_context *ev_ctx,
			       struct messaging_context *msg_ctx,
			       const struct server_id pid,
			       const int argc, const char **argv)
{
	if (argc != 1) {
		fprintf(stderr, "Usage: smbcontrol <dest> reload-printers\n");
		return False;
	}

	return send_message(msg_ctx, pid, MSG_PRINTER_PCAP, NULL, 0);
}

static void my_make_nmb_name( struct nmb_name *n, const char *name, int type)
{
	fstring unix_name;
	memset( (char *)n, '\0', sizeof(struct nmb_name) );
	fstrcpy(unix_name, name);
	(void)strupper_m(unix_name);
	push_ascii(n->name, unix_name, sizeof(n->name), STR_TERMINATE);
	n->name_type = (unsigned int)type & 0xFF;
	push_ascii(n->scope,  lp_netbios_scope(), 64, STR_TERMINATE);
}
示例#22
0
static int print_share_mode(const struct share_mode_entry *e,
			    const char *sharepath,
			    const char *fname,
			    const char *sname,
			    void *dummy)
{
	static int count;

	if (do_checks && !is_valid_share_mode_entry(e)) {
		return 0;
	}

	if (count==0) {
		d_printf("Locked files:\n");
		d_printf("Pid          Uid        DenyMode   Access      R/W        Oplock           SharePath   Name   Time\n");
		d_printf("--------------------------------------------------------------------------------------------------\n");
	}
	count++;

	if (do_checks && !serverid_exists(&e->pid)) {
		/* the process for this entry does not exist any more */
		return 0;
	}

	if (Ucrit_checkPid(e->pid)) {
		struct server_id_buf tmp;
		d_printf("%-11s  ", server_id_str_buf(e->pid, &tmp));
		d_printf("%-9u  ", (unsigned int)e->uid);
		switch (map_share_mode_to_deny_mode(e->share_access,
						    e->private_options)) {
			case DENY_NONE: d_printf("DENY_NONE  "); break;
			case DENY_ALL:  d_printf("DENY_ALL   "); break;
			case DENY_DOS:  d_printf("DENY_DOS   "); break;
			case DENY_READ: d_printf("DENY_READ  "); break;
			case DENY_WRITE:printf("DENY_WRITE "); break;
			case DENY_FCB:  d_printf("DENY_FCB "); break;
			default: {
				d_printf("unknown-please report ! "
					 "e->share_access = 0x%x, "
					 "e->private_options = 0x%x\n",
					 (unsigned int)e->share_access,
					 (unsigned int)e->private_options );
				break;
			}
		}
		d_printf("0x%-8x  ",(unsigned int)e->access_mask);
		if ((e->access_mask & (FILE_READ_DATA|FILE_WRITE_DATA))==
				(FILE_READ_DATA|FILE_WRITE_DATA)) {
			d_printf("RDWR       ");
		} else if (e->access_mask & FILE_WRITE_DATA) {
			d_printf("WRONLY     ");
		} else {
			d_printf("RDONLY     ");
		}

		if((e->op_type & (EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) == 
					(EXCLUSIVE_OPLOCK|BATCH_OPLOCK)) {
			d_printf("EXCLUSIVE+BATCH ");
		} else if (e->op_type & EXCLUSIVE_OPLOCK) {
			d_printf("EXCLUSIVE       ");
		} else if (e->op_type & BATCH_OPLOCK) {
			d_printf("BATCH           ");
		} else if (e->op_type & LEVEL_II_OPLOCK) {
			d_printf("LEVEL_II        ");
		} else if (e->op_type == LEASE_OPLOCK) {
			uint32_t lstate = e->lease->current_state;
			d_printf("LEASE(%s%s%s)%s%s%s      ",
				 (lstate & SMB2_LEASE_READ)?"R":"",
				 (lstate & SMB2_LEASE_WRITE)?"W":"",
				 (lstate & SMB2_LEASE_HANDLE)?"H":"",
				 (lstate & SMB2_LEASE_READ)?"":" ",
				 (lstate & SMB2_LEASE_WRITE)?"":" ",
				 (lstate & SMB2_LEASE_HANDLE)?"":" ");
		} else {
			d_printf("NONE            ");
		}

		d_printf(" %s   %s%s   %s",
			 sharepath, fname,
			 sname ? sname : "",
			 time_to_asc((time_t)e->time.tv_sec));
	}

	return 0;
}
示例#23
0
NTSTATUS smbXsrv_open_cleanup(uint64_t persistent_id)
{
	NTSTATUS status = NT_STATUS_OK;
	TALLOC_CTX *frame = talloc_stackframe();
	struct smbXsrv_open_global0 *op = NULL;
	TDB_DATA val;
	struct db_record *rec;
	bool delete_open = false;
	uint32_t global_id = persistent_id & UINT32_MAX;

	rec = smbXsrv_open_global_fetch_locked(smbXsrv_open_global_db_ctx,
					       global_id,
					       frame);
	if (rec == NULL) {
		status = NT_STATUS_NOT_FOUND;
		goto done;
	}

	val = dbwrap_record_get_value(rec);
	if (val.dsize == 0) {
		DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
			  "empty record in %s, skipping...\n",
			   global_id, dbwrap_name(smbXsrv_open_global_db_ctx)));
		goto done;
	}

	status = smbXsrv_open_global_parse_record(talloc_tos(), rec, &op);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] "
			  "failed to read record: %s\n",
			  global_id, nt_errstr(status)));
		goto done;
	}

	if (server_id_is_disconnected(&op->server_id)) {
		struct timeval now, disconnect_time;
		int64_t tdiff;
		now = timeval_current();
		nttime_to_timeval(&disconnect_time, op->disconnect_time);
		tdiff = usec_time_diff(&now, &disconnect_time);
		delete_open = (tdiff >= 1000*op->durable_timeout_msec);

		DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
			   "disconnected at [%s] %us ago with "
			   "timeout of %us -%s reached\n",
			   global_id,
			   nt_time_string(frame, op->disconnect_time),
			   (unsigned)(tdiff/1000000),
			   op->durable_timeout_msec / 1000,
			   delete_open ? "" : " not"));
	} else if (!serverid_exists(&op->server_id)) {
		struct server_id_buf idbuf;
		DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
			   "server[%s] does not exist\n",
			   global_id,
			   server_id_str_buf(op->server_id, &idbuf)));
		delete_open = true;
	}

	if (!delete_open) {
		goto done;
	}

	status = dbwrap_record_delete(rec);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("smbXsrv_open_cleanup[global: 0x%08x] "
			  "failed to delete record"
			  "from %s: %s\n", global_id,
			  dbwrap_name(smbXsrv_open_global_db_ctx),
			  nt_errstr(status)));
		goto done;
	}

	DEBUG(10, ("smbXsrv_open_cleanup[global: 0x%08x] "
		   "delete record from %s\n",
		   global_id,
		   dbwrap_name(smbXsrv_open_global_db_ctx)));

done:
	talloc_free(frame);
	return status;
}
示例#24
0
static int traverse_connections(const struct connections_key *key,
				const struct connections_data *crec,
				void *private_data)
{
	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
	struct server_id_buf tmp;
	char *timestr = NULL;
	int result = 0;
	const char *encryption = "-";
	const char *signing = "-";

	if (crec->cnum == TID_FIELD_INVALID)
		return 0;

	if (do_checks &&
	    (!process_exists(crec->pid) || !Ucrit_checkUid(crec->uid))) {
		return 0;
	}

	timestr = timestring(mem_ctx, crec->start);
	if (timestr == NULL) {
		return -1;
	}

	if (smbXsrv_is_encrypted(crec->encryption_flags)) {
		switch (crec->cipher) {
		case SMB_ENCRYPTION_GSSAPI:
			encryption = "GSSAPI";
			break;
		case SMB2_ENCRYPTION_AES128_CCM:
			encryption = "AES-128-CCM";
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			encryption = "AES-128-GCM";
			break;
		default:
			encryption = "???";
			result = -1;
			break;
		}
	}

	if (smbXsrv_is_signed(crec->signing_flags)) {
		if (crec->dialect >= SMB3_DIALECT_REVISION_302) {
			signing = "AES-128-CMAC";
		} else if (crec->dialect >= SMB2_DIALECT_REVISION_202) {
			signing = "HMAC-SHA256";
		} else {
			signing = "HMAC-MD5";
		}
	}

	d_printf("%-12s %-7s %-13s %-32s %-12s %-12s\n",
		 crec->servicename, server_id_str_buf(crec->pid, &tmp),
		 crec->machine,
		 timestr,
		 encryption,
		 signing);

	TALLOC_FREE(timestr);

	return result;
}
示例#25
0
static int traverse_sessionid(const char *key, struct sessionid *session,
			      void *private_data)
{
	TALLOC_CTX *mem_ctx = (TALLOC_CTX *)private_data;
	fstring uid_str, gid_str;
	struct server_id_buf tmp;
	char *machine_hostname = NULL;
	int result = 0;
	const char *encryption = "-";
	const char *signing = "-";

	if (do_checks &&
	    (!process_exists(session->pid) ||
	     !Ucrit_checkUid(session->uid))) {
		return 0;
	}

	Ucrit_addPid(session->pid);

	fstrcpy(uid_str, "-1");

	if (session->uid != -1) {
		if (numeric_only) {
			fstr_sprintf(uid_str, "%u", (unsigned int)session->uid);
		} else {
			fstrcpy(uid_str, uidtoname(session->uid));
		}
	}

	fstrcpy(gid_str, "-1");

	if (session->gid != -1) {
		if (numeric_only) {
			fstr_sprintf(gid_str, "%u", (unsigned int)session->gid);
		} else {
			fstrcpy(gid_str, gidtoname(session->gid));
		}
	}

	machine_hostname = talloc_asprintf(mem_ctx, "%s (%s)",
					   session->remote_machine,
					   session->hostname);
	if (machine_hostname == NULL) {
		return -1;
	}

	if (smbXsrv_is_encrypted(session->encryption_flags)) {
		switch (session->cipher) {
		case SMB2_ENCRYPTION_AES128_CCM:
			encryption = "AES-128-CCM";
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			encryption = "AES-128-GCM";
			break;
		default:
			encryption = "???";
			result = -1;
			break;
		}
	} else if (smbXsrv_is_partially_encrypted(session->encryption_flags)) {
		switch (session->cipher) {
		case SMB_ENCRYPTION_GSSAPI:
			encryption = "partial(GSSAPI)";
			break;
		case SMB2_ENCRYPTION_AES128_CCM:
			encryption = "partial(AES-128-CCM)";
			break;
		case SMB2_ENCRYPTION_AES128_GCM:
			encryption = "partial(AES-128-GCM)";
			break;
		default:
			encryption = "???";
			result = -1;
			break;
		}
	}

	if (smbXsrv_is_signed(session->signing_flags)) {
		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
			signing = "AES-128-CMAC";
		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
			signing = "HMAC-SHA256";
		} else {
			signing = "HMAC-MD5";
		}
	} else if (smbXsrv_is_partially_signed(session->signing_flags)) {
		if (session->connection_dialect >= SMB3_DIALECT_REVISION_302) {
			signing = "partial(AES-128-CMAC)";
		} else if (session->connection_dialect >= SMB2_DIALECT_REVISION_202) {
			signing = "partial(HMAC-SHA256)";
		} else {
			signing = "partial(HMAC-MD5)";
		}
	}


	d_printf("%-7s %-12s %-12s %-41s %-17s %-20s %-21s\n",
		 server_id_str_buf(session->pid, &tmp),
		 uid_str, gid_str,
		 machine_hostname,
		 session_dialect_str(session->connection_dialect),
		 encryption,
		 signing);

	TALLOC_FREE(machine_hostname);

	return result;
}
示例#26
0
static void smbXsrv_tcon_global_verify_record(struct db_record *db_rec,
					bool *is_free,
					bool *was_free,
					TALLOC_CTX *mem_ctx,
					struct smbXsrv_tcon_global0 **_g)
{
	TDB_DATA key;
	TDB_DATA val;
	DATA_BLOB blob;
	struct smbXsrv_tcon_globalB global_blob;
	enum ndr_err_code ndr_err;
	struct smbXsrv_tcon_global0 *global = NULL;
	bool exists;
	TALLOC_CTX *frame = talloc_stackframe();

	*is_free = false;

	if (was_free) {
		*was_free = false;
	}
	if (_g) {
		*_g = NULL;
	}

	key = dbwrap_record_get_key(db_rec);

	val = dbwrap_record_get_value(db_rec);
	if (val.dsize == 0) {
		TALLOC_FREE(frame);
		*is_free = true;
		if (was_free) {
			*was_free = true;
		}
		return;
	}

	blob = data_blob_const(val.dptr, val.dsize);

	ndr_err = ndr_pull_struct_blob(&blob, frame, &global_blob,
			(ndr_pull_flags_fn_t)ndr_pull_smbXsrv_tcon_globalB);
	if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
		NTSTATUS status = ndr_map_error2ntstatus(ndr_err);
		DEBUG(1,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' ndr_pull_struct_blob - %s\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 nt_errstr(status)));
		TALLOC_FREE(frame);
		return;
	}

	DEBUG(10,("smbXsrv_tcon_global_verify_record\n"));
	if (DEBUGLVL(10)) {
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
	}

	if (global_blob.version != SMBXSRV_VERSION_0) {
		DEBUG(0,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' use unsupported version %u\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 global_blob.version));
		NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
		TALLOC_FREE(frame);
		return;
	}

	global = global_blob.info.info0;

	exists = serverid_exists(&global->server_id);
	if (!exists) {
		struct server_id_buf idbuf;
		DEBUG(2,("smbXsrv_tcon_global_verify_record: "
			 "key '%s' server_id %s does not exist.\n",
			 hex_encode_talloc(frame, key.dptr, key.dsize),
			 server_id_str_buf(global->server_id, &idbuf)));
		if (DEBUGLVL(2)) {
			NDR_PRINT_DEBUG(smbXsrv_tcon_globalB, &global_blob);
		}
		TALLOC_FREE(frame);
		dbwrap_record_delete(db_rec);
		*is_free = true;
		return;
	}

	if (_g) {
		*_g = talloc_move(mem_ctx, &global);
	}
	TALLOC_FREE(frame);
}
示例#27
0
/*
  called when a new socket connection has been established. This is called in the process
  context of the new process (if appropriate)
*/
static void stream_new_connection(struct tevent_context *ev,
				  struct loadparm_context *lp_ctx,
				  struct socket_context *sock, 
				  struct server_id server_id, void *private_data)
{
	struct stream_socket *stream_socket = talloc_get_type(private_data, struct stream_socket);
	struct stream_connection *srv_conn;

	srv_conn = talloc_zero(ev, struct stream_connection);
	if (!srv_conn) {
		DEBUG(0,("talloc(mem_ctx, struct stream_connection) failed\n"));
		return;
	}

	talloc_steal(srv_conn, sock);

	srv_conn->private_data	= stream_socket->private_data;
	srv_conn->model_ops     = stream_socket->model_ops;
	srv_conn->socket	= sock;
	srv_conn->server_id	= server_id;
	srv_conn->ops           = stream_socket->ops;
	srv_conn->event.ctx	= ev;
	srv_conn->lp_ctx	= lp_ctx;

	if (!socket_check_access(sock, "smbd", lpcfg_hosts_allow(NULL, lpcfg_default_service(lp_ctx)), lpcfg_hosts_deny(NULL, lpcfg_default_service(lp_ctx)))) {
		stream_terminate_connection(srv_conn, "denied by access rules");
		return;
	}

	srv_conn->event.fde	= tevent_add_fd(ev, srv_conn, socket_get_fd(sock),
						0, stream_io_handler_fde, srv_conn);
	if (!srv_conn->event.fde) {
		stream_terminate_connection(srv_conn, "tevent_add_fd() failed");
		return;
	}

	/* setup to receive internal messages on this connection */
	srv_conn->msg_ctx = imessaging_init(srv_conn,
					    lp_ctx,
					    srv_conn->server_id, ev);
	if (!srv_conn->msg_ctx) {
		stream_terminate_connection(srv_conn, "imessaging_init() failed");
		return;
	}

	srv_conn->remote_address = socket_get_remote_addr(srv_conn->socket, srv_conn);
	if (!srv_conn->remote_address) {
		stream_terminate_connection(srv_conn, "socket_get_remote_addr() failed");
		return;
	}

	srv_conn->local_address = socket_get_local_addr(srv_conn->socket, srv_conn);
	if (!srv_conn->local_address) {
		stream_terminate_connection(srv_conn, "socket_get_local_addr() failed");
		return;
	}

	{
		TALLOC_CTX *tmp_ctx;
		const char *title;
		struct server_id_buf idbuf;

		tmp_ctx = talloc_new(srv_conn);

		title = talloc_asprintf(tmp_ctx, "conn[%s] c[%s] s[%s] server_id[%s]",
					stream_socket->ops->name, 
					tsocket_address_string(srv_conn->remote_address, tmp_ctx),
					tsocket_address_string(srv_conn->local_address, tmp_ctx),
					server_id_str_buf(server_id, &idbuf));
		if (title) {
			stream_connection_set_title(srv_conn, title);
		}
		talloc_free(tmp_ctx);
	}

	/* we're now ready to start receiving events on this stream */
	TEVENT_FD_READABLE(srv_conn->event.fde);

	/* call the server specific accept code */
	stream_socket->ops->accept_connection(srv_conn);
}