--- /dev/null
+/*
+ Unix SMB/CIFS implementation.
+ Authenticate an NTLMSSP client against Samba4's auth subsystem
+ Copyright (C) Andrew Bartlett 2010
+
+ 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 3 of the License, or
+ (at your option) any later version.
+
+ This program is distributed in the hope that it will be useful,
+ but WITHOUT ANY WARRANTY; without even the implied warranty of
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ 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, see <http://www.gnu.org/licenses/>.
+*/
+
+#include "includes.h"
+#include "s3compat/s3compat_authenticate.h"
+#include "../auth/ntlmssp/ntlmssp.h"
+#include "auth/gensec/gensec.h"
+
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_AUTH
+
+struct auth_ntlmssp_state {
+ struct gensec_security *gensec_security;
+};
+
+struct auth_serversupplied_info *auth_ntlmssp_server_info(TALLOC_CTX *mem_ctx,
+ struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ struct auth_serversupplied_info *server_info;
+ struct netr_SamInfo3 *info3 = NULL;
+ NTSTATUS status;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ return NULL;
+ }
+
+ status = s3compat_gensec_session_info_info3(tmp_ctx,
+ auth_ntlmssp_state->gensec_security, &info3);
+ DEBUG(10, ("s3compat_gensec_session_info_info3 returned %s\n", nt_errstr(status)));
+
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ return NULL;
+ }
+
+ status = make_server_info_info3(tmp_ctx, info3->base.account_name.string,
+ NULL, /* unused, our 'info3' is perfectly formed */
+ &server_info,
+ info3);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(tmp_ctx);
+ DEBUG(10, ("make_server_info_info3 failed: %s\n",
+ nt_errstr(status)));
+ return NULL;
+ }
+
+ /* TODO: Fill in the full list of groups from the full list we
+ * have in the session_info, to avoid a double-lookup */
+
+ /* This looks up the groups via the Samba3 local group lookup code, which we also hook */
+
+
+ /* We don't do
+
+ auth_ntlmssp_state->server_info->nss_token |= username_was_mapped;
+
+ as we always have winbind around, and we don't want to make
+ up a local token, we want to use the domain SIDs
+ provided */
+
+ status = create_local_token(server_info);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(10, ("create_local_token failed: %s\n",
+ nt_errstr(status)));
+ return NULL;
+ }
+
+ return talloc_steal(mem_ctx, server_info);
+}
+
+struct ntlmssp_state *auth_ntlmssp_get_ntlmssp_state(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ struct gensec_ntlmssp_context *gensec_ntlmssp =
+ talloc_get_type_abort(auth_ntlmssp_state->gensec_security->private_data,
+ struct gensec_ntlmssp_context);
+ return gensec_ntlmssp->ntlmssp_state;
+}
+
+const char *auth_ntlmssp_get_username(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ struct ntlmssp_state *ntlmssp_state = auth_ntlmssp_get_ntlmssp_state(auth_ntlmssp_state);
+ return ntlmssp_state->user;
+}
+const char *auth_ntlmssp_get_domain(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ struct ntlmssp_state *ntlmssp_state = auth_ntlmssp_get_ntlmssp_state(auth_ntlmssp_state);
+ return ntlmssp_state->domain;
+}
+const char *auth_ntlmssp_get_client(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ struct ntlmssp_state *ntlmssp_state = auth_ntlmssp_get_ntlmssp_state(auth_ntlmssp_state);
+ return ntlmssp_state->client.netbios_name;
+}
+bool auth_ntlmssp_negotiated_sign(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return gensec_have_feature(auth_ntlmssp_state->gensec_security, GENSEC_FEATURE_SIGN);
+}
+
+bool auth_ntlmssp_negotiated_seal(struct auth_ntlmssp_state *auth_ntlmssp_state)
+{
+ return gensec_have_feature(auth_ntlmssp_state->gensec_security, GENSEC_FEATURE_SEAL);
+}
+
+NTSTATUS auth_ntlmssp_start(struct auth_ntlmssp_state **auth_ntlmssp_state)
+{
+ NTSTATUS status;
+ *auth_ntlmssp_state = talloc_zero(NULL, struct auth_ntlmssp_state);
+ NT_STATUS_HAVE_NO_MEMORY(*auth_ntlmssp_state);
+
+ status = s3compat_samba_server_gensec_start(*auth_ntlmssp_state, &(*auth_ntlmssp_state)->gensec_security);
+ if (!NT_STATUS_IS_OK(status)) {
+ talloc_free(*auth_ntlmssp_state);
+ return status;
+ }
+ return gensec_start_mech_by_sasl_name((*auth_ntlmssp_state)->gensec_security, GENSEC_SASL_NAME_NTLMSSP);
+}
+
+void auth_ntlmssp_end(struct auth_ntlmssp_state **auth_ntlmssp_state)
+{
+ talloc_free(*auth_ntlmssp_state);
+ *auth_ntlmssp_state = NULL;
+}
+
+NTSTATUS auth_ntlmssp_update(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ const DATA_BLOB request, DATA_BLOB *reply)
+{
+ return gensec_update(auth_ntlmssp_state->gensec_security, auth_ntlmssp_state, request, reply);
+}
+
+NTSTATUS auth_ntlmssp_sign_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ TALLOC_CTX *sig_mem_ctx,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig)
+{
+ return gensec_sign_packet(auth_ntlmssp_state->gensec_security,
+ sig_mem_ctx,
+ data, length,
+ whole_pdu, pdu_length,
+ sig);
+}
+NTSTATUS auth_ntlmssp_check_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ const uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig)
+{
+ return gensec_check_packet(auth_ntlmssp_state->gensec_security,
+ auth_ntlmssp_state, /* hopefully unused */
+ data, length,
+ whole_pdu, pdu_length,
+ sig);
+}
+NTSTATUS auth_ntlmssp_seal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ TALLOC_CTX *sig_mem_ctx,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ DATA_BLOB *sig)
+{
+ return gensec_seal_packet(auth_ntlmssp_state->gensec_security,
+ sig_mem_ctx,
+ data, length,
+ whole_pdu, pdu_length,
+ sig);
+}
+
+NTSTATUS auth_ntlmssp_unseal_packet(struct auth_ntlmssp_state *auth_ntlmssp_state,
+ uint8_t *data, size_t length,
+ const uint8_t *whole_pdu, size_t pdu_length,
+ const DATA_BLOB *sig)
+{
+ return gensec_unseal_packet(auth_ntlmssp_state->gensec_security,
+ auth_ntlmssp_state, /* hopefully unused */
+ data, length,
+ whole_pdu, pdu_length,
+ sig);
+}
+
{
return authsam_expand_nested_groups(sam_ctx, dn_val, only_childs, filter, res_sids_ctx, res_sids, num_res_sids);
}
+
+/* Return only the 'info3' part of the session_info generated by a successful authentication */
+NTSTATUS s3compat_gensec_session_info_info3(TALLOC_CTX *mem_ctx,
+ struct gensec_security *gensec_server_context,
+ struct netr_SamInfo3 **info3)
+{
+ NTSTATUS nt_status;
+ struct auth_session_info *session_info;
+ nt_status = gensec_session_info(gensec_server_context, &session_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ return nt_status;
+ }
+
+ return auth_convert_server_info_saminfo3(mem_ctx,
+ session_info->server_info,
+ info3);
+}
+
+NTSTATUS s3compat_samba_server_gensec_start(TALLOC_CTX *mem_ctx,
+ struct gensec_security **gensec_security)
+{
+ struct cli_credentials *server_credentials;
+ TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+ NTSTATUS status;
+ struct loadparm_context *lp_ctx = s3compat_get_lp_ctx();
+ NT_STATUS_HAVE_NO_MEMORY(tmp_ctx);
+
+ server_credentials = cli_credentials_init(tmp_ctx);
+ NT_STATUS_HAVE_NO_MEMORY_AND_FREE(server_credentials, tmp_ctx);
+
+ 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(1, ("Failed to obtain server credentials, can not validate a Kerberos ticket: %s\n",
+ nt_errstr(status)));
+ talloc_free(tmp_ctx);
+ return status;
+ }
+
+ status = samba_server_gensec_start(tmp_ctx,
+ s3compat_get_tevent_ctx(),
+ s3compat_get_msg_ctx(),
+ lp_ctx,
+ server_credentials,
+ "host",
+ gensec_security);
+ if (NT_STATUS_IS_OK(status)) {
+ talloc_steal(mem_ctx, *gensec_security);
+ }
+ talloc_free(tmp_ctx);
+ return status;
+}