#include "kdc/db-glue.h"
#include "auth/auth.h"
#include "kdc/kpasswd_glue.h"
+#include "lib/tsocket/tsocket.h"
#include "auth/auth_sam.h"
#include "messaging/messaging.h"
return samba_princ_needs_pac(skdc_entry);
}
+
+void mit_samba_log_auth_event(struct mit_samba_context *mit_ctx,
+ krb5_timestamp authtime,
+ krb5_kdc_req *request,
+ krb5_db_entry *client,
+ const krb5_address *local_addr,
+ const krb5_address *remote_addr,
+ krb5_error_code error_code)
+{
+ TALLOC_CTX *frame = talloc_stackframe();
+ char *client_name = NULL;
+ char enctype[64] = "unknown enctype";
+ NTSTATUS status = NT_STATUS_OK;
+ krb5_error_code code;
+ /*
+ * Forcing this via the NTLM auth structure is not ideal, but
+ * 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 = {
+ .was_mapped = true,
+ .client = {
+ .domain_name = NULL,
+ },
+ .service_description = "Kerberos KDC",
+ .auth_description = "ENC-TS Pre-authentication",
+ .password_type = "unknown enctype",
+ };
+ struct timeval auth_time;
+ struct samba_kdc_entry *p;
+ struct tsocket_address *remote_host;
+ struct tsocket_address *local_host;
+ struct sockaddr_storage ss;
+ size_t sa_socklen = 0;
+ bool ok;
+ int rc;
+
+ p = (struct samba_kdc_entry *)client->e_data;
+
+ code = krb5_unparse_name(mit_ctx->context, client->princ, &client_name);
+ if (code != 0) {
+ return;
+ }
+ ui.client.account_name = client_name;
+
+ /* TODO: if PKINIT set it to "PKINIT" */
+ code = krb5_enctype_to_string(request->authorization_data.enctype,
+ enctype,
+ sizeof(enctype));
+ if (code == 0) {
+ ui.password_type = enctype;
+ }
+
+ switch (error_code) {
+ case 0: /* CORRECT PASSWORD */
+ status = NT_STATUS_OK;
+ break;
+ case KRB5KRB_AP_ERR_BAD_INTEGRITY:
+ status = NT_STATUS_WRONG_PASSWORD;
+ break;
+ case KRB5KDC_ERR_PREAUTH_FAILED:
+ status = NT_STATUS_NO_SUCH_USER;
+ break;
+ case KRB5KDC_ERR_PREAUTH_REQUIRED:
+ /* Do not log PREAUTH */
+ SAFE_FREE(client_name);
+ TALLOC_FREE(frame);
+ return;
+ default:
+ DBG_ERR("Unhandled error code: %d\n", error_code);
+ SAFE_FREE(client_name);
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ /* Set the local address */
+ ok = smb_krb5_kaddr_to_sockaddr(local_addr,
+ 0,
+ &ss,
+ &sa_socklen);
+ if (!ok) {
+ SAFE_FREE(client_name);
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ rc = tsocket_address_bsd_from_sockaddr(frame,
+ (const struct sockaddr *)&ss,
+ sa_socklen,
+ &local_host);
+ if (rc != 0) {
+ ui.local_host = NULL;
+ } else {
+ ui.local_host = local_host;
+ }
+
+ /* Set the remote address */
+ ok = smb_krb5_kaddr_to_sockaddr(remote_addr,
+ 0,
+ &ss,
+ &sa_socklen);
+ if (!ok) {
+ SAFE_FREE(client_name);
+ TALLOC_FREE(frame);
+ return;
+ }
+
+ rc = tsocket_address_bsd_from_sockaddr(frame,
+ (const struct sockaddr *)&ss,
+ sa_socklen,
+ &remote_host);
+ if (rc != 0) {
+ ui.remote_host = NULL;
+ } else {
+ ui.remote_host = remote_host;
+ }
+
+ auth_time = timeval_set(authtime, 0);
+
+ if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
+ log_authentication_event(mit_ctx->db_ctx->msg_ctx,
+ mit_ctx->db_ctx->lp_ctx,
+ &auth_time,
+ &ui,
+ NT_STATUS_NO_SUCH_USER,
+ NULL,
+ NULL,
+ NULL);
+ } else {
+ 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);
+
+ ui.mapped.account_name = account_name;
+ ui.mapped.domain_name = domain_name;
+
+ log_authentication_event(mit_ctx->db_ctx->msg_ctx,
+ mit_ctx->db_ctx->lp_ctx,
+ &auth_time,
+ &ui,
+ status,
+ domain_name,
+ account_name,
+ sid);
+ }
+
+ SAFE_FREE(client_name);
+ TALLOC_FREE(frame);
+}