-/*
+/*
Unix SMB/CIFS implementation.
LDAP server
#include "../libcli/util/tstream.h"
#include "libds/common/roles.h"
#include "lib/util/time.h"
+#include "lib/util/server_id.h"
+#include "lib/util/server_id_db.h"
+#include "lib/messaging/messaging_internal.h"
#undef strcasecmp
*/
static void ldapsrv_accept(struct stream_connection *c,
struct auth_session_info *session_info,
- bool is_privileged)
+ bool is_privileged,
+ bool is_ldapi)
{
- struct ldapsrv_service *ldapsrv_service =
+ struct ldapsrv_service *ldapsrv_service =
talloc_get_type(c->private_data, struct ldapsrv_service);
struct ldapsrv_connection *conn;
struct cli_credentials *server_credentials;
return;
}
conn->is_privileged = is_privileged;
+ conn->is_ldapi = is_ldapi;
- conn->sockets.send_queue = tevent_queue_create(conn, "ldapsev send queue");
+ conn->sockets.send_queue = tevent_queue_create(conn, "ldapsrv send queue");
if (conn->sockets.send_queue == NULL) {
stream_terminate_connection(c,
"ldapsrv_accept: tevent_queue_create failed");
return;
}
socket_set_flags(c->socket, SOCKET_FLAG_NOCLOSE);
+ /* as server we want to fail early */
+ tstream_bsd_fail_readv_first_error(conn->sockets.raw, true);
conn->connection = c;
conn->service = ldapsrv_service;
conn->require_strong_auth = lpcfg_ldap_server_require_strong_auth(conn->lp_ctx);
}
+ if (conn->require_strong_auth ==
+ LDAP_SERVER_REQUIRE_STRONG_AUTH_ALLOW_SASL_OVER_TLS)
+ {
+ D_ERR("WARNING: You have not configured "
+ "'ldap server require strong auth = "
+ "allow_sasl_over_tls'.\n"
+ "Please change to 'yes' (preferred and default) or "
+ "'allow_sasl_without_tls_channel_bindings' "
+ "(if really needed)\n\n");
+ }
+
ret = ldapsrv_backend_Init(conn, &errstring);
if (ret != LDB_SUCCESS) {
char *reason = talloc_asprintf(conn,
/* load limits from the conf partition */
ldapsrv_load_limits(conn); /* should we fail on error ? */
- /* register the server */
+ /* register the server */
irpc_add_name(c->msg_ctx, "ldap_server");
DLIST_ADD_END(ldapsrv_service->connections, conn);
static void ldapsrv_call_read_done(struct tevent_req *subreq);
static NTSTATUS ldapsrv_packet_check(
+ struct tstream_context *stream,
void *private_data,
DATA_BLOB blob,
size_t *packet_size);
"session info");
return;
}
- ldapsrv_accept(c, session_info, false);
+ ldapsrv_accept(c, session_info, false, false);
}
static const struct stream_server_ops ldap_stream_nonpriv_ops = {
.send_handler = ldapsrv_send,
};
+static void ldapsrv_accept_nonpriv_ldapi(struct stream_connection *c)
+{
+ struct ldapsrv_service *ldapsrv_service = talloc_get_type_abort(
+ c->private_data, struct ldapsrv_service);
+ struct auth_session_info *session_info;
+ NTSTATUS status;
+
+ status = auth_anonymous_session_info(
+ c, ldapsrv_service->lp_ctx, &session_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ stream_terminate_connection(c, "failed to setup anonymous "
+ "session info");
+ return;
+ }
+ ldapsrv_accept(c, session_info, false, true);
+}
+
+static const struct stream_server_ops ldapi_stream_nonpriv_ops = {
+ .name = "ldap",
+ .accept_connection = ldapsrv_accept_nonpriv_ldapi,
+ .recv_handler = ldapsrv_recv,
+ .send_handler = ldapsrv_send,
+};
+
/* The feature removed behind an #ifdef until we can do it properly
* with an EXTERNAL bind. */
#define WITH_LDAPI_PRIV_SOCKET
#ifdef WITH_LDAPI_PRIV_SOCKET
-static void ldapsrv_accept_priv(struct stream_connection *c)
+static void ldapsrv_accept_priv_ldapi(struct stream_connection *c)
{
struct ldapsrv_service *ldapsrv_service = talloc_get_type_abort(
c->private_data, struct ldapsrv_service);
"session info");
return;
}
- ldapsrv_accept(c, session_info, true);
+ ldapsrv_accept(c, session_info, true, true);
}
-static const struct stream_server_ops ldap_stream_priv_ops = {
+static const struct stream_server_ops ldapi_stream_priv_ops = {
.name = "ldap",
- .accept_connection = ldapsrv_accept_priv,
+ .accept_connection = ldapsrv_accept_priv_ldapi,
.recv_handler = ldapsrv_recv,
.send_handler = ldapsrv_send,
};
return NT_STATUS_OK;
}
+static void ldap_reload_certs(struct imessaging_context *msg_ctx,
+ void *private_data,
+ uint32_t msg_type,
+ struct server_id server_id,
+ size_t num_fds,
+ int *fds,
+ DATA_BLOB *data)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ struct ldapsrv_service *ldap_service =
+ talloc_get_type_abort(private_data,
+ struct ldapsrv_service);
+ int default_children;
+ int num_children;
+ int i;
+ bool ok;
+ struct server_id ldap_master_id;
+ NTSTATUS status;
+ struct tstream_tls_params *new_tls_params = NULL;
+
+ SMB_ASSERT(msg_ctx == ldap_service->current_msg);
+
+ /* reload certificates */
+ status = tstream_tls_params_server(ldap_service,
+ ldap_service->dns_host_name,
+ lpcfg_tls_enabled(ldap_service->lp_ctx),
+ lpcfg_tls_keyfile(frame, ldap_service->lp_ctx),
+ lpcfg_tls_certfile(frame, ldap_service->lp_ctx),
+ lpcfg_tls_cafile(frame, ldap_service->lp_ctx),
+ lpcfg_tls_crlfile(frame, ldap_service->lp_ctx),
+ lpcfg_tls_dhpfile(frame, ldap_service->lp_ctx),
+ lpcfg_tls_priority(ldap_service->lp_ctx),
+ &new_tls_params);
+ if (!NT_STATUS_IS_OK(status)) {
+ DBG_ERR("ldapsrv failed tstream_tls_params_server - %s\n",
+ nt_errstr(status));
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ TALLOC_FREE(ldap_service->tls_params);
+ ldap_service->tls_params = new_tls_params;
+
+ if (getpid() != ldap_service->parent_pid) {
+ /*
+ * If we are not the master process we are done
+ */
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ /*
+ * Check we're running under the prefork model,
+ * by checking if the prefork-master-ldap name
+ * was registered
+ */
+ ok = server_id_db_lookup_one(msg_ctx->names, "prefork-master-ldap", &ldap_master_id);
+ if (!ok) {
+ /*
+ * We are done if another process model is in use.
+ */
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ /*
+ * Now we loop over all possible prefork workers
+ * in order to notify them about the reload
+ */
+ default_children = lpcfg_prefork_children(ldap_service->lp_ctx);
+ num_children = lpcfg_parm_int(ldap_service->lp_ctx,
+ NULL, "prefork children", "ldap",
+ default_children);
+ for (i = 0; i < num_children; i++) {
+ char child_name[64] = { 0, };
+ struct server_id ldap_worker_id;
+
+ snprintf(child_name, sizeof(child_name), "prefork-worker-ldap-%d", i);
+ ok = server_id_db_lookup_one(msg_ctx->names, child_name, &ldap_worker_id);
+ if (!ok) {
+ DBG_ERR("server_id_db_lookup_one(%s) - failed\n",
+ child_name);
+ continue;
+ }
+
+ status = imessaging_send(msg_ctx, ldap_worker_id,
+ MSG_RELOAD_TLS_CERTIFICATES, NULL);
+ if (!NT_STATUS_IS_OK(status)) {
+ struct server_id_buf id_buf;
+ DBG_ERR("ldapsrv failed imessaging_send(%s, %s) - %s\n",
+ child_name,
+ server_id_str_buf(ldap_worker_id, &id_buf),
+ nt_errstr(status));
+ continue;
+ }
+ }
+
+ TALLOC_FREE(frame);
+}
+
/*
open the ldap server sockets
*/
static NTSTATUS ldapsrv_task_init(struct task_server *task)
-{
+{
char *ldapi_path;
#ifdef WITH_LDAPI_PRIV_SOCKET
char *priv_dir;
switch (lpcfg_server_role(task->lp_ctx)) {
case ROLE_STANDALONE:
- task_server_terminate(task, "ldap_server: no LDAP server required in standalone configuration",
+ task_server_terminate(task, "ldap_server: no LDAP server required in standalone configuration",
false);
return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_DOMAIN_MEMBER:
- task_server_terminate(task, "ldap_server: no LDAP server required in member server configuration",
+ task_server_terminate(task, "ldap_server: no LDAP server required in member server configuration",
false);
return NT_STATUS_INVALID_DOMAIN_ROLE;
case ROLE_ACTIVE_DIRECTORY_DC:
goto failed;
}
+ ldap_service->parent_pid = getpid();
+
status = tstream_tls_params_server(ldap_service,
ldap_service->dns_host_name,
lpcfg_tls_enabled(task->lp_ctx),
load_interface_list(task, task->lp_ctx, &ifaces);
num_interfaces = iface_list_count(ifaces);
- /* We have been given an interfaces line, and been
+ /* We have been given an interfaces line, and been
told to only bind to those interfaces. Create a
socket per interface and bind to only these.
*/
}
status = stream_setup_socket(task, task->event_ctx, task->lp_ctx,
- task->model_ops, &ldap_stream_nonpriv_ops,
- "unix", ldapi_path, NULL,
+ task->model_ops, &ldapi_stream_nonpriv_ops,
+ "unix", ldapi_path, NULL,
lpcfg_socket_options(task->lp_ctx),
ldap_service, task->process_context);
talloc_free(ldapi_path);
}
status = stream_setup_socket(task, task->event_ctx, task->lp_ctx,
- task->model_ops, &ldap_stream_priv_ops,
+ task->model_ops, &ldapi_stream_priv_ops,
"unix", ldapi_path, NULL,
lpcfg_socket_options(task->lp_ctx),
ldap_service,
{
struct ldapsrv_service *ldap_service =
talloc_get_type_abort(task->private_data, struct ldapsrv_service);
+ NTSTATUS status;
if (ldap_service->sam_ctx != NULL) {
/*
ldap_service->current_ev = task->event_ctx;
ldap_service->current_msg = task->msg_ctx;
}
+
+ status = imessaging_register(ldap_service->current_msg,
+ ldap_service,
+ MSG_RELOAD_TLS_CERTIFICATES,
+ ldap_reload_certs);
+ if (!NT_STATUS_IS_OK(status)) {
+ task_server_terminate(task, "Cannot register ldap_reload_certs",
+ true);
+ return;
+ }
}
/*
*
*/
static NTSTATUS ldapsrv_packet_check(
+ struct tstream_context *stream,
void *private_data,
DATA_BLOB blob,
size_t *packet_size)
struct ldapsrv_connection *conn = private_data;
int result = LDB_SUCCESS;
- ret = ldap_full_packet(private_data, blob, packet_size);
+ ret = ldap_full_packet(stream, private_data, blob, packet_size);
if (!NT_STATUS_IS_OK(ret)) {
return ret;
}