#include "includes.h"
#include "ldap_server/ldap_server.h"
#include "auth/auth.h"
-#include "libcli/ldap/ldap.h"
#include "smbd/service.h"
-#include "lib/ldb/include/ldb.h"
-#include "lib/ldb/include/ldb_errors.h"
+#include <ldb.h>
+#include <ldb_errors.h>
#include "dsdb/samdb/samdb.h"
#include "auth/gensec/gensec.h"
+#include "auth/gensec/gensec_tstream.h"
#include "param/param.h"
+#include "../lib/util/tevent_ntstatus.h"
static NTSTATUS ldapsrv_BindSimple(struct ldapsrv_call *call)
{
call->conn->lp_ctx,
nt4_domain, nt4_account,
req->creds.password,
+ MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT |
+ MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT,
&session_info);
}
result = LDAP_SUCCESS;
errstr = NULL;
- talloc_free(call->conn->session_info);
+ talloc_unlink(call->conn, call->conn->session_info);
call->conn->session_info = session_info;
talloc_steal(call->conn, session_info);
/* don't leak the old LDB */
- talloc_free(call->conn->ldb);
+ talloc_unlink(call->conn, call->conn->ldb);
status = ldapsrv_backend_Init(call->conn);
return NT_STATUS_OK;
}
-struct ldapsrv_sasl_context {
+struct ldapsrv_sasl_postprocess_context {
struct ldapsrv_connection *conn;
- struct socket_context *sasl_socket;
+ struct tstream_context *sasl;
};
-static void ldapsrv_set_sasl(void *private)
+struct ldapsrv_sasl_postprocess_state {
+ uint8_t dummy;
+};
+
+static struct tevent_req *ldapsrv_sasl_postprocess_send(TALLOC_CTX *mem_ctx,
+ struct tevent_context *ev,
+ void *private_data)
{
- struct ldapsrv_sasl_context *ctx = talloc_get_type(private, struct ldapsrv_sasl_context);
- talloc_steal(ctx->conn->connection, ctx->sasl_socket);
- talloc_unlink(ctx->conn->connection, ctx->conn->connection->socket);
+ struct ldapsrv_sasl_postprocess_context *context =
+ talloc_get_type_abort(private_data,
+ struct ldapsrv_sasl_postprocess_context);
+ struct tevent_req *req;
+ struct ldapsrv_sasl_postprocess_state *state;
+
+ req = tevent_req_create(mem_ctx, &state,
+ struct ldapsrv_sasl_postprocess_state);
+ if (req == NULL) {
+ return NULL;
+ }
+
+ TALLOC_FREE(context->conn->sockets.sasl);
+ context->conn->sockets.sasl = talloc_move(context->conn, &context->sasl);
+ context->conn->sockets.active = context->conn->sockets.sasl;
- ctx->conn->sockets.sasl = ctx->sasl_socket;
- ctx->conn->connection->socket = ctx->sasl_socket;
- packet_set_socket(ctx->conn->packet, ctx->conn->connection->socket);
+ tevent_req_done(req);
+ return tevent_req_post(req, ev);
+}
+
+static NTSTATUS ldapsrv_sasl_postprocess_recv(struct tevent_req *req)
+{
+ return tevent_req_simple_recv_ntstatus(req);
}
static NTSTATUS ldapsrv_BindSASL(struct ldapsrv_call *call)
if (!conn->gensec) {
conn->session_info = NULL;
- status = gensec_server_start(conn,
- conn->connection->event.ctx,
- conn->lp_ctx,
- conn->connection->msg_ctx,
- &conn->gensec);
+ status = samba_server_gensec_start(conn,
+ conn->connection->event.ctx,
+ conn->connection->msg_ctx,
+ conn->lp_ctx,
+ conn->server_credentials,
+ "ldap",
+ &conn->gensec);
if (!NT_STATUS_IS_OK(status)) {
DEBUG(1, ("Failed to start GENSEC server code: %s\n", nt_errstr(status)));
result = LDAP_OPERATIONS_ERROR;
errstr = talloc_asprintf(reply, "SASL: Failed to start authentication system: %s",
nt_errstr(status));
} else {
-
- gensec_set_target_service(conn->gensec, "ldap");
-
- gensec_set_credentials(conn->gensec, conn->server_credentials);
-
+
gensec_want_feature(conn->gensec, GENSEC_FEATURE_SIGN);
gensec_want_feature(conn->gensec, GENSEC_FEATURE_SEAL);
gensec_want_feature(conn->gensec, GENSEC_FEATURE_ASYNC_REPLIES);
input = *req->creds.SASL.secblob;
}
- resp->SASL.secblob = talloc(reply, DATA_BLOB);
- NT_STATUS_HAVE_NO_MEMORY(resp->SASL.secblob);
-
status = gensec_update(conn->gensec, reply,
input, &output);
errstr = NULL;
} else if (NT_STATUS_IS_OK(status)) {
struct auth_session_info *old_session_info=NULL;
- struct ldapsrv_sasl_context *ctx;
+ struct ldapsrv_sasl_postprocess_context *context = NULL;
result = LDAP_SUCCESS;
errstr = NULL;
- ctx = talloc(call, struct ldapsrv_sasl_context);
+ if (gensec_have_feature(conn->gensec, GENSEC_FEATURE_SIGN) ||
+ gensec_have_feature(conn->gensec, GENSEC_FEATURE_SEAL)) {
- if (!ctx) {
- status = NT_STATUS_NO_MEMORY;
- } else {
- ctx->conn = conn;
- status = gensec_socket_init(conn->gensec,
- conn->connection->socket,
- conn->connection->event.ctx,
- stream_io_handler_callback,
- conn->connection,
- &ctx->sasl_socket);
- }
-
- if (!ctx || !NT_STATUS_IS_OK(status)) {
+ context = talloc(call, struct ldapsrv_sasl_postprocess_context);
+
+ if (!context) {
+ status = NT_STATUS_NO_MEMORY;
+ }
+ }
+
+ if (context && conn->sockets.tls) {
+ TALLOC_FREE(context);
+ status = NT_STATUS_NOT_SUPPORTED;
+ result = LDAP_UNWILLING_TO_PERFORM;
+ errstr = talloc_asprintf(reply,
+ "SASL:[%s]: Sign or Seal are not allowed if TLS is used",
+ req->creds.SASL.mechanism);
+ }
+
+ if (context && conn->sockets.sasl) {
+ TALLOC_FREE(context);
+ status = NT_STATUS_NOT_SUPPORTED;
+ result = LDAP_UNWILLING_TO_PERFORM;
+ errstr = talloc_asprintf(reply,
+ "SASL:[%s]: Sign or Seal are not allowed if SASL encryption has already been set up",
+ req->creds.SASL.mechanism);
+ }
+
+ if (context) {
+ context->conn = conn;
+ status = gensec_create_tstream(context,
+ context->conn->gensec,
+ context->conn->sockets.raw,
+ &context->sasl);
+ if (NT_STATUS_IS_OK(status)) {
+ if (!talloc_reference(context->sasl, conn->gensec)) {
+ status = NT_STATUS_NO_MEMORY;
+ }
+ }
+ }
+
+ if (result != LDAP_SUCCESS) {
+ conn->session_info = old_session_info;
+ } else if (!NT_STATUS_IS_OK(status)) {
conn->session_info = old_session_info;
result = LDAP_OPERATIONS_ERROR;
errstr = talloc_asprintf(reply,
req->creds.SASL.mechanism, nt_errstr(status));
} else {
- call->send_callback = ldapsrv_set_sasl;
- call->send_private = ctx;
-
old_session_info = conn->session_info;
conn->session_info = NULL;
status = gensec_session_info(conn->gensec, &conn->session_info);
"SASL:[%s]: Failed to get session info: %s",
req->creds.SASL.mechanism, nt_errstr(status));
} else {
- talloc_free(old_session_info);
+ talloc_unlink(conn, old_session_info);
talloc_steal(conn, conn->session_info);
/* don't leak the old LDB */
- talloc_free(conn->ldb);
+ talloc_unlink(conn, conn->ldb);
status = ldapsrv_backend_Init(conn);
}
}
}
+
+ if (NT_STATUS_IS_OK(status) && context) {
+ call->postprocess_send = ldapsrv_sasl_postprocess_send;
+ call->postprocess_recv = ldapsrv_sasl_postprocess_recv;
+ call->postprocess_private = context;
+ }
+ talloc_unlink(conn, conn->gensec);
+ conn->gensec = NULL;
} else {
status = auth_nt_status_squash(status);
if (result == 0) {
result = LDAP_INVALID_CREDENTIALS;
errstr = talloc_asprintf(reply, "SASL:[%s]: %s", req->creds.SASL.mechanism, nt_errstr(status));
}
+ talloc_unlink(conn, conn->gensec);
+ conn->gensec = NULL;
}
resp->response.resultcode = result;