s4:s3compat Add a wrapper for auth_ntlmssp the calls directly to GENSEC
authorAndrew Bartlett <abartlet@samba.org>
Tue, 1 Jun 2010 09:13:17 +0000 (19:13 +1000)
committerAndrew Bartlett <abartlet@samba.org>
Thu, 3 Jun 2010 11:57:47 +0000 (21:57 +1000)
This allows us to use the same stack for all server-side NTLMSSP in
s3compat.

Andrew Bartlett

source4/s3compat/auth_ntlmssp.c [new file with mode: 0644]
source4/s3compat/s3compat_authenticate.c
source4/s3compat/wscript_build

diff --git a/source4/s3compat/auth_ntlmssp.c b/source4/s3compat/auth_ntlmssp.c
new file mode 100644 (file)
index 0000000..03b8c56
--- /dev/null
@@ -0,0 +1,194 @@
+/*
+   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);
+}
+
index 003082278a2b7493c0b85c89685c751f3fd03986..e3d27e344a6154cd5c80c425434839443d2b034d 100644 (file)
@@ -270,3 +270,55 @@ NTSTATUS s3compat_authsam_expand_nested_groups(struct ldb_context *sam_ctx,
 {
        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;
+}
index 6ecc58f4a87af28b7cb36b4e005d48b6a88ffe1c..a76fd0ff39ea82b418acac27742786f5e43eb731 100644 (file)
@@ -496,7 +496,7 @@ AUTH_BASE_SRC = '''${SLCACHE_SRC} auth/user_info.c
                    auth/token_util.c'''
 
 AUTH_SRC = '''${AUTH_SRC1} auth/auth.c ${AUTH_STATIC} auth/auth_util.c 
-           auth/auth_compat.c auth/auth_ntlmssp.c 
+           auth/auth_compat.c 
            ${PLAINTEXT_AUTH_SRC}'''
 
 
@@ -850,7 +850,8 @@ bld.SAMBA_SUBSYSTEM('s3_winbind',
 bld.SAMBA_SUBSYSTEM('s3compat_wrapper',
                     includes=SAMBA3_INCLUDES,
                     autoproto='s3compat_wrapper_proto.h',
-                    source='s3compat.c s3compat_winbindd.c auth_samba4.c pdb_samba4.c idmap_samba4.c',
+                    source='''s3compat.c s3compat_winbindd.c auth_samba4.c
+                              auth_ntlmssp.c pdb_samba4.c idmap_samba4.c''',
                     deps='tdb tevent ldb SAMDB_COMMON',
                     hide_symbols=True)