This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
+ the Free Software Foundation; either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "includes.h"
#include "auth/credentials/credentials.h"
#include "librpc/gen_ndr/ndr_samr.h"
#include "lib/util/dlinklist.h"
-#include "libcli/util/asn_1.h"
+#include "lib/util/asn1.h"
#include "ldap_server/ldap_server.h"
#include "smbd/service_task.h"
#include "smbd/service_stream.h"
#include "system/network.h"
#include "lib/socket/netif.h"
#include "dsdb/samdb/samdb.h"
+#include "param/param.h"
/*
close the socket and shutdown a server_context
*/
/* build all the replies into a single blob */
while (call->replies) {
DATA_BLOB b;
+ bool ret;
msg = call->replies->msg;
if (!ldap_encode(msg, &b, call)) {
return;
}
- status = data_blob_append(call, &blob, b.data, b.length);
+ ret = data_blob_append(call, &blob, b.data, b.length);
data_blob_free(&b);
talloc_set_name_const(blob.data, "Outgoing, encoded LDAP packet");
- if (!NT_STATUS_IS_OK(status)) {
+ if (!ret) {
talloc_free(call);
return;
}
conn->connection = c;
conn->service = ldapsrv_service;
conn->sockets.raw = c->socket;
+ conn->lp_ctx = ldapsrv_service->task->lp_ctx;
c->private = conn;
conn->sockets.tls = tls_socket;
} else if (port == 3268) /* Global catalog */ {
- conn->global_catalog = True;
+ conn->global_catalog = true;
}
conn->packet = packet_init(conn);
if (conn->packet == NULL) {
/* Ensure we don't get packets until the database is ready below */
packet_recv_disable(conn->packet);
- server_credentials
- = cli_credentials_init(conn);
+ server_credentials = cli_credentials_init(conn);
if (!server_credentials) {
stream_terminate_connection(c, "Failed to init server credentials\n");
return;
}
- cli_credentials_set_conf(server_credentials);
- status = cli_credentials_set_machine_account(server_credentials);
+ cli_credentials_set_conf(server_credentials, conn->lp_ctx);
+ status = cli_credentials_set_machine_account(server_credentials, conn->lp_ctx);
if (!NT_STATUS_IS_OK(status)) {
stream_terminate_connection(c, talloc_asprintf(conn, "Failed to obtain server credentials, perhaps a standalone server?: %s\n", nt_errstr(status)));
return;
conn->server_credentials = server_credentials;
/* Connections start out anonymous */
- if (!NT_STATUS_IS_OK(auth_anonymous_session_info(conn, &conn->session_info))) {
+ if (!NT_STATUS_IS_OK(auth_anonymous_session_info(conn, conn->lp_ctx, &conn->session_info))) {
ldapsrv_terminate_connection(conn, "failed to setup anonymous session info");
return;
}
add a socket address to the list of events, one event per port
*/
static NTSTATUS add_socket(struct event_context *event_context,
+ struct loadparm_context *lp_ctx,
const struct model_ops *model_ops,
const char *address, struct ldapsrv_service *ldap_service)
{
uint16_t port = 389;
NTSTATUS status;
- const char *attrs[] = { "options", NULL };
- int ret;
- struct ldb_result *res;
struct ldb_context *ldb;
- int options;
- status = stream_setup_socket(event_context, model_ops, &ldap_stream_ops,
- "ipv4", address, &port, ldap_service);
+ status = stream_setup_socket(event_context, lp_ctx,
+ model_ops, &ldap_stream_ops,
+ "ipv4", address, &port,
+ lp_socket_options(lp_ctx),
+ ldap_service);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
if (tls_support(ldap_service->tls_params)) {
/* add ldaps server */
port = 636;
- status = stream_setup_socket(event_context, model_ops, &ldap_stream_ops,
- "ipv4", address, &port, ldap_service);
+ status = stream_setup_socket(event_context, lp_ctx,
+ model_ops, &ldap_stream_ops,
+ "ipv4", address, &port,
+ lp_socket_options(lp_ctx),
+ ldap_service);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
}
/* Load LDAP database */
- ldb = samdb_connect(ldap_service, system_session(ldap_service));
+ ldb = samdb_connect(ldap_service, lp_ctx, system_session(ldap_service, lp_ctx));
if (!ldb) {
return NT_STATUS_INTERNAL_DB_CORRUPTION;
}
- /* Query cn=ntds settings,.... */
- ret = ldb_search(ldb, samdb_ntds_settings_dn(ldb), LDB_SCOPE_BASE, NULL, attrs, &res);
- if (ret) {
- return NT_STATUS_INTERNAL_DB_CORRUPTION;
- }
- if (res->count != 1) {
- talloc_free(res);
- return NT_STATUS_NOT_FOUND;
- }
-
- options = ldb_msg_find_attr_as_int(res->msgs[0], "options", 0);
- talloc_free(res);
- talloc_free(ldb);
-
- /* if options attribute has the 0x00000001 flag set, then enable the global catlog */
- if (options & 0x000000001) {
+ if (samdb_is_gc(ldb)) {
port = 3268;
- status = stream_setup_socket(event_context, model_ops, &ldap_stream_ops,
- "ipv4", address, &port, ldap_service);
+ status = stream_setup_socket(event_context, lp_ctx,
+ model_ops, &ldap_stream_ops,
+ "ipv4", address, &port,
+ lp_socket_options(lp_ctx),
+ ldap_service);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(0,("ldapsrv failed to bind to %s:%u - %s\n",
address, port, nt_errstr(status)));
*/
static void ldapsrv_task_init(struct task_server *task)
{
+ char *ldapi_path;
struct ldapsrv_service *ldap_service;
NTSTATUS status;
const struct model_ops *model_ops;
+ switch (lp_server_role(task->lp_ctx)) {
+ case ROLE_STANDALONE:
+ task_server_terminate(task, "ldap_server: no LDAP server required in standalone configuration");
+ return;
+ case ROLE_DOMAIN_MEMBER:
+ task_server_terminate(task, "ldap_server: no LDAP server required in member server configuration");
+ return;
+ case ROLE_DOMAIN_CONTROLLER:
+ /* Yes, we want an LDAP server */
+ break;
+ }
+
task_server_set_title(task, "task[ldapsrv]");
/* run the ldap server as a single process */
ldap_service = talloc_zero(task, struct ldapsrv_service);
if (ldap_service == NULL) goto failed;
- ldap_service->tls_params = tls_initialise(ldap_service);
+ ldap_service->task = task;
+
+ ldap_service->tls_params = tls_initialise(ldap_service, task->lp_ctx);
if (ldap_service->tls_params == NULL) goto failed;
- if (lp_interfaces() && lp_bind_interfaces_only()) {
- int num_interfaces = iface_count();
+ if (lp_interfaces(task->lp_ctx) && lp_bind_interfaces_only(task->lp_ctx)) {
+ struct interface *ifaces;
+ int num_interfaces;
int i;
+ load_interfaces(task, lp_interfaces(task->lp_ctx), &ifaces);
+ num_interfaces = iface_count(ifaces);
+
/* 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.
*/
for(i = 0; i < num_interfaces; i++) {
- const char *address = iface_n_ip(i);
- status = add_socket(task->event_ctx, model_ops, address, ldap_service);
+ const char *address = iface_n_ip(ifaces, i);
+ status = add_socket(task->event_ctx, task->lp_ctx, model_ops, address, ldap_service);
if (!NT_STATUS_IS_OK(status)) goto failed;
}
} else {
- status = add_socket(task->event_ctx, model_ops, lp_socket_address(), ldap_service);
+ status = add_socket(task->event_ctx, task->lp_ctx, model_ops,
+ lp_socket_address(task->lp_ctx), ldap_service);
if (!NT_STATUS_IS_OK(status)) goto failed;
}
+ ldapi_path = private_path(ldap_service, task->lp_ctx, "ldapi");
+ if (!ldapi_path) {
+ goto failed;
+ }
+
+ status = stream_setup_socket(task->event_ctx, task->lp_ctx,
+ model_ops, &ldap_stream_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:
listening on all configured sockets
*/
static NTSTATUS ldapsrv_init(struct event_context *event_context,
+ struct loadparm_context *lp_ctx,
const struct model_ops *model_ops)
{
- return task_server_startup(event_context, model_ops, ldapsrv_task_init);
+ return task_server_startup(event_context, lp_ctx, "ldap", model_ops,
+ ldapsrv_task_init);
}