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:
parent
7cbe1c844e
commit
f498ba77df
@ -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)) {
|
||||||
|
@ -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;
|
||||||
|
@ -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
|
|
||||||
|
@ -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
|
||||||
|
@ -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.
|
||||||
*/
|
*/
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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,
|
||||||
|
@ -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;
|
||||||
|
Loading…
Reference in New Issue
Block a user