1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-22 13:34:15 +03:00

heimdal: Pass extra information to hdb_auth_status() to log success and failures

We now pass on the original client name and the client address to allow
consistent audit logging in Samba across multiple protocols.

We use config->db[0] to find the first database to record incorrect
users.

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
This commit is contained in:
Andrew Bartlett 2017-02-21 14:07:54 +13:00
parent 7cbe1c844e
commit f498ba77df
9 changed files with 180 additions and 28 deletions

View File

@ -637,9 +637,11 @@ static const char* get_password_type(const struct auth_usersupplied_info *ui)
const char *password_type = NULL; const char *password_type = NULL;
if (ui->password_state == AUTH_PASSWORD_RESPONSE && if (ui->password_type != NULL) {
(ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) && password_type = ui->password_type;
ui->password.response.nt.length == 24) { } else if (ui->password_state == AUTH_PASSWORD_RESPONSE &&
(ui->logon_parameters & MSV1_0_ALLOW_MSVCHAPV2) &&
ui->password.response.nt.length == 24) {
password_type = "MSCHAPv2"; password_type = "MSCHAPv2";
} else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED) } else if ((ui->logon_parameters & MSV1_0_CLEARTEXT_PASSWORD_SUPPLIED)
|| (ui->password_state == AUTH_PASSWORD_PLAIN)) { || (ui->password_state == AUTH_PASSWORD_PLAIN)) {

View File

@ -83,6 +83,13 @@ struct auth_usersupplied_info
const char *service_description; const char *service_description;
const char *auth_description; const char *auth_description;
/*
* for logging only, normally worked out from the password but
* for krb5 logging only (krb5 normally doesn't use this) we
* record the enc type here
*/
const char *password_type;
}; };
struct auth_method_context; struct auth_method_context;

View File

@ -319,18 +319,3 @@
^samba3.smb2.credits.skipped_mid.* ^samba3.smb2.credits.skipped_mid.*
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_dbcheck ^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_dbcheck
^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_missing ^samba4.blackbox.dbcheck-links.release-4-5-0-pre1.dangling_multi_valued_check_missing
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_ldap\(
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_ip_tcp_krb5_dns
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_ip_tcp_krb5_dns_connect
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_ip_tcp_krb5_dns_seal
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_ip_tcp_krb5_dns_sign
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_np_krb_dns
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_np_krb_dns_sign
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_np_krb_dns_smb2
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_np_krb_srv
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_rpc_ncacn_np_krb_srv_sign
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_smb\(
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_smb_bad_password
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_smb_bad_user
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_smb_bad_user_and_password
^samba.tests.auth_log.samba.tests.auth_log.AuthLogTests.test_smb_default_connect

View File

@ -1090,6 +1090,13 @@ _kdc_as_rep(krb5_context context,
kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg); kdc_log(context, config, 0, "UNKNOWN -- %s: %s", client_name, msg);
krb5_free_error_message(context, msg); krb5_free_error_message(context, msg);
ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN; ret = KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
if (config->db[0] && config->db[0]->hdb_auth_status)
(config->db[0]->hdb_auth_status)(context, config->db[0], NULL,
from_addr,
client_name,
NULL,
HDB_AUTH_CLIENT_UNKNOWN);
goto out; goto out;
} }
ret = _kdc_db_fetch(context, config, server_princ, ret = _kdc_db_fetch(context, config, server_princ,
@ -1194,6 +1201,12 @@ _kdc_as_rep(krb5_context context,
kdc_log(context, config, 0, kdc_log(context, config, 0,
"PKINIT pre-authentication succeeded -- %s using %s", "PKINIT pre-authentication succeeded -- %s using %s",
client_name, client_cert); client_name, client_cert);
if (clientdb->hdb_auth_status)
(clientdb->hdb_auth_status)(context, clientdb, client,
from_addr,
client_name,
"PKINIT",
HDB_AUTH_PKINIT_SUCCESS);
free(client_cert); free(client_cert);
if (pkp) if (pkp)
goto preauth_done; goto preauth_done;
@ -1291,22 +1304,30 @@ _kdc_as_rep(krb5_context context,
pa_key->key.keytype, &str); pa_key->key.keytype, &str);
if (ret2) if (ret2)
str = NULL; str = NULL;
kdc_log(context, config, 5, kdc_log(context, config, 5,
"Failed to decrypt PA-DATA -- %s " "Failed to decrypt PA-DATA -- %s "
"(enctype %s) error %s", "(enctype %s) error %s",
client_name, str ? str : "unknown enctype", msg); client_name, str ? str : "unknown enctype", msg);
krb5_free_error_message(context, msg); krb5_free_error_message(context, msg);
free(str);
if(hdb_next_enctype2key(context, &client->entry, if(hdb_next_enctype2key(context, &client->entry,
enc_data.etype, &pa_key) == 0) enc_data.etype, &pa_key) == 0) {
free(str);
goto try_next_key; goto try_next_key;
}
e_text = "Failed to decrypt PA-DATA"; e_text = "Failed to decrypt PA-DATA";
free_EncryptedData(&enc_data); free_EncryptedData(&enc_data);
if (clientdb->hdb_auth_status) if (clientdb->hdb_auth_status)
(clientdb->hdb_auth_status)(context, clientdb, client, HDB_AUTH_WRONG_PASSWORD); (clientdb->hdb_auth_status)(context, clientdb, client,
from_addr,
client_name,
str ? str : "unknown enctype",
HDB_AUTH_WRONG_PASSWORD);
free(str);
ret = KRB5KDC_ERR_PREAUTH_FAILED; ret = KRB5KDC_ERR_PREAUTH_FAILED;
continue; continue;
@ -1362,6 +1383,13 @@ _kdc_as_rep(krb5_context context,
kdc_log(context, config, 2, kdc_log(context, config, 2,
"ENC-TS Pre-authentication succeeded -- %s using %s", "ENC-TS Pre-authentication succeeded -- %s using %s",
client_name, str ? str : "unknown enctype"); client_name, str ? str : "unknown enctype");
if (clientdb->hdb_auth_status)
(clientdb->hdb_auth_status)(context, clientdb, client,
from_addr,
client_name,
str ? str : "unknown enctype",
HDB_AUTH_CORRECT_PASSWORD);
free(str); free(str);
break; break;
} }
@ -1414,7 +1442,10 @@ _kdc_as_rep(krb5_context context,
if (clientdb->hdb_auth_status) if (clientdb->hdb_auth_status)
(clientdb->hdb_auth_status)(context, clientdb, client, (clientdb->hdb_auth_status)(context, clientdb, client,
HDB_AUTH_SUCCESS); from_addr,
client_name,
NULL,
HDB_AUTHZ_SUCCESS);
/* /*
* Selelct the best encryption type for the KDC with out regard to * Selelct the best encryption type for the KDC with out regard to

View File

@ -70,9 +70,12 @@ enum hdb_lockop{ HDB_RLOCK, HDB_WLOCK };
#define HDB_CAP_F_PASSWORD_UPDATE_KEYS 4 #define HDB_CAP_F_PASSWORD_UPDATE_KEYS 4
/* auth status values */ /* auth status values */
#define HDB_AUTH_SUCCESS 0 #define HDB_AUTHZ_SUCCESS 0
#define HDB_AUTH_WRONG_PASSWORD 1 #define HDB_AUTH_WRONG_PASSWORD 1
#define HDB_AUTH_INVALID_SIGNATURE 2 #define HDB_AUTH_INVALID_SIGNATURE 2
#define HDB_AUTH_CORRECT_PASSWORD 3
#define HDB_AUTH_PKINIT_SUCCESS 4
#define HDB_AUTH_CLIENT_UNKNOWN 5
/* key usage for master key */ /* key usage for master key */
#define HDB_KU_MKEY 0x484442 #define HDB_KU_MKEY 0x484442
@ -244,7 +247,11 @@ typedef struct HDB{
* In case the entry is locked out, the backend should set the * In case the entry is locked out, the backend should set the
* hdb_entry.flags.locked-out flag. * hdb_entry.flags.locked-out flag.
*/ */
krb5_error_code (*hdb_auth_status)(krb5_context, struct HDB *, hdb_entry_ex *, int); krb5_error_code (*hdb_auth_status)(krb5_context, struct HDB *,
hdb_entry_ex *, struct sockaddr *from_addr,
const char *original_client_name,
const char *auth_type,
int);
/** /**
* Check if delegation is allowed. * Check if delegation is allowed.
*/ */

View File

@ -2677,6 +2677,7 @@ NTSTATUS samba_kdc_setup_db_ctx(TALLOC_CTX *mem_ctx, struct samba_kdc_base_conte
} }
kdc_db_ctx->ev_ctx = base_ctx->ev_ctx; kdc_db_ctx->ev_ctx = base_ctx->ev_ctx;
kdc_db_ctx->lp_ctx = base_ctx->lp_ctx; kdc_db_ctx->lp_ctx = base_ctx->lp_ctx;
kdc_db_ctx->msg_ctx = base_ctx->msg_ctx;
/* get default kdc policy */ /* get default kdc policy */
lpcfg_default_kdc_policy(base_ctx->lp_ctx, lpcfg_default_kdc_policy(base_ctx->lp_ctx,

View File

@ -36,9 +36,13 @@
#include "kdc/kdc-glue.h" #include "kdc/kdc-glue.h"
#include "kdc/db-glue.h" #include "kdc/db-glue.h"
#include "auth/auth_sam.h" #include "auth/auth_sam.h"
#include "auth/common_auth.h"
#include <ldb.h> #include <ldb.h>
#include "sdb.h" #include "sdb.h"
#include "sdb_hdb.h" #include "sdb_hdb.h"
#include "dsdb/samdb/samdb.h"
#include "param/param.h"
#include "../lib/tsocket/tsocket.h"
static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode) static krb5_error_code hdb_samba4_open(krb5_context context, HDB *db, int flags, mode_t mode)
{ {
@ -292,19 +296,131 @@ hdb_samba4_check_s4u2self(krb5_context context, HDB *db,
static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db, static krb5_error_code hdb_samba4_auth_status(krb5_context context, HDB *db,
hdb_entry_ex *entry, hdb_entry_ex *entry,
struct sockaddr *from_addr,
const char *original_client_name,
const char *auth_type,
int hdb_auth_status) int hdb_auth_status)
{ {
struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db, struct samba_kdc_db_context *kdc_db_ctx = talloc_get_type_abort(db->hdb_db,
struct samba_kdc_db_context); struct samba_kdc_db_context);
struct samba_kdc_entry *p = talloc_get_type(entry->ctx, struct samba_kdc_entry);
struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb); struct ldb_dn *domain_dn = ldb_get_default_basedn(kdc_db_ctx->samdb);
if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) { /*
authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn); * Forcing this via the NTLM auth structure is not ideal, but
} else if (hdb_auth_status == HDB_AUTH_SUCCESS) { * it is the most practical option right now, and ensures the
* logs are consistent, even if some elements are always NULL.
*/
struct auth_usersupplied_info ui = {
.mapped_state = true,
.was_mapped = true,
.client = {
.account_name = original_client_name,
.domain_name = NULL,
},
.service_description = "Kerberos KDC",
.auth_description = "ENC-TS Pre-authentication",
.password_type = auth_type
};
size_t sa_socklen = 0;
switch (from_addr->sa_family) {
case AF_INET:
sa_socklen = sizeof(struct sockaddr_in);
break;
#ifdef HAVE_IPV6
case AF_INET6:
sa_socklen = sizeof(struct sockaddr_in6);
break;
#endif
}
switch (hdb_auth_status) {
case HDB_AUTHZ_SUCCESS:
{
struct samba_kdc_entry *p = talloc_get_type(entry->ctx,
struct samba_kdc_entry);
/*
* TODO: We could log the AS-REQ authorization success here as
* well. However before we do that, we need to pass
* in the PAC here or re-calculate it.
*/
authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg, authsam_logon_success_accounting(kdc_db_ctx->samdb, p->msg,
domain_dn, true); domain_dn, true);
break;
}
case HDB_AUTH_INVALID_SIGNATURE:
break;
case HDB_AUTH_CORRECT_PASSWORD:
case HDB_AUTH_WRONG_PASSWORD:
{
TALLOC_CTX *frame = talloc_stackframe();
struct samba_kdc_entry *p = talloc_get_type(entry->ctx,
struct samba_kdc_entry);
struct dom_sid *sid
= samdb_result_dom_sid(frame, p->msg, "objectSid");
const char *account_name
= ldb_msg_find_attr_as_string(p->msg, "sAMAccountName", NULL);
const char *domain_name = lpcfg_sam_name(p->kdc_db_ctx->lp_ctx);
struct tsocket_address *remote_host;
NTSTATUS status;
int ret;
if (hdb_auth_status == HDB_AUTH_WRONG_PASSWORD) {
authsam_update_bad_pwd_count(kdc_db_ctx->samdb, p->msg, domain_dn);
status = NT_STATUS_WRONG_PASSWORD;
} else {
status = NT_STATUS_OK;
}
ret = tsocket_address_bsd_from_sockaddr(frame, from_addr,
sa_socklen,
&remote_host);
if (ret != 0) {
ui.remote_host = NULL;
} else {
ui.remote_host = remote_host;
}
ui.mapped.account_name = account_name;
ui.mapped.domain_name = domain_name;
log_authentication_event(kdc_db_ctx->msg_ctx,
kdc_db_ctx->lp_ctx,
&ui,
status,
domain_name,
account_name,
NULL,
sid);
TALLOC_FREE(frame);
break;
}
case HDB_AUTH_CLIENT_UNKNOWN:
{
struct tsocket_address *remote_host;
int ret;
TALLOC_CTX *frame = talloc_stackframe();
ret = tsocket_address_bsd_from_sockaddr(frame, from_addr,
sa_socklen,
&remote_host);
if (ret != 0) {
ui.remote_host = NULL;
} else {
ui.remote_host = remote_host;
}
log_authentication_event(kdc_db_ctx->msg_ctx,
kdc_db_ctx->lp_ctx,
&ui,
NT_STATUS_NO_SUCH_USER,
NULL, NULL,
NULL, NULL);
TALLOC_FREE(frame);
break;
}
} }
return 0; return 0;
} }

View File

@ -391,6 +391,7 @@ static void kdc_task_init(struct task_server *task)
kdc->base_ctx->ev_ctx = task->event_ctx; kdc->base_ctx->ev_ctx = task->event_ctx;
kdc->base_ctx->lp_ctx = task->lp_ctx; kdc->base_ctx->lp_ctx = task->lp_ctx;
kdc->base_ctx->msg_ctx = task->msg_ctx;
status = hdb_samba4_create_kdc(kdc->base_ctx, status = hdb_samba4_create_kdc(kdc->base_ctx,
kdc->smb_krb5_context->krb5_context, kdc->smb_krb5_context->krb5_context,

View File

@ -33,6 +33,7 @@ struct samba_kdc_policy {
struct samba_kdc_base_context { struct samba_kdc_base_context {
struct tevent_context *ev_ctx; struct tevent_context *ev_ctx;
struct loadparm_context *lp_ctx; struct loadparm_context *lp_ctx;
struct imessaging_context *msg_ctx;
}; };
struct samba_kdc_seq; struct samba_kdc_seq;
@ -40,6 +41,7 @@ struct samba_kdc_seq;
struct samba_kdc_db_context { struct samba_kdc_db_context {
struct tevent_context *ev_ctx; struct tevent_context *ev_ctx;
struct loadparm_context *lp_ctx; struct loadparm_context *lp_ctx;
struct imessaging_context *msg_ctx;
struct ldb_context *samdb; struct ldb_context *samdb;
struct samba_kdc_seq *seq_ctx; struct samba_kdc_seq *seq_ctx;
bool rodc; bool rodc;