summaryrefslogtreecommitdiff
path: root/source4/auth
diff options
context:
space:
mode:
Diffstat (limited to 'source4/auth')
-rw-r--r--source4/auth/gensec/gensec_gssapi.c80
-rw-r--r--source4/auth/gensec/gensec_krb5.c184
-rw-r--r--source4/auth/kerberos/kerberos_pac.c213
-rw-r--r--source4/auth/kerberos/kerberos_verify.c2
4 files changed, 277 insertions, 202 deletions
diff --git a/source4/auth/gensec/gensec_gssapi.c b/source4/auth/gensec/gensec_gssapi.c
index 533448e06f..a95805f9fa 100644
--- a/source4/auth/gensec/gensec_gssapi.c
+++ b/source4/auth/gensec/gensec_gssapi.c
@@ -3,8 +3,8 @@
Kerberos backend for GENSEC
- Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
- Copyright (C) Stefan Metzmacher <metze@samba.org> 2005
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
+ Copyright (C) Stefan Metzmacher <metze@samba.org> 2004-2005
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
@@ -224,6 +224,7 @@ static NTSTATUS gensec_gssapi_server_start(struct gensec_security *gensec_securi
static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_security)
{
struct gensec_gssapi_state *gensec_gssapi_state;
+ struct cli_credentials *creds = gensec_get_credentials(gensec_security);
NTSTATUS nt_status;
gss_buffer_desc name_token;
OM_uint32 maj_stat, min_stat;
@@ -251,8 +252,8 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
return NT_STATUS_UNSUCCESSFUL;
}
- name_token.value = cli_credentials_get_principal(gensec_get_credentials(gensec_security),
- gensec_gssapi_state),
+ name_token.value = cli_credentials_get_principal(creds,
+ gensec_gssapi_state);
name_token.length = strlen(name_token.value);
maj_stat = gss_import_name (&min_stat,
@@ -267,7 +268,7 @@ static NTSTATUS gensec_gssapi_client_start(struct gensec_security *gensec_securi
}
nt_status = kinit_to_ccache(gensec_gssapi_state,
- gensec_get_credentials(gensec_security),
+ creds,
gensec_gssapi_state->smb_krb5_context,
&gensec_gssapi_state->ccache, &gensec_gssapi_state->ccache_name);
if (!NT_STATUS_IS_OK(nt_status)) {
@@ -724,16 +725,22 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
struct auth_session_info **_session_info)
{
NTSTATUS nt_status;
+ TALLOC_CTX *mem_ctx;
struct gensec_gssapi_state *gensec_gssapi_state = gensec_security->private_data;
struct auth_serversupplied_info *server_info = NULL;
struct auth_session_info *session_info = NULL;
+ struct PAC_LOGON_INFO *logon_info;
char *p;
char *principal;
const char *account_name;
const char *realm;
OM_uint32 maj_stat, min_stat;
gss_buffer_desc name_token;
+ gss_buffer_desc pac;
+ mem_ctx = talloc_named(gensec_gssapi_state, 0, "gensec_gssapi_session_info context");
+ NT_STATUS_HAVE_NO_MEMORY(mem_ctx);
+
maj_stat = gss_display_name (&min_stat,
gensec_gssapi_state->client_name,
&name_token,
@@ -742,11 +749,14 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
return NT_STATUS_FOOBAR;
}
- principal = talloc_strndup(gensec_gssapi_state, name_token.value, name_token.length);
+ principal = talloc_strndup(mem_ctx, name_token.value, name_token.length);
gss_release_buffer(&min_stat, &name_token);
- NT_STATUS_HAVE_NO_MEMORY(principal);
+ if (!principal) {
+ talloc_free(mem_ctx);
+ return NT_STATUS_NO_MEMORY;
+ }
p = strchr(principal, '@');
if (p) {
@@ -757,24 +767,56 @@ static NTSTATUS gensec_gssapi_session_info(struct gensec_security *gensec_securi
realm = lp_realm();
}
account_name = principal;
+
+ maj_stat = gsskrb5_extract_authz_data_from_sec_context(&min_stat,
+ gensec_gssapi_state->gssapi_context,
+ 1,
+ &pac);
+
+ if (maj_stat == 0) {
+ DATA_BLOB pac_blob = data_blob_talloc(mem_ctx, pac.value, pac.length);
+ pac_blob = unwrap_pac(mem_ctx, &pac_blob);
+ gss_release_buffer(&min_stat, &pac);
+
+ /* decode and verify the pac */
+ nt_status = kerberos_decode_pac(mem_ctx, &logon_info, pac_blob,
+ gensec_gssapi_state->smb_krb5_context);
+
+ if (NT_STATUS_IS_OK(nt_status)) {
+ union netr_Validation validation;
+ validation.sam3 = &logon_info->info3;
+ nt_status = make_server_info_netlogon_validation(gensec_gssapi_state,
+ account_name,
+ 3, &validation,
+ &server_info);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
+ } else {
+ maj_stat = 1;
+ }
+ }
+
+ if (maj_stat) {
+ /* IF we have the PAC - otherwise we need to get this
+ * data from elsewere - local ldb, or (TODO) lookup of some
+ * kind...
+ *
+ * when heimdal can generate the PAC, we should fail if there's
+ * no PAC present
+ */
- /* IF we have the PAC - otherwise we need to get this
- * data from elsewere - local ldb, or (TODO) lookup of some
- * kind...
- *
- * when heimdal can generate the PAC, we should fail if there's
- * no PAC present
- */
-
- {
DATA_BLOB user_sess_key = data_blob(NULL, 0);
DATA_BLOB lm_sess_key = data_blob(NULL, 0);
/* TODO: should we pass the krb5 session key in here? */
- nt_status = sam_get_server_info(gensec_gssapi_state, account_name, realm,
+ nt_status = sam_get_server_info(mem_ctx, account_name, realm,
user_sess_key, lm_sess_key,
&server_info);
- talloc_free(principal);
- NT_STATUS_NOT_OK_RETURN(nt_status);
+ if (!NT_STATUS_IS_OK(nt_status)) {
+ talloc_free(mem_ctx);
+ return nt_status;
+ }
}
/* references the server_info into the session_info */
diff --git a/source4/auth/gensec/gensec_krb5.c b/source4/auth/gensec/gensec_krb5.c
index 348a75b535..6d3c105405 100644
--- a/source4/auth/gensec/gensec_krb5.c
+++ b/source4/auth/gensec/gensec_krb5.c
@@ -51,185 +51,6 @@ struct gensec_krb5_state {
char *peer_principal;
};
-#ifdef KRB5_DO_VERIFY_PAC
-static NTSTATUS gensec_krb5_pac_checksum(DATA_BLOB pac_data,
- struct PAC_SIGNATURE_DATA *sig,
- struct gensec_krb5_state *gensec_krb5_state,
- uint32 keyusage)
-{
- krb5_error_code ret;
- krb5_crypto crypto;
- Checksum cksum;
- int i;
-
- cksum.cksumtype = (CKSUMTYPE)sig->type;
- cksum.checksum.length = sizeof(sig->signature);
- cksum.checksum.data = sig->signature;
-
-
- ret = krb5_crypto_init(gensec_krb5_state->smb_krb5_context->krb5_context,
- &gensec_krb5_state->keyblock,
- 0,
- &crypto);
- if (ret) {
- DEBUG(0,("krb5_crypto_init() failed\n"));
- return NT_STATUS_FOOBAR;
- }
- for (i=0; i < 40; i++) {
- keyusage = i;
- ret = krb5_verify_checksum(gensec_krb5_state->smb_krb5_context->krb5_context,
- crypto,
- keyusage,
- pac_data.data,
- pac_data.length,
- &cksum);
- if (!ret) {
- DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage));
- break;
- }
- }
- krb5_crypto_destroy(gensec_krb5_state->smb_krb5_context->krb5_context, crypto);
-
- if (ret) {
- DEBUG(0,("NOT verifying PAC checksums yet!\n"));
- //return NT_STATUS_LOGON_FAILURE;
- } else {
- DEBUG(0,("PAC checksums verified!\n"));
- }
-
- return NT_STATUS_OK;
-}
-#endif
-
-static NTSTATUS gensec_krb5_decode_pac(TALLOC_CTX *mem_ctx,
- struct PAC_LOGON_INFO **logon_info_out,
- DATA_BLOB blob,
- struct gensec_krb5_state *gensec_krb5_state)
-{
- NTSTATUS status;
- struct PAC_SIGNATURE_DATA srv_sig;
- struct PAC_SIGNATURE_DATA *srv_sig_ptr;
- struct PAC_SIGNATURE_DATA kdc_sig;
- struct PAC_SIGNATURE_DATA *kdc_sig_ptr;
- struct PAC_LOGON_INFO *logon_info = NULL;
- struct PAC_DATA pac_data;
-#ifdef KRB5_DO_VERIFY_PAC
- DATA_BLOB tmp_blob = data_blob(NULL, 0);
-#endif
- int i;
-
- status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("can't parse the PAC\n"));
- return status;
- }
- NDR_PRINT_DEBUG(PAC_DATA, &pac_data);
-
- if (pac_data.num_buffers < 3) {
- /* we need logon_ingo, service_key and kdc_key */
- DEBUG(0,("less than 3 PAC buffers\n"));
- return NT_STATUS_FOOBAR;
- }
-
- for (i=0; i < pac_data.num_buffers; i++) {
- switch (pac_data.buffers[i].type) {
- case PAC_TYPE_LOGON_INFO:
- if (!pac_data.buffers[i].info) {
- break;
- }
- logon_info = &pac_data.buffers[i].info->logon_info;
- break;
- case PAC_TYPE_SRV_CHECKSUM:
- if (!pac_data.buffers[i].info) {
- break;
- }
- srv_sig_ptr = &pac_data.buffers[i].info->srv_cksum;
- srv_sig = pac_data.buffers[i].info->srv_cksum;
- break;
- case PAC_TYPE_KDC_CHECKSUM:
- if (!pac_data.buffers[i].info) {
- break;
- }
- kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum;
- kdc_sig = pac_data.buffers[i].info->kdc_cksum;
- break;
- case PAC_TYPE_UNKNOWN_10:
- break;
- default:
- break;
- }
- }
-
- if (!logon_info) {
- DEBUG(0,("PAC no logon_info\n"));
- return NT_STATUS_FOOBAR;
- }
-
- if (!srv_sig_ptr) {
- DEBUG(0,("PAC no srv_key\n"));
- return NT_STATUS_FOOBAR;
- }
-
- if (!kdc_sig_ptr) {
- DEBUG(0,("PAC no kdc_key\n"));
- return NT_STATUS_FOOBAR;
- }
-#ifdef KRB5_DO_VERIFY_PAC
- /* clear the kdc_key */
-/* memset((void *)kdc_sig_ptr , '\0', sizeof(*kdc_sig_ptr));*/
-
- status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data,
- (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("can't parse the PAC\n"));
- return status;
- }
- /*NDR_PRINT_DEBUG(PAC_DATA, &pac_data);*/
-
- /* verify by kdc_key */
- status = gensec_krb5_pac_checksum(tmp_blob, &kdc_sig, gensec_krb5_state, 0);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-
- /* clear the service_key */
-/* memset((void *)srv_sig_ptr , '\0', sizeof(*srv_sig_ptr));*/
-
- status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data,
- (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
- status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
- (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
- if (!NT_STATUS_IS_OK(status)) {
- DEBUG(0,("can't parse the PAC\n"));
- return status;
- }
- NDR_PRINT_DEBUG(PAC_DATA, &pac_data);
-
- /* verify by servie_key */
- status = gensec_krb5_pac_checksum(tmp_blob, &srv_sig, gensec_krb5_state, 0);
-
- if (!NT_STATUS_IS_OK(status)) {
- return status;
- }
-#endif
- DEBUG(0,("account_name: %s [%s]\n",
- logon_info->info3.base.account_name.string,
- logon_info->info3.base.full_name.string));
- *logon_info_out = logon_info;
-
- return status;
-}
-
static int gensec_krb5_destory(void *ptr)
{
struct gensec_krb5_state *gensec_krb5_state = ptr;
@@ -263,7 +84,6 @@ static NTSTATUS gensec_krb5_start(struct gensec_security *gensec_security)
gensec_security->private_data = gensec_krb5_state;
- initialize_krb5_error_table();
gensec_krb5_state->auth_context = NULL;
gensec_krb5_state->ccache = NULL;
ZERO_STRUCT(gensec_krb5_state->ticket);
@@ -623,8 +443,8 @@ static NTSTATUS gensec_krb5_session_info(struct gensec_security *gensec_security
account_name = principal;
/* decode and verify the pac */
- nt_status = gensec_krb5_decode_pac(gensec_krb5_state, &logon_info, gensec_krb5_state->pac,
- gensec_krb5_state);
+ nt_status = kerberos_decode_pac(gensec_krb5_state, &logon_info, gensec_krb5_state->pac,
+ gensec_krb5_state);
/* IF we have the PAC - otherwise we need to get this
* data from elsewere - local ldb, or (TODO) lookup of some
diff --git a/source4/auth/kerberos/kerberos_pac.c b/source4/auth/kerberos/kerberos_pac.c
new file mode 100644
index 0000000000..8f3d2cd72c
--- /dev/null
+++ b/source4/auth/kerberos/kerberos_pac.c
@@ -0,0 +1,213 @@
+/*
+ Unix SMB/CIFS implementation.
+
+ Kerberos backend for GENSEC
+
+ Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004
+ Copyright (C) Andrew Tridgell 2001
+ Copyright (C) Luke Howard 2002-2003
+ Copyright (C) Stefan Metzmacher 2004-2005
+
+ 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
+ (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, write to the Free Software
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include "includes.h"
+#include "system/kerberos.h"
+#include "system/time.h"
+#include "system/network.h"
+#include "auth/kerberos/kerberos.h"
+#include "librpc/gen_ndr/ndr_krb5pac.h"
+#include "auth/auth.h"
+
+#ifdef KRB5_DO_VERIFY_PAC
+static NTSTATUS kerberos_pac_checksum(DATA_BLOB pac_data,
+ struct PAC_SIGNATURE_DATA *sig,
+ struct smb_krb5_context *smb_krb5_context,
+ uint32 keyusage)
+{
+ krb5_error_code ret;
+ krb5_crypto crypto;
+ Checksum cksum;
+ int i;
+
+ cksum.cksumtype = (CKSUMTYPE)sig->type;
+ cksum.checksum.length = sizeof(sig->signature);
+ cksum.checksum.data = sig->signature;
+
+
+ ret = krb5_crypto_init(smb_krb5_context->krb5_context,
+ &gensec_krb5_state->keyblock,
+ 0,
+ &crypto);
+ if (ret) {
+ DEBUG(0,("krb5_crypto_init() failed\n"));
+ return NT_STATUS_FOOBAR;
+ }
+ for (i=0; i < 40; i++) {
+ keyusage = i;
+ ret = krb5_verify_checksum(smb_krb5_context->krb5_context,
+ crypto,
+ keyusage,
+ pac_data.data,
+ pac_data.length,
+ &cksum);
+ if (!ret) {
+ DEBUG(0,("PAC Verified: keyusage: %d\n", keyusage));
+ break;
+ }
+ }
+ krb5_crypto_destroy(smb_krb5_context->krb5_context, crypto);
+
+ if (ret) {
+ DEBUG(0,("NOT verifying PAC checksums yet!\n"));
+ //return NT_STATUS_LOGON_FAILURE;
+ } else {
+ DEBUG(0,("PAC checksums verified!\n"));
+ }
+
+ return NT_STATUS_OK;
+}
+#endif
+
+NTSTATUS kerberos_decode_pac(TALLOC_CTX *mem_ctx,
+ struct PAC_LOGON_INFO **logon_info_out,
+ DATA_BLOB blob,
+ struct smb_krb5_context *smb_krb5_context)
+{
+ NTSTATUS status;
+ struct PAC_SIGNATURE_DATA srv_sig;
+ struct PAC_SIGNATURE_DATA *srv_sig_ptr;
+ struct PAC_SIGNATURE_DATA kdc_sig;
+ struct PAC_SIGNATURE_DATA *kdc_sig_ptr;
+ struct PAC_LOGON_INFO *logon_info = NULL;
+ struct PAC_DATA pac_data;
+#ifdef KRB5_DO_VERIFY_PAC
+ DATA_BLOB tmp_blob = data_blob(NULL, 0);
+#endif
+ int i;
+
+ status = ndr_pull_struct_blob(&blob, mem_ctx, &pac_data,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("can't parse the PAC\n"));
+ return status;
+ }
+ NDR_PRINT_DEBUG(PAC_DATA, &pac_data);
+
+ if (pac_data.num_buffers < 3) {
+ /* we need logon_ingo, service_key and kdc_key */
+ DEBUG(0,("less than 3 PAC buffers\n"));
+ return NT_STATUS_FOOBAR;
+ }
+
+ for (i=0; i < pac_data.num_buffers; i++) {
+ switch (pac_data.buffers[i].type) {
+ case PAC_TYPE_LOGON_INFO:
+ if (!pac_data.buffers[i].info) {
+ break;
+ }
+ logon_info = &pac_data.buffers[i].info->logon_info;
+ break;
+ case PAC_TYPE_SRV_CHECKSUM:
+ if (!pac_data.buffers[i].info) {
+ break;
+ }
+ srv_sig_ptr = &pac_data.buffers[i].info->srv_cksum;
+ srv_sig = pac_data.buffers[i].info->srv_cksum;
+ break;
+ case PAC_TYPE_KDC_CHECKSUM:
+ if (!pac_data.buffers[i].info) {
+ break;
+ }
+ kdc_sig_ptr = &pac_data.buffers[i].info->kdc_cksum;
+ kdc_sig = pac_data.buffers[i].info->kdc_cksum;
+ break;
+ case PAC_TYPE_UNKNOWN_10:
+ break;
+ default:
+ break;
+ }
+ }
+
+ if (!logon_info) {
+ DEBUG(0,("PAC no logon_info\n"));
+ return NT_STATUS_FOOBAR;
+ }
+
+ if (!srv_sig_ptr) {
+ DEBUG(0,("PAC no srv_key\n"));
+ return NT_STATUS_FOOBAR;
+ }
+
+ if (!kdc_sig_ptr) {
+ DEBUG(0,("PAC no kdc_key\n"));
+ return NT_STATUS_FOOBAR;
+ }
+#ifdef KRB5_DO_VERIFY_PAC
+ /* clear the kdc_key */
+/* memset((void *)kdc_sig_ptr , '\0', sizeof(*kdc_sig_ptr));*/
+
+ status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data,
+ (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("can't parse the PAC\n"));
+ return status;
+ }
+ /*NDR_PRINT_DEBUG(PAC_DATA, &pac_data);*/
+
+ /* verify by kdc_key */
+ status = kerberos_pac_checksum(tmp_blob, &kdc_sig, smb_krb5_context, 0);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+
+ /* clear the service_key */
+/* memset((void *)srv_sig_ptr , '\0', sizeof(*srv_sig_ptr));*/
+
+ status = ndr_push_struct_blob(&tmp_blob, mem_ctx, &pac_data,
+ (ndr_push_flags_fn_t)ndr_push_PAC_DATA);
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+ status = ndr_pull_struct_blob(&tmp_blob, mem_ctx, &pac_data,
+ (ndr_pull_flags_fn_t)ndr_pull_PAC_DATA);
+ if (!NT_STATUS_IS_OK(status)) {
+ DEBUG(0,("can't parse the PAC\n"));
+ return status;
+ }
+ NDR_PRINT_DEBUG(PAC_DATA, &pac_data);
+
+ /* verify by servie_key */
+ status = kerberos_pac_checksum(tmp_blob, &srv_sig, smb_krb5_context, 0);
+
+ if (!NT_STATUS_IS_OK(status)) {
+ return status;
+ }
+#endif
+ DEBUG(0,("account_name: %s [%s]\n",
+ logon_info->info3.base.account_name.string,
+ logon_info->info3.base.full_name.string));
+ *logon_info_out = logon_info;
+
+ return status;
+}
+
diff --git a/source4/auth/kerberos/kerberos_verify.c b/source4/auth/kerberos/kerberos_verify.c
index f269012ae3..01b8a75c95 100644
--- a/source4/auth/kerberos/kerberos_verify.c
+++ b/source4/auth/kerberos/kerberos_verify.c
@@ -34,7 +34,7 @@
#ifdef HAVE_KRB5
-static DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
+DATA_BLOB unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data)
{
DATA_BLOB out;
DATA_BLOB pac_contents = data_blob(NULL, 0);