From a0ab86dedca2471ca2e4bb222f272d4bd35c85df Mon Sep 17 00:00:00 2001 From: Andrew Bartlett Date: Wed, 1 Mar 2017 12:18:49 +1300 Subject: [PATCH] auth: Add logging of service authorization In ntlm_auth.c and authdata.c, the session info will be incomplete Signed-off-by: Andrew Bartlett Pair-Programmed-by: Gary Lockyer Signed-off-by: Gary Lockyer --- auth/auth_log.c | 54 +++++++++++++++++++++++++++++++++++++++ auth/common_auth.h | 5 ++++ auth/gensec/gensec.c | 36 ++++++++++++++++++++++++-- auth/gensec/gensec.h | 1 + source3/libads/authdata.c | 3 +++ source3/utils/ntlm_auth.c | 3 +++ 6 files changed, 100 insertions(+), 2 deletions(-) diff --git a/auth/auth_log.c b/auth/auth_log.c index 64b6eaa102c..9bbc172e664 100644 --- a/auth/auth_log.c +++ b/auth/auth_log.c @@ -159,3 +159,57 @@ void log_authentication_event(const struct auth_usersupplied_info *ui, talloc_free(frame); } + + +/* + * Log details of a successful authorization to a service. + * + * Only successful authorizations are logged. For clarity: + * - NTLM bad passwords will be recorded by the above + * - Kerberos decrypt failures need to be logged in gensec_gssapi et al + * + * The service may later refuse authorization due to an ACL. + * + */ +void log_successful_authz_event(const struct tsocket_address *remote, + const struct tsocket_address *local, + const char *service_description, + struct auth_session_info *session_info) +{ + TALLOC_CTX *frame = NULL; + + char *ts = NULL; /* formatted current time */ + char *remote_str = NULL; /* formatted remote host */ + char *local_str = NULL; /* formatted local host */ + char sid_buf[DOM_SID_STR_BUFLEN]; + + /* set the log level */ + if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL)) { + return; + } + + frame = talloc_stackframe(); + + /* Get the current time */ + ts = http_timestring(frame, time(NULL)); + + remote_str = tsocket_address_string(remote, frame); + local_str = tsocket_address_string(local, frame); + + dom_sid_string_buf(&session_info->security_token->sids[0], sid_buf, sizeof(sid_buf)); + + DEBUGC( DBGC_AUTH_AUDIT, AUTHZ_SUCCESS_LEVEL, ( + "Successful AuthZ: [%s] user [%s]\\[%s] [%s]" + " at [%s]" + " Remote host [%s]" + " local host [%s]\n", + service_description, + log_escape(frame, session_info->info->domain_name), + log_escape(frame, session_info->info->account_name), + sid_buf, + ts, + remote_str, + local_str)); + + talloc_free(frame); +} diff --git a/auth/common_auth.h b/auth/common_auth.h index c2ba846de54..8950a0cdc91 100644 --- a/auth/common_auth.h +++ b/auth/common_auth.h @@ -152,4 +152,9 @@ void log_authentication_event(const struct auth_usersupplied_info *ui, const char *domain_name, const char *unix_username, struct dom_sid *sid); + +void log_successful_authz_event(const struct tsocket_address *remote, + const struct tsocket_address *local, + const char *service_description, + struct auth_session_info *session_info); #endif diff --git a/auth/gensec/gensec.c b/auth/gensec/gensec.c index e413fbdfd6f..63cc35e9074 100644 --- a/auth/gensec/gensec.c +++ b/auth/gensec/gensec.c @@ -29,6 +29,7 @@ #include "auth/gensec/gensec.h" #include "auth/gensec/gensec_internal.h" #include "librpc/gen_ndr/dcerpc.h" +#include "auth/common_auth.h" _PRIVATE_ NTSTATUS gensec_may_reset_crypto(struct gensec_security *gensec_security, bool full_reset) @@ -192,13 +193,36 @@ _PUBLIC_ NTSTATUS gensec_session_key(struct gensec_security *gensec_security, return gensec_security->ops->session_key(gensec_security, mem_ctx, session_key); } +/* + * Log details of a successful GENSEC authorization to a service. + * + * Only successful authorizations are logged, as only these call gensec_session_info() + * + * The service may later refuse authorization due to an ACL. + * + */ +static void log_successful_gensec_authz_event(struct gensec_security *gensec_security, + struct auth_session_info *session_info) +{ + const struct tsocket_address *remote + = gensec_get_remote_address(gensec_security); + const struct tsocket_address *local + = gensec_get_local_address(gensec_security); + const char *service_description + = gensec_get_target_service_description(gensec_security); + log_successful_authz_event(remote, local, service_description, session_info); +} + + /** * Return the credentials of a logged on user, including session keys * etc. * * Only valid after a successful authentication * - * May only be called once per authentication. + * May only be called once per authentication. This will also make an + * authorization log entry, as it is already called by all the + * callers. * */ @@ -206,10 +230,18 @@ _PUBLIC_ NTSTATUS gensec_session_info(struct gensec_security *gensec_security, TALLOC_CTX *mem_ctx, struct auth_session_info **session_info) { + NTSTATUS status; if (!gensec_security->ops->session_info) { return NT_STATUS_NOT_IMPLEMENTED; } - return gensec_security->ops->session_info(gensec_security, mem_ctx, session_info); + status = gensec_security->ops->session_info(gensec_security, mem_ctx, session_info); + + if (NT_STATUS_IS_OK(status) && !gensec_security->subcontext + && (gensec_security->want_features & GENSEC_FEATURE_NO_AUTHZ_LOG) == 0) { + log_successful_gensec_authz_event(gensec_security, *session_info); + } + + return status; } _PUBLIC_ void gensec_set_max_update_size(struct gensec_security *gensec_security, diff --git a/auth/gensec/gensec.h b/auth/gensec/gensec.h index 0c9fa2661a8..7bd893266b9 100644 --- a/auth/gensec/gensec.h +++ b/auth/gensec/gensec.h @@ -64,6 +64,7 @@ struct gensec_target { #define GENSEC_FEATURE_UNIX_TOKEN 0x00000100 #define GENSEC_FEATURE_NTLM_CCACHE 0x00000200 #define GENSEC_FEATURE_LDAP_STYLE 0x00000400 +#define GENSEC_FEATURE_NO_AUTHZ_LOG 0x00000800 #define GENSEC_EXPIRE_TIME_INFINITY (NTTIME)0x8000000000000000LL diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index f4f4b4f1898..d8a6487dc27 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -269,6 +269,9 @@ NTSTATUS kerberos_return_pac(TALLOC_CTX *mem_ctx, talloc_unlink(tmp_ctx, gensec_settings); talloc_unlink(tmp_ctx, auth_context); + /* Session info is not complete, do not pass to auth log */ + gensec_want_feature(gensec_server_context, GENSEC_FEATURE_NO_AUTHZ_LOG); + status = gensec_start_mech_by_oid(gensec_server_context, GENSEC_OID_KERBEROS5); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, (__location__ "Failed to start server-side GENSEC krb5 to validate a Kerberos ticket: %s\n", nt_errstr(status))); diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index c0b55215300..6a7a269987c 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -1455,6 +1455,9 @@ static void manage_gensec_request(enum stdio_helper_mode stdio_helper_mode, gensec_want_feature_list(state->gensec_state, want_feature_list); + /* Session info is not complete, do not pass to auth log */ + gensec_want_feature(state->gensec_state, GENSEC_FEATURE_NO_AUTHZ_LOG); + switch (stdio_helper_mode) { case GSS_SPNEGO_CLIENT: case GSS_SPNEGO_SERVER: -- 2.34.1