summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAndrew Bartlett <abartlet@samba.org>2011-12-31 22:57:18 +1100
committerStefan Metzmacher <metze@samba.org>2012-01-18 16:23:21 +0100
commitf8c9ae3615cf0c463bd2bff1531894612b574930 (patch)
treeb8efc946191b9934d26eb935b0e8f71ffec34060
parentd2bf6af1651c44b29d69be6944cd6148d90caed0 (diff)
downloadsamba-f8c9ae3615cf0c463bd2bff1531894612b574930.tar.gz
samba-f8c9ae3615cf0c463bd2bff1531894612b574930.tar.bz2
samba-f8c9ae3615cf0c463bd2bff1531894612b574930.zip
s3-auth Add auth hook for PAC parsing
This will allow gensec_gse to parse the PAC. This is a copy from source3/rpc_server/dcesrv_generic.c to preserve behaviour. A future commit will enable the samlogon cache. Andrew Bartlett Signed-off-by: Stefan Metzmacher <metze@samba.org>
-rw-r--r--source3/auth/auth_generic.c130
1 files changed, 128 insertions, 2 deletions
diff --git a/source3/auth/auth_generic.c b/source3/auth/auth_generic.c
index d7108f5cbf..1f1aeb5aa0 100644
--- a/source3/auth/auth_generic.c
+++ b/source3/auth/auth_generic.c
@@ -1,10 +1,11 @@
/*
Unix SMB/Netbios implementation.
Version 3.0
- handle NLTMSSP, server side
+ handle GENSEC authentication, server side
Copyright (C) Andrew Tridgell 2001
Copyright (C) Andrew Bartlett 2001-2003,2011
+ Copyright (C) Simo Sorce 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
@@ -25,6 +26,122 @@
#include "../lib/tsocket/tsocket.h"
#include "auth/gensec/gensec.h"
#include "lib/param/param.h"
+#ifdef HAVE_KRB5
+#include "libcli/auth/krb5_wrap.h"
+#endif
+
+static NTSTATUS auth3_generate_session_info_pac(struct auth4_context *auth_ctx,
+ TALLOC_CTX *mem_ctx,
+ struct smb_krb5_context *smb_krb5_context,
+ DATA_BLOB *pac_blob,
+ const char *princ_name,
+ const struct tsocket_address *remote_address,
+ uint32_t session_info_flags,
+ struct auth_session_info **session_info)
+{
+ TALLOC_CTX *tmp_ctx;
+ struct PAC_DATA *pac_data = NULL;
+ struct PAC_LOGON_INFO *logon_info = NULL;
+ unsigned int i;
+ bool is_mapped;
+ bool is_guest;
+ char *ntuser;
+ char *ntdomain;
+ char *username;
+ char *rhost;
+ struct passwd *pw;
+ NTSTATUS status;
+ int rc;
+
+ tmp_ctx = talloc_new(mem_ctx);
+ if (!tmp_ctx) {
+ return NT_STATUS_NO_MEMORY;
+ }
+
+ if (pac_blob) {
+#ifdef HAVE_KRB5
+ status = kerberos_decode_pac(tmp_ctx,
+ *pac_blob,
+ NULL, NULL, NULL, NULL, 0, &pac_data);
+#else
+ status = NT_STATUS_ACCESS_DENIED;
+#endif
+ if (!NT_STATUS_IS_OK(status)) {
+ goto done;
+ }
+
+ /* get logon name and logon info */
+ for (i = 0; i < pac_data->num_buffers; i++) {
+ struct PAC_BUFFER *data_buf = &pac_data->buffers[i];
+
+ switch (data_buf->type) {
+ case PAC_TYPE_LOGON_INFO:
+ if (!data_buf->info) {
+ break;
+ }
+ logon_info = data_buf->info->logon_info.info;
+ break;
+ default:
+ break;
+ }
+ }
+ if (!logon_info) {
+ DEBUG(1, ("Invalid PAC data, missing logon info!\n"));
+ status = NT_STATUS_NOT_FOUND;
+ goto done;
+ }
+ }
+
+ rc = get_remote_hostname(remote_address,
+ &rhost,
+ tmp_ctx);
+ if (rc < 0) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ if (strequal(rhost, "UNKNOWN")) {
+ rhost = tsocket_address_inet_addr_string(remote_address,
+ tmp_ctx);
+ if (rhost == NULL) {
+ status = NT_STATUS_NO_MEMORY;
+ goto done;
+ }
+ }
+
+ status = get_user_from_kerberos_info(tmp_ctx, rhost,
+ princ_name, logon_info,
+ &is_mapped, &is_guest,
+ &ntuser, &ntdomain,
+ &username, &pw);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to map kerberos principal to system user "
+ "(%s)\n", nt_errstr(status)));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
+ /* TODO: save PAC data in netsamlogon cache ? */
+
+ status = make_session_info_krb5(mem_ctx,
+ ntuser, ntdomain, username, pw,
+ logon_info, is_guest, is_mapped, NULL /* No session key for now, caller will sort it out */,
+ session_info);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(1, ("Failed to map kerberos pac to server info (%s)\n",
+ nt_errstr(status)));
+ status = NT_STATUS_ACCESS_DENIED;
+ goto done;
+ }
+
+ DEBUG(5, (__location__ "OK: user: %s domain: %s client: %s\n",
+ ntuser, ntdomain, rhost));
+
+ status = NT_STATUS_OK;
+
+done:
+ TALLOC_FREE(tmp_ctx);
+ return status;
+}
NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
const struct tsocket_address *remote_address,
@@ -54,6 +171,14 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
struct gensec_settings *gensec_settings;
struct loadparm_context *lp_ctx;
+ struct auth4_context *auth4_context = talloc_zero(tmp_ctx, struct auth4_context);
+ if (auth4_context == NULL) {
+ DEBUG(10, ("failed to allocate auth4_context failed\n"));
+ TALLOC_FREE(tmp_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
+ auth4_context->generate_session_info_pac = auth3_generate_session_info_pac;
+
lp_ctx = loadparm_init_s3(tmp_ctx, loadparm_s3_context());
if (lp_ctx == NULL) {
DEBUG(10, ("loadparm_init_s3 failed\n"));
@@ -77,7 +202,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
gensec_settings->backends[0] = &gensec_ntlmssp3_server_ops;
nt_status = gensec_server_start(tmp_ctx, gensec_settings,
- NULL, &gensec_security);
+ auth4_context, &gensec_security);
if (!NT_STATUS_IS_OK(nt_status)) {
TALLOC_FREE(tmp_ctx);
@@ -85,6 +210,7 @@ NTSTATUS auth_generic_prepare(TALLOC_CTX *mem_ctx,
}
talloc_unlink(tmp_ctx, lp_ctx);
talloc_unlink(tmp_ctx, gensec_settings);
+ talloc_unlink(tmp_ctx, auth4_context);
}
nt_status = gensec_set_remote_address(gensec_security,