auth: Add logging of service authorization
authorAndrew Bartlett <abartlet@samba.org>
Tue, 28 Feb 2017 23:18:49 +0000 (12:18 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 29 Mar 2017 00:37:27 +0000 (02:37 +0200)
In ntlm_auth.c and authdata.c, the session info will be incomplete

Signed-off-by: Andrew Bartlett <abartlet@samba.org>
Pair-Programmed-by: Gary Lockyer <gary@catalyst.net.nz>
Signed-off-by: Gary Lockyer <gary@catalyst.net.nz>
auth/auth_log.c
auth/common_auth.h
auth/gensec/gensec.c
auth/gensec/gensec.h
source3/libads/authdata.c
source3/utils/ntlm_auth.c

index 64b6eaa102cd72348cd3887a61e268c7fb2a71ef..9bbc172e664dcaebe1d6960c9b210534cf99958c 100644 (file)
@@ -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);
+}
index c2ba846de54dd2ef7ba137b5de84164edccd85ff..8950a0cdc9196f9065098402049e4163ba5c3feb 100644 (file)
@@ -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
index e413fbdfd6fdbd26b0121ea8459d4a84a2bae2aa..63cc35e907416120a71385c510ec4cff642f942e 100644 (file)
@@ -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,
index 0c9fa2661a84f49a43b0b2716ce2f0b68ad44881..7bd893266b95f4fb5057ee8dcca4371fd535d237 100644 (file)
@@ -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
 
index f4f4b4f1898543446be6ce79fc5af6e0176266a9..d8a6487dc27ddd3fde8494649dcd3091268d8758 100644 (file)
@@ -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)));
index c0b552153000e5036ef107e39b89aed5d305427a..6a7a269987c67f86a7afc39b61e24297ef76df12 100644 (file)
@@ -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: