From 256b227b27b599fffe5746bae7132a27e2c59dd4 Mon Sep 17 00:00:00 2001 From: Volker Lendecke Date: Fri, 29 May 2009 10:48:54 +0200 Subject: [PATCH] Allow access as SYSTEM on a privileged ldapi connection This patch creates ldap_priv/ as a subdirectory under the private dir with the appropriate permissions to only allow the same access as the privileged winbind socket allows. Connecting to ldap_priv/ldapi gives SYSTEM access to the ldap database. --- source4/ldap_server/ldap_server.c | 96 +++++++++++++++++++++++++++++++++------ 1 file changed, 83 insertions(+), 13 deletions(-) diff --git a/source4/ldap_server/ldap_server.c b/source4/ldap_server/ldap_server.c index 38858efc7ce..36e8de68832 100644 --- a/source4/ldap_server/ldap_server.c +++ b/source4/ldap_server/ldap_server.c @@ -325,7 +325,8 @@ failed: initialise a server_context from a open socket and register a event handler for reading from that socket */ -static void ldapsrv_accept(struct stream_connection *c) +static void ldapsrv_accept(struct stream_connection *c, + struct auth_session_info *session_info) { struct ldapsrv_service *ldapsrv_service = talloc_get_type(c->private_data, struct ldapsrv_service); @@ -408,11 +409,7 @@ static void ldapsrv_accept(struct stream_connection *c) } conn->server_credentials = server_credentials; - /* Connections start out anonymous */ - if (!NT_STATUS_IS_OK(auth_anonymous_session_info(conn, c->event.ctx, conn->lp_ctx, &conn->session_info))) { - ldapsrv_terminate_connection(conn, "failed to setup anonymous session info"); - return; - } + conn->session_info = talloc_move(conn, &session_info); if (!NT_STATUS_IS_OK(ldapsrv_backend_Init(conn))) { ldapsrv_terminate_connection(conn, "backend Init failed"); @@ -434,9 +431,50 @@ static void ldapsrv_accept(struct stream_connection *c) } -static const struct stream_server_ops ldap_stream_ops = { +static void ldapsrv_accept_nonpriv(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, c->event.ctx, ldapsrv_service->task->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); +} + +static const struct stream_server_ops ldap_stream_nonpriv_ops = { + .name = "ldap", + .accept_connection = ldapsrv_accept_nonpriv, + .recv_handler = ldapsrv_recv, + .send_handler = ldapsrv_send, +}; + +static void ldapsrv_accept_priv(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_system_session_info( + c, ldapsrv_service->task->lp_ctx, &session_info); + if (!NT_STATUS_IS_OK(status)) { + stream_terminate_connection(c, "failed to setup system " + "session info"); + return; + } + ldapsrv_accept(c, session_info); +} + +static const struct stream_server_ops ldap_stream_priv_ops = { .name = "ldap", - .accept_connection = ldapsrv_accept, + .accept_connection = ldapsrv_accept_priv, .recv_handler = ldapsrv_recv, .send_handler = ldapsrv_send, }; @@ -454,7 +492,7 @@ static NTSTATUS add_socket(struct tevent_context *event_context, struct ldb_context *ldb; status = stream_setup_socket(event_context, lp_ctx, - model_ops, &ldap_stream_ops, + model_ops, &ldap_stream_nonpriv_ops, "ipv4", address, &port, lp_socket_options(lp_ctx), ldap_service); @@ -467,7 +505,8 @@ static NTSTATUS add_socket(struct tevent_context *event_context, /* add ldaps server */ port = 636; status = stream_setup_socket(event_context, lp_ctx, - model_ops, &ldap_stream_ops, + model_ops, + &ldap_stream_nonpriv_ops, "ipv4", address, &port, lp_socket_options(lp_ctx), ldap_service); @@ -487,7 +526,8 @@ static NTSTATUS add_socket(struct tevent_context *event_context, if (samdb_is_gc(ldb)) { port = 3268; status = stream_setup_socket(event_context, lp_ctx, - model_ops, &ldap_stream_ops, + model_ops, + &ldap_stream_nonpriv_ops, "ipv4", address, &port, lp_socket_options(lp_ctx), ldap_service); @@ -509,7 +549,7 @@ static NTSTATUS add_socket(struct tevent_context *event_context, */ static void ldapsrv_task_init(struct task_server *task) { - char *ldapi_path; + char *ldapi_path, *priv_dir; struct ldapsrv_service *ldap_service; NTSTATUS status; const struct model_ops *model_ops; @@ -569,7 +609,7 @@ static void ldapsrv_task_init(struct task_server *task) } status = stream_setup_socket(task->event_ctx, task->lp_ctx, - model_ops, &ldap_stream_ops, + model_ops, &ldap_stream_nonpriv_ops, "unix", ldapi_path, NULL, lp_socket_options(task->lp_ctx), ldap_service); @@ -579,6 +619,36 @@ static void ldapsrv_task_init(struct task_server *task) ldapi_path, nt_errstr(status))); } + priv_dir = private_path(ldap_service, task->lp_ctx, "ldap_priv"); + if (priv_dir == NULL) { + goto failed; + } + /* + * Make sure the directory for the privileged ldapi socket exists, and + * is of the correct permissions + */ + if (!directory_create_or_exist(priv_dir, geteuid(), 0750)) { + task_server_terminate(task, "Cannot create ldap " + "privileged ldapi directory"); + return; + } + ldapi_path = talloc_asprintf(ldap_service, "%s/ldapi", priv_dir); + talloc_free(priv_dir); + if (ldapi_path == NULL) { + goto failed; + } + + status = stream_setup_socket(task->event_ctx, task->lp_ctx, + model_ops, &ldap_stream_priv_ops, + "unix", ldapi_path, NULL, + lp_socket_options(task->lp_ctx), + ldap_service); + talloc_free(ldapi_path); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("ldapsrv failed to bind to %s - %s\n", + ldapi_path, nt_errstr(status))); + } + return; failed: -- 2.11.4.GIT