Example #1
0
/*
 * Hook to allow handling of NTLM authentication for AD operation
 * without directly linking the s4 auth stack
 *
 * This ensures we use the source4 authentication stack, as well as
 * the authorization stack to create the user's token.  This ensures
 * consistency between NTLM logins and NTLMSSP logins, as NTLMSSP is
 * handled by the hook above.
 */
static NTSTATUS make_auth4_context_s4(TALLOC_CTX *mem_ctx,
				      struct auth4_context **auth4_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct imessaging_context *msg_ctx;
	struct server_id *server_id;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(frame);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_id = new_server_id_task(frame);
	if (server_id == NULL) {
		DEBUG(1, ("new_server_id_task failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_init(frame,
				  lp_ctx,
				  *server_id,
				  event_ctx, true);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	talloc_reparent(frame, msg_ctx, server_id);

	status = auth_context_create(mem_ctx,
					event_ctx,
					msg_ctx,
					lp_ctx,
					auth4_context);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start auth server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, *auth4_context, msg_ctx);
	talloc_reparent(frame, *auth4_context, event_ctx);
	talloc_reparent(frame, *auth4_context, lp_ctx);

	TALLOC_FREE(frame);
	return status;
}
Example #2
0
File: winbindd.c Project: hef/samba
struct imessaging_context *winbind_imessaging_context(void)
{
	static struct imessaging_context *msg = NULL;
	struct loadparm_context *lp_ctx;

	if (msg != NULL) {
		return msg;
	}

	lp_ctx = loadparm_init_s3(NULL, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		smb_panic("Could not load smb.conf to init winbindd's imessaging context.\n");
	}

	/*
	 * Note we MUST use the NULL context here, not the autofree context,
	 * to avoid side effects in forked children exiting.
	 */
	msg = imessaging_init(NULL, lp_ctx, procid_self(), winbind_event_context(), false);
	talloc_unlink(NULL, lp_ctx);

	if (msg == NULL) {
		smb_panic("Could not init winbindd's messaging context.\n");
	}
	return msg;
}
Example #3
0
/*
  setup messaging for the top level samba (parent) task
 */
static NTSTATUS setup_parent_messaging(struct tevent_context *event_ctx, 
				       struct loadparm_context *lp_ctx)
{
	struct imessaging_context *msg;
	NTSTATUS status;

	msg = imessaging_init(talloc_autofree_context(),
			      lpcfg_imessaging_path(event_ctx, lp_ctx),
			      cluster_id(0, SAMBA_PARENT_TASKID), event_ctx, false);
	NT_STATUS_HAVE_NO_MEMORY(msg);

	irpc_add_name(msg, "samba");

	status = IRPC_REGISTER(msg, irpc, SAMBA_TERMINATE,
			       samba_terminate, NULL);

	return status;
}
Example #4
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_hostsallow(NULL, lpcfg_default_service(lp_ctx)), lpcfg_hostsdeny(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,
					    lpcfg_imessaging_path(srv_conn, lp_ctx),
					    srv_conn->server_id, ev, false);
	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;

		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(tmp_ctx, &server_id));
		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);
}
Example #5
0
/*
 * Hook to allow handling of NTLM authentication for AD operation
 * without directly linking the s4 auth stack
 *
 * This ensures we use the source4 authentication stack, as well as
 * the authorization stack to create the user's token.  This ensures
 * consistency between NTLM logins and NTLMSSP logins, as NTLMSSP is
 * handled by the hook above.
 */
static NTSTATUS make_auth4_context_s4(const struct auth_context *auth_context,
				      TALLOC_CTX *mem_ctx,
				      struct auth4_context **auth4_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct imessaging_context *msg_ctx;
	struct server_id *server_id;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(frame);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_id = new_server_id_task(frame);
	if (server_id == NULL) {
		DEBUG(1, ("new_server_id_task failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_init(frame,
				  lp_ctx,
				  *server_id,
				  event_ctx, true);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	talloc_reparent(frame, msg_ctx, server_id);

	/* Allow forcing a specific auth4 module */
	if (!auth_context->forced_samba4_methods) {
		status = auth_context_create(mem_ctx,
					     event_ctx,
					     msg_ctx,
					     lp_ctx,
					     auth4_context);
	} else {
		const char * const *forced_auth_methods = (const char * const *)str_list_make(mem_ctx, auth_context->forced_samba4_methods, NULL);
		status = auth_context_create_methods(mem_ctx, forced_auth_methods, event_ctx, msg_ctx, lp_ctx, NULL, auth4_context);
	}
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start auth server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, *auth4_context, msg_ctx);
	talloc_reparent(frame, *auth4_context, event_ctx);
	talloc_reparent(frame, *auth4_context, lp_ctx);

	TALLOC_FREE(frame);
	return status;
}
Example #6
0
/*
 * Hook to allow the source4 set of GENSEC modules to handle
 * blob-based authentication mechanisms, without directly linking the
 * mechanism code.
 *
 * This may eventually go away, when the GSSAPI acceptors are merged,
 * when we will just rely on the make_auth4_context_s4 hook instead.
 *
 * Even for NTLMSSP, which has a common module, significant parts of
 * the behaviour are overridden here, because it uses the source4 NTLM
 * stack and the source4 mapping between the PAC/SamLogon response and
 * the local token.
 *
 * It is important to override all this to ensure that the exact same
 * token is generated and used in the SMB and LDAP servers, for NTLM
 * and for Kerberos.
 */
static NTSTATUS prepare_gensec(const struct auth_context *auth_context,
			       TALLOC_CTX *mem_ctx,
			       struct gensec_security **gensec_context)
{
	NTSTATUS status;
	struct loadparm_context *lp_ctx;
	struct tevent_context *event_ctx;
	TALLOC_CTX *frame = talloc_stackframe();
	struct gensec_security *gensec_ctx;
	struct imessaging_context *msg_ctx;
	struct cli_credentials *server_credentials;
	struct server_id *server_id;

	lp_ctx = loadparm_init_s3(frame, loadparm_s3_helpers());
	if (lp_ctx == NULL) {
		DEBUG(1, ("loadparm_init_s3 failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}
	event_ctx = s4_event_context_init(frame);
	if (event_ctx == NULL) {
		DEBUG(1, ("s4_event_context_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	server_id = new_server_id_task(frame);
	if (server_id == NULL) {
		DEBUG(1, ("new_server_id_task failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	msg_ctx = imessaging_init(frame,
				  lp_ctx,
				  *server_id,
				  event_ctx, true);
	if (msg_ctx == NULL) {
		DEBUG(1, ("imessaging_init failed\n"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	talloc_reparent(frame, msg_ctx, server_id);

	server_credentials
		= cli_credentials_init(frame);
	if (!server_credentials) {
		DEBUG(1, ("Failed to init server credentials"));
		TALLOC_FREE(frame);
		return NT_STATUS_INVALID_SERVER_STATE;
	}

	cli_credentials_set_conf(server_credentials, lp_ctx);
	status = cli_credentials_set_machine_account(server_credentials, lp_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(10, ("Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	status = samba_server_gensec_start(mem_ctx,
					   event_ctx, msg_ctx,
					   lp_ctx, server_credentials, "cifs",
					   &gensec_ctx);
	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
		TALLOC_FREE(frame);
		return status;
	}

	talloc_reparent(frame, gensec_ctx, msg_ctx);
	talloc_reparent(frame, gensec_ctx, event_ctx);
	talloc_reparent(frame, gensec_ctx, lp_ctx);
	talloc_reparent(frame, gensec_ctx, server_credentials);

	gensec_want_feature(gensec_ctx, GENSEC_FEATURE_SESSION_KEY);
	gensec_want_feature(gensec_ctx, GENSEC_FEATURE_UNIX_TOKEN);

	*gensec_context = gensec_ctx;
	TALLOC_FREE(frame);
	return status;
}
Example #7
0
/*
  test ping speed
*/
static bool test_ping_speed(struct torture_context *tctx)
{
	struct tevent_context *ev;
	struct imessaging_context *msg_client_ctx;
	struct imessaging_context *msg_server_ctx;
	int ping_count = 0;
	int pong_count = 0;
	struct timeval tv;
	int timelimit = torture_setting_int(tctx, "timelimit", 10);
	uint32_t msg_ping, msg_exit;

	lpcfg_set_cmdline(tctx->lp_ctx, "pid directory", "piddir.tmp");

	ev = tctx->ev;

	msg_server_ctx = imessaging_init(tctx,
					 tctx->lp_ctx, cluster_id(0, 1),
					 ev, true);
	
	torture_assert(tctx, msg_server_ctx != NULL, "Failed to init ping messaging context");
		
	imessaging_register_tmp(msg_server_ctx, NULL, ping_message, &msg_ping);
	imessaging_register_tmp(msg_server_ctx, tctx, exit_message, &msg_exit);

	msg_client_ctx = imessaging_init(tctx,
					 tctx->lp_ctx,
					 cluster_id(0, 2),
					 ev, true);

	torture_assert(tctx, msg_client_ctx != NULL, 
		       "msg_client_ctx imessaging_init() failed");

	imessaging_register_tmp(msg_client_ctx, &pong_count, pong_message, &msg_pong);

	tv = timeval_current();

	torture_comment(tctx, "Sending pings for %d seconds\n", timelimit);
	while (timeval_elapsed(&tv) < timelimit) {
		DATA_BLOB data;
		NTSTATUS status1, status2;

		data.data = discard_const_p(uint8_t, "testing");
		data.length = strlen((const char *)data.data);

		status1 = imessaging_send(msg_client_ctx, cluster_id(0, 1), msg_ping, &data);
		status2 = imessaging_send(msg_client_ctx, cluster_id(0, 1), msg_ping, NULL);

		torture_assert_ntstatus_ok(tctx, status1, "msg1 failed");
		ping_count++;

		torture_assert_ntstatus_ok(tctx, status2, "msg2 failed");
		ping_count++;

		while (ping_count > pong_count + 20) {
			tevent_loop_once(ev);
		}
	}

	torture_comment(tctx, "waiting for %d remaining replies (done %d)\n", 
	       ping_count - pong_count, pong_count);
	while (timeval_elapsed(&tv) < 30 && pong_count < ping_count) {
		tevent_loop_once(ev);
	}

	torture_comment(tctx, "sending exit\n");
	imessaging_send(msg_client_ctx, cluster_id(0, 1), msg_exit, NULL);

	torture_assert_int_equal(tctx, ping_count, pong_count, "ping test failed");

	torture_comment(tctx, "ping rate of %.0f messages/sec\n", 
	       (ping_count+pong_count)/timeval_elapsed(&tv));

	talloc_free(msg_client_ctx);
	talloc_free(msg_server_ctx);

	return true;
}
Example #8
0
static bool test_messaging_overflow(struct torture_context *tctx)
{
	struct imessaging_context *msg_ctx;
	ssize_t nwritten, nread;
	pid_t child;
	char c = 0;
	int up_pipe[2], down_pipe[2];
	int i, ret, child_status;

	ret = pipe(up_pipe);
	torture_assert(tctx, ret == 0, "pipe failed");
	ret = pipe(down_pipe);
	torture_assert(tctx, ret == 0, "pipe failed");

	child = fork();
	if (child < 0) {
		torture_fail(tctx, "fork failed");
	}

	if (child == 0) {
		ret = tevent_re_initialise(tctx->ev);
		torture_assert(tctx, ret == 0, "tevent_re_initialise failed");

		msg_ctx = imessaging_init(tctx, tctx->lp_ctx,
					  cluster_id(getpid(), 0),
					  tctx->ev);
		torture_assert(tctx, msg_ctx != NULL,
			       "imessaging_init failed");

		do {
			nwritten = write(up_pipe[1], &c, 1);
		} while ((nwritten == -1) && (errno == EINTR));

		ret = close(down_pipe[1]);
		torture_assert(tctx, ret == 0, "close failed");

		do {
			nread = read(down_pipe[0], &c, 1);
		} while ((nread == -1) && (errno == EINTR));

		exit(0);
	}

	do {
		nread = read(up_pipe[0], &c, 1);
	} while ((nread == -1) && (errno == EINTR));

	msg_ctx = imessaging_init(tctx, tctx->lp_ctx, cluster_id(getpid(), 0),
				  tctx->ev);
	torture_assert(tctx, msg_ctx != NULL, "imessaging_init failed");

	for (i=0; i<1000; i++) {
		NTSTATUS status;
		status = imessaging_send(msg_ctx, cluster_id(child, 0),
					 MSG_PING, NULL);
		torture_assert_ntstatus_ok(tctx, status,
					   "imessaging_send failed");
	}

	tevent_loop_once(tctx->ev);

	talloc_free(msg_ctx);

	ret = close(down_pipe[1]);
	torture_assert(tctx, ret == 0, "close failed");

	ret = waitpid(child, &child_status, 0);
	torture_assert(tctx, ret == child, "wrong child exited");
	torture_assert(tctx, child_status == 0, "child failed");

	poll(NULL, 0, 500);

	return true;
}