Print this page
NEX-18907 File Access Auditing does not work with SMB Kerberos authentication
Review by: Gordon Ross <gordon.ross@nexenta.com>
Review by: Evan Layton <evan.layton@nexenta.com>
NEX-13644 File access audit logging
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Roman Strashkin <roman.strashkin@nexenta.com>
Reviewed by: Saso Kiselkov <saso.kiselkov@nexenta.com>
Reviewed by: Rick McNeal <rick.mcneal@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-15558 SMB logon fails during 1st second after service start
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
NEX-8707 smb/server in 4.0.x does not accept username@hostname
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SMB-149 mount.cifs RedHat\Centos 6 doesn't work with default security options
        
@@ -18,11 +18,11 @@
  *
  * CDDL HEADER END
  */
 /*
  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
- * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
+ * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  */
 
 #include <sys/types.h>
 #include <errno.h>
 #include <synch.h>
@@ -74,51 +74,109 @@
 static smb_audit_t *smbd_audit_unlink(uint32_t);
 
 
 /*
  * Invoked at user logon due to SmbSessionSetupX.  Authenticate the
- * user, start an audit session and audit the event.
+ * user.
+ *
+ * On error, returns NULL, and status in user_info->lg_status
  */
 smb_token_t *
 smbd_user_auth_logon(smb_logon_t *user_info)
 {
         smb_token_t *token;
-        smb_audit_t *entry;
-        adt_session_data_t *ah;
-        adt_event_data_t *event;
         smb_logon_t tmp_user;
-        au_tid_addr_t termid;
-        char sidbuf[SMB_SID_STRSZ];
-        char *username;
-        char *domain;
-        uid_t uid;
-        gid_t gid;
-        char *sid;
-        int status;
-        int retval;
+        char *p;
+        char *buf = NULL;
 
         if (user_info->lg_username == NULL ||
             user_info->lg_domain == NULL ||
             user_info->lg_workstation == NULL) {
+                user_info->lg_status = NT_STATUS_INVALID_PARAMETER;
                 return (NULL);
         }
 
+        /*
+         * Avoid modifying the caller-provided struct because it
+         * may or may not point to allocated strings etc.
+         * Copy to tmp_user, auth, then copy the (out) lg_status
+         * member back to the caller-provided struct.
+         */
         tmp_user = *user_info;
         if (tmp_user.lg_username[0] == '\0') {
                 tmp_user.lg_flags |= SMB_ATF_ANON;
                 tmp_user.lg_e_username = "anonymous";
         } else {
                 tmp_user.lg_e_username = tmp_user.lg_username;
         }
+
+        /* Handle user@domain format. */
+        if (tmp_user.lg_domain[0] == '\0' &&
+            (p = strchr(tmp_user.lg_e_username, '@')) != NULL) {
+                buf = strdup(tmp_user.lg_e_username);
+                p = buf + (p - tmp_user.lg_e_username);
+                *p = '\0';
+                tmp_user.lg_e_domain = p + 1;
+                tmp_user.lg_e_username = buf;
+        } else {
         tmp_user.lg_e_domain = tmp_user.lg_domain;
+        }
 
-        if ((token = smb_logon(&tmp_user)) == NULL) {
+        token = smb_logon(&tmp_user);
+        user_info->lg_status = tmp_user.lg_status;
+
+        if (token == NULL) {
+                if (user_info->lg_status == 0) /* should not happen */
+                        user_info->lg_status = NT_STATUS_INTERNAL_ERROR;
+        }
+
+        if (!smbd_logon_audit(token, &user_info->lg_clnt_ipaddr,
+            tmp_user.lg_e_username, tmp_user.lg_e_domain)) {
+                user_info->lg_status = NT_STATUS_AUDIT_FAILED;
+                goto errout;
+        }
+
+        if (token) {
+                smb_autohome_add(token);
+        }
+
+        if (buf != NULL)
+                free(buf);
+
+        return (token);
+
+errout:
+        if (buf != NULL)
+                free(buf);
+        smb_token_destroy(token);
+        return (NULL);
+}
+
+/* Start an audit session and audit the event. */
+boolean_t
+smbd_logon_audit(smb_token_t *token, smb_inaddr_t *ipaddr, char *username,
+    char *domain)
+{
+        smb_audit_t *entry;
+        adt_session_data_t *ah = NULL;
+        adt_event_data_t *event;
+        au_tid_addr_t termid;
+        char sidbuf[SMB_SID_STRSZ];
+        uid_t uid;
+        gid_t gid;
+        char *sid;
+        int status;
+        int retval;
+
+        if (username == NULL)
+                username = "";
+
+        if (token == NULL) {
                 uid = ADT_NO_ATTRIB;
                 gid = ADT_NO_ATTRIB;
                 sid = NT_NULL_SIDSTR;
-                username = tmp_user.lg_e_username;
-                domain = tmp_user.lg_e_domain;
+                /* use the 'default' username and domain we were given */
                 status = ADT_FAILURE;
                 retval = ADT_FAIL_VALUE_AUTH;
         } else {
                 uid = token->tkn_user.i_id;
                 gid = token->tkn_primary_grp.i_id;
@@ -130,41 +188,36 @@
                 retval = ADT_SUCCESS;
         }
 
         if (adt_start_session(&ah, NULL, 0)) {
                 syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
-                smb_token_destroy(token);
-                return (NULL);
+                goto errout;
         }
 
         if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
                 syslog(LOG_AUTH | LOG_ALERT,
                     "adt_alloc_event(ADT_smbd_session): %m");
-                (void) adt_end_session(ah);
-                smb_token_destroy(token);
-                return (NULL);
+                goto errout;
         }
 
         (void) memset(&termid, 0, sizeof (au_tid_addr_t));
-        termid.at_port = user_info->lg_local_port;
+        termid.at_port = 445;
 
-        if (user_info->lg_clnt_ipaddr.a_family == AF_INET) {
-                termid.at_addr[0] = user_info->lg_clnt_ipaddr.a_ipv4;
+        if (ipaddr->a_family == AF_INET) {
+                termid.at_addr[0] = ipaddr->a_ipv4;
                 termid.at_type = AU_IPv4;
         } else {
-                bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
+                bcopy(&ipaddr->a_ip, termid.at_addr,
                     sizeof (in6_addr_t));
                 termid.at_type = AU_IPv6;
         }
         adt_set_termid(ah, &termid);
 
         if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
                 syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
                 adt_free_event(event);
-                (void) adt_end_session(ah);
-                smb_token_destroy(token);
-                return (NULL);
+                goto errout;
         }
 
         event->adt_smbd_session.domain = domain;
         event->adt_smbd_session.username = username;
         event->adt_smbd_session.sid = sid;
@@ -175,27 +228,32 @@
         adt_free_event(event);
 
         if (token) {
                 if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
                         syslog(LOG_ERR, "smbd_user_auth_logon: %m");
-                        (void) adt_end_session(ah);
-                        smb_token_destroy(token);
-                        return (NULL);
+                        goto errout;
                 }
 
                 entry->sa_handle = ah;
                 entry->sa_uid = uid;
                 entry->sa_gid = gid;
                 entry->sa_username = strdup(username);
                 entry->sa_domain = strdup(domain);
 
-                smb_autohome_add(token);
                 smbd_audit_link(entry);
                 token->tkn_audit_sid = entry->sa_audit_sid;
+                adt_get_auid(ah, &token->tkn_auid);
+                adt_get_mask(ah, &token->tkn_amask);
+                adt_get_asid(ah, &token->tkn_asid);
         }
 
-        return (token);
+        return (B_TRUE);
+errout:
+        if (ah != NULL)
+                (void) adt_end_session(ah);
+
+        return (B_FALSE);
 }
 
 /*
  * Logon due to a subsequent SmbSessionSetupX on an existing session.
  * The user was authenticated during the initial session setup.