1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-24 10:50:22 +03:00

s3-krb5 Only build ADS support if arcfour-hmac-md5 is available

Modern Kerberos implementations have either defines or enums for these
key types, which makes doing #ifdef difficult.  This shows up in files
such as libnet_samsync_keytab.c, the bulk of which is not compiled on
current Fedora 12, for example.

The downside is that this makes Samba unconditionally depend on the
arcfour-hmac-md5 encryption type at build time.  We will no longer
support libraries that only support the DES based encryption types.
However, the single-DES types that are supported in common with AD are
already painfully weak - so much so that they are disabled by default
in modern Kerberos libraries.

If not found, ADS support will not be compiled in.

This means that our 'net ads join' will no longer set the
ACB_USE_DES_KEY_ONLY flag, and we will always try to use
arcfour-hmac-md5.

A future improvement would be to remove the use of the DES encryption
types totally, but this would require that any ACB_USE_DES_KEY_ONLY
flag be removed from existing joins.

Andrew Bartlett

Signed-off-by: Simo Sorce <idra@samba.org>
This commit is contained in:
Andrew Bartlett 2010-08-10 08:25:02 +10:00 committed by Simo Sorce
parent fff6fa72ff
commit 71d80e6be0
10 changed files with 2520 additions and 21 deletions

View File

@ -4040,6 +4040,7 @@ if test x"$with_ads_support" != x"no"; then
[Whether the krb5_keyblock struct has a keyvalue property])
fi
found_arcfour_hmac=no
AC_CACHE_CHECK([for ENCTYPE_ARCFOUR_HMAC_MD5],
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,[
AC_TRY_COMPILE([#include <krb5.h>],
@ -4057,7 +4058,19 @@ if test x"$with_ads_support" != x"no"; then
if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC_MD5" = x"yes" -a\
x"$samba_cv_HAVE_KEYTYPE_ARCFOUR_56" = x"yes"; then
AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5,1,
[Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type is available])
[Whether the ENCTYPE_ARCFOUR_HMAC_MD5 key type definition is available])
found_arcfour_hmac=yes
fi
AC_CACHE_CHECK([for ENCTYPE_ARCFOUR_HMAC],
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC,[
AC_TRY_COMPILE([#include <krb5.h>],
[krb5_enctype enctype; enctype = ENCTYPE_ARCFOUR_HMAC;],
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC=yes,
samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC=no)])
if test x"$samba_cv_HAVE_ENCTYPE_ARCFOUR_HMAC" = x"yes"; then
AC_DEFINE(HAVE_ENCTYPE_ARCFOUR_HMAC,1,
[Whether the ENCTYPE_ARCFOUR_HMAC key type definition is available])
found_arcfour_hmac=yes
fi
AC_CACHE_CHECK([for AP_OPTS_USE_SUBKEY],
@ -4300,6 +4313,11 @@ if test x"$with_ads_support" != x"no"; then
# NOTE: all tests should be done before this block!
#
#
if test x"$found_arcfour_hmac" != x"yes"; then
AC_MSG_WARN(arcfour-hmac-md5 encryption type not found in -lkrb5)
use_ads=no
fi
if test x"$ac_cv_lib_ext_krb5_krb5_mk_req_extended" != x"yes"; then
AC_MSG_WARN(krb5_mk_req_extended not found in -lkrb5)
use_ads=no

View File

@ -25,7 +25,7 @@
#endif
/* Heimdal uses a slightly different name */
#if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5)
#if defined(HAVE_ENCTYPE_ARCFOUR_HMAC_MD5) && !defined(HAVE_ENCTYPE_ARCFOUR_HMAC)
#define ENCTYPE_ARCFOUR_HMAC ENCTYPE_ARCFOUR_HMAC_MD5
#endif

View File

@ -236,17 +236,16 @@ int ads_keytab_add_entry(ADS_STRUCT *ads, const char *srvPrinc)
krb5_keytab keytab = NULL;
krb5_data password;
krb5_kvno kvno;
krb5_enctype enctypes[4] = { ENCTYPE_DES_CBC_CRC, ENCTYPE_DES_CBC_MD5, 0, 0 };
krb5_enctype enctypes[4] = { ENCTYPE_DES_CBC_CRC,
ENCTYPE_DES_CBC_MD5,
ENCTYPE_ARCFOUR_HMAC,
0 };
char *princ_s = NULL, *short_princ_s = NULL;
char *password_s = NULL;
char *my_fqdn;
TALLOC_CTX *ctx = NULL;
char *machine_name;
#if defined(ENCTYPE_ARCFOUR_HMAC)
enctypes[2] = ENCTYPE_ARCFOUR_HMAC;
#endif
initialize_krb5_error_table();
ret = krb5_init_context(&context);
if (ret) {

View File

@ -344,9 +344,7 @@ static krb5_error_code ads_secrets_verify_ticket(krb5_context context,
/* Let's make some room for 2 password (old and new)*/
krb5_data passwords[2];
krb5_enctype enctypes[] = {
#if defined(ENCTYPE_ARCFOUR_HMAC)
ENCTYPE_ARCFOUR_HMAC,
#endif
ENCTYPE_DES_CBC_CRC,
ENCTYPE_DES_CBC_MD5,
ENCTYPE_NULL

View File

@ -25,7 +25,7 @@
#include "libnet/libnet_keytab.h"
#include "librpc/gen_ndr/ndr_drsblobs.h"
#if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC)
#if defined(HAVE_ADS)
static NTSTATUS keytab_startup(struct dssync_context *ctx, TALLOC_CTX *mem_ctx,
struct replUpToDateVectorBlob **pold_utdv)
@ -601,7 +601,7 @@ static NTSTATUS keytab_process_objects(struct dssync_context *ctx,
{
return NT_STATUS_NOT_SUPPORTED;
}
#endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */
#endif /* defined(HAVE_ADS) */
const struct dssync_ops libnet_dssync_keytab_ops = {
.startup = keytab_startup,

View File

@ -982,12 +982,6 @@ static NTSTATUS libnet_join_joindomain_rpc(TALLOC_CTX *mem_ctx,
/* Fill in the additional account flags now */
acct_flags |= ACB_PWNOEXP;
if (r->out.domain_is_ad) {
#if !defined(ENCTYPE_ARCFOUR_HMAC)
acct_flags |= ACB_USE_DES_KEY_ONLY;
#endif
;;
}
/* Set account flags on machine account */
ZERO_STRUCT(user_info.info16);

File diff suppressed because it is too large Load Diff

View File

@ -24,7 +24,7 @@
#include "libnet/libnet_keytab.h"
#include "libnet/libnet_samsync.h"
#if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC)
#if defined(HAVE_ADS)
/****************************************************************
****************************************************************/
@ -296,7 +296,7 @@ static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx,
return NT_STATUS_NOT_SUPPORTED;
}
#endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */
#endif /* defined(HAVE_ADS) */
const struct samsync_ops libnet_samsync_keytab_ops = {
.startup = init_keytab,

View File

@ -0,0 +1,305 @@
/*
Unix SMB/CIFS implementation.
dump the remote SAM using rpc samsync operations
Copyright (C) Guenther Deschner 2008.
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 "smb_krb5.h"
#include "ads.h"
#include "libnet/libnet_keytab.h"
#include "libnet/libnet_samsync.h"
#if defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC)
/****************************************************************
****************************************************************/
static NTSTATUS keytab_ad_connect(TALLOC_CTX *mem_ctx,
const char *domain_name,
const char *username,
const char *password,
struct libnet_keytab_context *ctx)
{
NTSTATUS status;
ADS_STATUS ad_status;
ADS_STRUCT *ads;
struct netr_DsRGetDCNameInfo *info = NULL;
const char *dc;
status = dsgetdcname(mem_ctx, NULL, domain_name, NULL, NULL, 0, &info);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
dc = strip_hostname(info->dc_unc);
ads = ads_init(NULL, domain_name, dc);
NT_STATUS_HAVE_NO_MEMORY(ads);
if (getenv(KRB5_ENV_CCNAME) == NULL) {
setenv(KRB5_ENV_CCNAME, "MEMORY:libnet_samsync_keytab", 1);
}
ads->auth.user_name = SMB_STRDUP(username);
ads->auth.password = SMB_STRDUP(password);
ad_status = ads_connect_user_creds(ads);
if (!ADS_ERR_OK(ad_status)) {
return NT_STATUS_UNSUCCESSFUL;
}
ctx->ads = ads;
ctx->dns_domain_name = talloc_strdup_upper(mem_ctx, ads->config.realm);
NT_STATUS_HAVE_NO_MEMORY(ctx->dns_domain_name);
return NT_STATUS_OK;
}
/****************************************************************
****************************************************************/
static NTSTATUS fetch_sam_entry_keytab(TALLOC_CTX *mem_ctx,
enum netr_SamDatabaseID database_id,
uint32_t rid,
struct netr_DELTA_USER *r,
struct libnet_keytab_context *ctx)
{
NTSTATUS status;
uint32_t kvno = 0;
DATA_BLOB blob;
if (memcmp(r->ntpassword.hash, ctx->zero_buf, 16) == 0) {
return NT_STATUS_OK;
}
kvno = ads_get_kvno(ctx->ads, r->account_name.string);
blob = data_blob_const(r->ntpassword.hash, 16);
status = libnet_keytab_add_to_keytab_entries(mem_ctx, ctx,
kvno,
r->account_name.string,
NULL,
ENCTYPE_ARCFOUR_HMAC,
blob);
if (!NT_STATUS_IS_OK(status)) {
return status;
}
return NT_STATUS_OK;
}
/****************************************************************
****************************************************************/
static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx,
struct samsync_context *ctx,
enum netr_SamDatabaseID database_id,
uint64_t *sequence_num)
{
krb5_error_code ret = 0;
NTSTATUS status;
struct libnet_keytab_context *keytab_ctx = NULL;
struct libnet_keytab_entry *entry;
uint64_t old_sequence_num = 0;
const char *principal = NULL;
ret = libnet_keytab_init(mem_ctx, ctx->output_filename, &keytab_ctx);
if (ret) {
return krb5_to_nt_status(ret);
}
keytab_ctx->clean_old_entries = ctx->clean_old_entries;
ctx->private_data = keytab_ctx;
status = keytab_ad_connect(mem_ctx,
ctx->domain_name,
ctx->username,
ctx->password,
keytab_ctx);
if (!NT_STATUS_IS_OK(status)) {
TALLOC_FREE(keytab_ctx);
return status;
}
principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s",
keytab_ctx->dns_domain_name);
NT_STATUS_HAVE_NO_MEMORY(principal);
entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL,
mem_ctx);
if (entry && (entry->password.length == 8)) {
old_sequence_num = BVAL(entry->password.data, 0);
}
if (sequence_num) {
*sequence_num = old_sequence_num;
}
return status;
}
/****************************************************************
****************************************************************/
static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
enum netr_SamDatabaseID database_id,
struct netr_DELTA_ENUM_ARRAY *r,
uint64_t *sequence_num,
struct samsync_context *ctx)
{
struct libnet_keytab_context *keytab_ctx =
(struct libnet_keytab_context *)ctx->private_data;
NTSTATUS status = NT_STATUS_OK;
int i;
for (i = 0; i < r->num_deltas; i++) {
switch (r->delta_enum[i].delta_type) {
case NETR_DELTA_USER:
break;
case NETR_DELTA_DOMAIN:
if (sequence_num) {
*sequence_num =
r->delta_enum[i].delta_union.domain->sequence_num;
}
continue;
case NETR_DELTA_MODIFY_COUNT:
if (sequence_num) {
*sequence_num =
*r->delta_enum[i].delta_union.modified_count;
}
continue;
default:
continue;
}
status = fetch_sam_entry_keytab(mem_ctx, database_id,
r->delta_enum[i].delta_id_union.rid,
r->delta_enum[i].delta_union.user,
keytab_ctx);
if (!NT_STATUS_IS_OK(status)) {
goto out;
}
}
out:
return status;
}
/****************************************************************
****************************************************************/
static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx,
struct samsync_context *ctx,
enum netr_SamDatabaseID database_id,
uint64_t sequence_num)
{
struct libnet_keytab_context *keytab_ctx =
(struct libnet_keytab_context *)ctx->private_data;
krb5_error_code ret;
NTSTATUS status;
struct libnet_keytab_entry *entry;
uint64_t old_sequence_num = 0;
const char *principal = NULL;
principal = talloc_asprintf(mem_ctx, "SEQUENCE_NUM@%s",
keytab_ctx->dns_domain_name);
NT_STATUS_HAVE_NO_MEMORY(principal);
entry = libnet_keytab_search(keytab_ctx, principal, 0, ENCTYPE_NULL,
mem_ctx);
if (entry && (entry->password.length == 8)) {
old_sequence_num = BVAL(entry->password.data, 0);
}
if (sequence_num > old_sequence_num) {
DATA_BLOB blob;
blob = data_blob_talloc_zero(mem_ctx, 8);
SBVAL(blob.data, 0, sequence_num);
status = libnet_keytab_add_to_keytab_entries(mem_ctx, keytab_ctx,
0,
"SEQUENCE_NUM",
NULL,
ENCTYPE_NULL,
blob);
if (!NT_STATUS_IS_OK(status)) {
goto done;
}
}
ret = libnet_keytab_add(keytab_ctx);
if (ret) {
status = krb5_to_nt_status(ret);
ctx->error_message = talloc_asprintf(ctx,
"Failed to add entries to keytab %s: %s",
keytab_ctx->keytab_name, error_message(ret));
TALLOC_FREE(keytab_ctx);
return status;
}
ctx->result_message = talloc_asprintf(ctx,
"Vampired %d accounts to keytab %s",
keytab_ctx->count,
keytab_ctx->keytab_name);
status = NT_STATUS_OK;
done:
TALLOC_FREE(keytab_ctx);
return status;
}
#else
static NTSTATUS init_keytab(TALLOC_CTX *mem_ctx,
struct samsync_context *ctx,
enum netr_SamDatabaseID database_id,
uint64_t *sequence_num)
{
return NT_STATUS_NOT_SUPPORTED;
}
static NTSTATUS fetch_sam_entries_keytab(TALLOC_CTX *mem_ctx,
enum netr_SamDatabaseID database_id,
struct netr_DELTA_ENUM_ARRAY *r,
uint64_t *sequence_num,
struct samsync_context *ctx)
{
return NT_STATUS_NOT_SUPPORTED;
}
static NTSTATUS close_keytab(TALLOC_CTX *mem_ctx,
struct samsync_context *ctx,
enum netr_SamDatabaseID database_id,
uint64_t sequence_num)
{
return NT_STATUS_NOT_SUPPORTED;
}
#endif /* defined(HAVE_ADS) && defined(ENCTYPE_ARCFOUR_HMAC) */
const struct samsync_ops libnet_samsync_keytab_ops = {
.startup = init_keytab,
.process_objects = fetch_sam_entries_keytab,
.finish = close_keytab
};

View File

@ -964,9 +964,7 @@ int cli_krb5_get_ticket(TALLOC_CTX *mem_ctx,
krb5_ccache ccdef = NULL;
krb5_auth_context auth_context = NULL;
krb5_enctype enc_types[] = {
#ifdef ENCTYPE_ARCFOUR_HMAC
ENCTYPE_ARCFOUR_HMAC,
#endif
ENCTYPE_DES_CBC_MD5,
ENCTYPE_DES_CBC_CRC,
ENCTYPE_NULL};