auth: Generate a human readable Authentication log message.
authorGary Lockyer <gary@catalyst.net.nz>
Thu, 23 Feb 2017 00:50:14 +0000 (13:50 +1300)
committerAndrew Bartlett <abartlet@samba.org>
Wed, 29 Mar 2017 00:37:26 +0000 (02:37 +0200)
Add a human readable authentication log line, to allow
verification that all required details are being passed.

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 [new file with mode: 0644]
auth/common_auth.h
auth/wscript_build
source3/auth/auth.c
source3/rpc_server/wscript_build
source4/auth/kerberos/wscript_build
source4/auth/ntlm/auth.c
source4/kdc/wscript_build

diff --git a/auth/auth_log.c b/auth/auth_log.c
new file mode 100644 (file)
index 0000000..64b6eaa
--- /dev/null
@@ -0,0 +1,161 @@
+/*
+
+   Authentication and authorization logging
+
+   Copyright (C) Andrew Bartlett <abartlet@samba.org> 2017
+
+   This program is free software; you can redistribute it and/or modify
+   it under the terms of the GNU General Public License as published by
+   the Free Software Foundation; either version 3 of the License, or
+   (at your option) any later version.
+
+   This program is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+   GNU General Public License for more details.
+
+   You should have received a copy of the GNU General Public License
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
+*/
+
+/*
+ * Debug log levels for authentication logging (these both map to
+ * LOG_NOTICE in syslog)
+ */
+#define AUTH_SUCCESS_LEVEL 4
+#define AUTHZ_SUCCESS_LEVEL 5
+#define AUTH_FAILURE_LEVEL 2
+
+#include "includes.h"
+#include "../lib/tsocket/tsocket.h"
+#include "common_auth.h"
+#include "lib/util/util_str_escape.h"
+#include "libcli/security/dom_sid.h"
+
+/*
+ * Get a human readable timestamp.
+ *
+ * Returns the current time formatted as
+ *  "Tue, 14 Mar 2017 08:38:42.209028 NZDT"
+ *
+ * The returned string is allocated by talloc in the supplied context.
+ * It is the callers responsibility to free it.
+ *
+ */
+static const char* get_timestamp( TALLOC_CTX *frame )
+{
+       char buffer[40];        /* formatted time less usec and timezone */
+       char tz[10];            /* formatted time zone                   */
+       struct tm* tm_info;     /* current local time                    */
+       struct timeval tv;      /* current system time                   */
+       int r;                  /* response code from gettimeofday       */
+       const char * ts;        /* formatted time stamp                  */
+
+       r = gettimeofday(&tv, NULL);
+       if (r) {
+               DBG_ERR("Unable to get time of day: (%d) %s\n",
+                       errno,
+                       strerror( errno));
+               return NULL;
+       }
+
+       tm_info = localtime(&tv.tv_sec);
+       if (tm_info == NULL) {
+               DBG_ERR("Unable to determine local time\n");
+               return NULL;
+       }
+
+       strftime(buffer, sizeof(buffer)-1, "%a, %d %b %Y %H:%M:%S", tm_info);
+       strftime(tz, sizeof(tz)-1, "%Z", tm_info);
+       ts = talloc_asprintf(frame, "%s.%06ld %s", buffer, tv.tv_usec, tz);
+       if (ts == NULL) {
+               DBG_ERR("Out of memory formatting time stamp\n");
+       }
+       return ts;
+}
+
+/*
+ * Log details of an authentication attempt.
+ * Successful and unsuccessful attempts are logged.
+ *
+ */
+void log_authentication_event(const struct auth_usersupplied_info *ui,
+                             NTSTATUS status,
+                             const char *domain_name,
+                             const char *account_name,
+                             const char *unix_username,
+                             struct dom_sid *sid)
+{
+       TALLOC_CTX *frame = NULL;
+
+       const char *ts = NULL;             /* formatted current time      */
+       char *remote = NULL;               /* formatted remote host       */
+       char *local = NULL;                /* formatted local host        */
+       char *nl = NULL;                   /* NETLOGON details if present */
+       char *trust_computer_name = NULL;
+       char *trust_account_name = NULL;
+       char *logon_line = NULL;
+
+       /* set the log level */
+       int  level = NT_STATUS_IS_OK(status) ? AUTH_FAILURE_LEVEL : AUTH_SUCCESS_LEVEL;
+       if (!CHECK_DEBUGLVLC( DBGC_AUTH_AUDIT, level)) {
+               return;
+       }
+
+       frame = talloc_stackframe();
+
+       /* Get the current time */
+        ts = get_timestamp(frame);
+
+       /* Only log the NETLOGON details if they are present */
+       if (ui->netlogon_trust_account.computer_name ||
+           ui->netlogon_trust_account.account_name) {
+               trust_computer_name = log_escape(frame,
+                       ui->netlogon_trust_account.computer_name);
+               trust_account_name  = log_escape(frame,
+                       ui->netlogon_trust_account.account_name);
+               nl = talloc_asprintf(frame,
+                       " NETLOGON computer [%s] trust account [%s]",
+                       trust_computer_name, trust_account_name);
+       }
+
+       remote = tsocket_address_string(ui->remote_host, frame);
+       local  = tsocket_address_string(ui->local_host, frame);
+
+       if (NT_STATUS_IS_OK(status)) {
+               char sid_buf[DOM_SID_STR_BUFLEN];
+
+               dom_sid_string_buf(sid, sid_buf, sizeof(sid_buf));
+               logon_line = talloc_asprintf(frame,
+                                            " became [%s]\\[%s] [%s].",
+                                            log_escape(frame, domain_name),
+                                            log_escape(frame, account_name),
+                                            sid_buf);
+       } else {
+               logon_line = talloc_asprintf(frame,
+                                            " mapped to [%s]\\[%s].",
+                                            log_escape(frame, ui->mapped.domain_name),
+                                            log_escape(frame, ui->mapped.account_name));
+       }
+
+       DEBUGC( DBGC_AUTH_AUDIT, level, (
+               "Auth: [%s,%s] user [%s]\\[%s]"
+               " at [%s] status [%s]"
+               " workstation [%s] remote host [%s]"
+               "%s local host [%s]"
+               " %s\n",
+               ui->service_description,
+               ui->auth_description,
+               log_escape(frame, ui->client.domain_name),
+               log_escape(frame, ui->client.account_name),
+               ts,
+               nt_errstr( status),
+               log_escape(frame, ui->workstation_name),
+               remote,
+               logon_line,
+               local,
+               nl ? nl : ""
+               ));
+
+       talloc_free(frame);
+}
index d775b750c4b231625c666eee386bee6932159183..c2ba846de54dd2ef7ba137b5de84164edccd85ff 100644 (file)
@@ -146,4 +146,10 @@ struct auth4_context {
                                              struct auth_session_info **session_info);
 };
 
+void log_authentication_event(const struct auth_usersupplied_info *ui,
+                             NTSTATUS status,
+                             const char *account_name,
+                             const char *domain_name,
+                             const char *unix_username,
+                             struct dom_sid *sid);
 #endif
index 20261537fbd755c835c2972d72de5b8ed97d682b..732536d686ee7417aa7cfa929d5a43ece0fbf575 100644 (file)
@@ -1,8 +1,8 @@
 #!/usr/bin/env python
 
-bld.SAMBA_LIBRARY('auth_sam_reply',
-                  source='auth_sam_reply.c wbc_auth_util.c',
-                  deps='talloc samba-security samba-util',
+bld.SAMBA_LIBRARY('common_auth',
+                  source='auth_sam_reply.c wbc_auth_util.c auth_log.c',
+                  deps='talloc samba-security samba-util util_str_escape LIBTSOCKET',
                   private_library=True
                   )
 
index 50ff19f1ddfe83f19669d38d66a02a75a95027f4..45bcabd2721ddef74feac521d7c47d230c0dc86f 100644 (file)
@@ -174,7 +174,8 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
        NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
        const char *unix_username;
        auth_methods *auth_method;
-       struct auth_serversupplied_info *server_info;
+       struct auth_serversupplied_info *server_info = NULL;
+       struct dom_sid sid = {0};
 
        if (user_info == NULL || auth_context == NULL || pserver_info == NULL) {
                return NT_STATUS_LOGON_FAILURE;
@@ -291,6 +292,18 @@ NTSTATUS auth_check_ntlm_password(TALLOC_CTX *mem_ctx,
                goto fail;
        }
 
+       nt_status = get_user_sid_info3_and_extra(server_info->info3,
+                                                &server_info->extra,
+                                                &sid);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               sid = (struct dom_sid) {0};
+       }
+
+       log_authentication_event(user_info, nt_status,
+                                server_info->info3->base.logon_domain.string,
+                                server_info->info3->base.account_name.string,
+                                unix_username, &sid);
+
        DEBUG(server_info->guest ? 5 : 2,
              ("check_ntlm_password:  %sauthentication for user "
               "[%s] -> [%s] -> [%s] succeeded\n",
@@ -316,6 +329,9 @@ fail:
                  "[%s] -> [%s] FAILED with error %s, authoritative=%u\n",
                  user_info->client.account_name, user_info->mapped.account_name,
                  nt_errstr(nt_status), *pauthoritative));
+
+       log_authentication_event(user_info, nt_status, NULL, NULL, NULL, NULL);
+
        ZERO_STRUCTP(pserver_info);
 
        TALLOC_FREE(frame);
index 7fe4fda9df54bd6bb607b8f4096c22921c30e54e..ae75e567ace2d00edb718a47bbd51679f6225abe 100644 (file)
@@ -11,7 +11,7 @@ bld.SAMBA3_SUBSYSTEM('RPC_CONFIG',
 
 bld.SAMBA3_SUBSYSTEM('RPC_NCACN_NP',
                     source='rpc_ncacn_np.c rpc_handles.c rpc_contexts.c',
-                    deps='RPC_CONFIG auth auth_sam_reply RPC_PIPE_REGISTER npa_tstream')
+                    deps='RPC_CONFIG auth common_auth RPC_PIPE_REGISTER npa_tstream')
 
 bld.SAMBA3_SUBSYSTEM('RPC_SERVER_LOOP',
                     source='rpc_server.c',
index 0f886fa7c481e132510a5839098079e14e7882db..30853ec33c510c754c1a903157148a3daa4f1731 100644 (file)
@@ -9,7 +9,7 @@ bld.SAMBA_LIBRARY('authkrb5',
                   source='kerberos_pac.c',
                   autoproto='proto.h',
                   public_deps='ndr-krb5pac krb5samba samba_socket LIBCLI_RESOLVE asn1',
-                  deps='auth_sam_reply tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC samba-errors',
+                  deps='common_auth tevent LIBPACKET ndr ldb krb5samba KRB_INIT_CTX KRB5_PAC samba-errors',
                   private_library=True
                   )
 
index 9bde07323fcebdfce8bc5f56dafa628ae3f60f50..18ecf853fce01d23eb99b1ca5a03a207bd6ee78d 100644 (file)
@@ -432,7 +432,7 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
 {
        struct auth_check_password_state *state =
                tevent_req_data(req, struct auth_check_password_state);
-       NTSTATUS status;
+       NTSTATUS status = NT_STATUS_OK;
 
        *pauthoritative = state->authoritative;
 
@@ -448,6 +448,9 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
                         state->user_info->mapped.domain_name,
                         state->user_info->mapped.account_name,
                         nt_errstr(status), state->authoritative));
+
+               log_authentication_event(state->user_info, status,
+                                        NULL, NULL, NULL, NULL);
                tevent_req_received(req);
                return status;
        }
@@ -458,6 +461,12 @@ _PUBLIC_ NTSTATUS auth_check_password_recv(struct tevent_req *req,
                 state->user_info_dc->info->domain_name,
                 state->user_info_dc->info->account_name));
 
+       log_authentication_event(state->user_info, status,
+                                state->user_info_dc->info->domain_name,
+                                state->user_info_dc->info->account_name,
+                                NULL,
+                                &state->user_info_dc->sids[0]);
+
        *user_info_dc = talloc_move(mem_ctx, &state->user_info_dc);
 
        tevent_req_received(req);
index 24d89f4c89b8e92a032d33606530b69dc94a0036..76efb1f02ca206b25be7989e4a20ebd649223f2f 100644 (file)
@@ -27,7 +27,7 @@ bld.SAMBA_MODULE('service_kdc',
 
 bld.SAMBA_LIBRARY('HDB_SAMBA4',
                   source='hdb-samba4.c hdb-samba4-plugin.c',
-                  deps='ldb auth4_sam auth_sam_reply samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb',
+                  deps='ldb auth4_sam common_auth samba-credentials hdb db-glue samba-hostconfig com_err sdb_hdb',
                   includes=kdc_include,
                   private_library=True,
                   enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL')
@@ -78,7 +78,7 @@ bld.SAMBA_SUBSYSTEM('KDC-GLUE',
 bld.SAMBA_SUBSYSTEM('WDC_SAMBA4',
        source='wdc-samba4.c',
         includes=kdc_include,
-       deps='ldb auth4_sam auth_sam_reply samba-credentials hdb PAC_GLUE samba-hostconfig com_err KDC-GLUE',
+       deps='ldb auth4_sam common_auth samba-credentials hdb PAC_GLUE samba-hostconfig com_err KDC-GLUE',
        enabled=bld.CONFIG_SET('SAMBA4_USES_HEIMDAL')
        )
 
@@ -107,7 +107,7 @@ bld.SAMBA_SUBSYSTEM('sdb_kdb',
 bld.SAMBA_SUBSYSTEM('PAC_GLUE',
        source='pac-glue.c',
         includes=kdc_include,
-       deps='ldb auth4_sam auth_sam_reply samba-credentials samba-hostconfig com_err'
+       deps='ldb auth4_sam common_auth samba-credentials samba-hostconfig com_err'
        )
 
 bld.SAMBA_LIBRARY('pac',
@@ -119,7 +119,7 @@ bld.SAMBA_LIBRARY('pac',
 
 bld.SAMBA_LIBRARY('db-glue',
        source='db-glue.c',
-       deps='ldb auth4_sam auth_sam_reply samba-credentials sdb samba-hostconfig com_err',
+       deps='ldb auth4_sam common_auth samba-credentials sdb samba-hostconfig com_err',
        private_library=True,
         includes=kdc_include,
        )
@@ -134,7 +134,7 @@ bld.SAMBA_SUBSYSTEM('MIT_SAMBA',
                     deps='''
                          ldb
                          auth4_sam
-                         auth_sam_reply
+                         common_auth
                          samba-credentials
                          db-glue
                          PAC_GLUE