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


   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2014 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <errno.h>
  28 #include <synch.h>
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <unistd.h>
  32 #include <string.h>
  33 #include <strings.h>
  34 #include <syslog.h>
  35 #include <fcntl.h>
  36 #include <bsm/adt.h>
  37 #include <bsm/adt_event.h>
  38 #include <bsm/audit_uevents.h>
  39 #include <pwd.h>
  40 #include <nss_dbdefs.h>
  41 #include <sys/idmap.h>
  42 #include "smbd.h"
  43 


  59         uint32_t sa_refcnt;
  60         char *sa_domain;
  61         char *sa_username;
  62 } smb_audit_t;
  63 
  64 static smb_audit_t *smbd_audit_list;
  65 static mutex_t smbd_audit_lock;
  66 
  67 /*
  68  * Unique identifier for audit sessions in the audit list.
  69  * Used to lookup an audit session on logoff.
  70  */
  71 static uint32_t smbd_audit_sid;
  72 
  73 static void smbd_audit_link(smb_audit_t *);
  74 static smb_audit_t *smbd_audit_unlink(uint32_t);
  75 
  76 
  77 /*
  78  * Invoked at user logon due to SmbSessionSetupX.  Authenticate the
  79  * user, start an audit session and audit the event.


  80  */
  81 smb_token_t *
  82 smbd_user_auth_logon(smb_logon_t *user_info)
  83 {
  84         smb_token_t *token;
  85         smb_audit_t *entry;
  86         adt_session_data_t *ah;
  87         adt_event_data_t *event;
  88         smb_logon_t tmp_user;
  89         au_tid_addr_t termid;
  90         char sidbuf[SMB_SID_STRSZ];
  91         char *username;
  92         char *domain;
  93         uid_t uid;
  94         gid_t gid;
  95         char *sid;
  96         int status;
  97         int retval;
  98 
  99         if (user_info->lg_username == NULL ||
 100             user_info->lg_domain == NULL ||
 101             user_info->lg_workstation == NULL) {

 102                 return (NULL);
 103         }
 104 






 105         tmp_user = *user_info;
 106         if (tmp_user.lg_username[0] == '\0') {
 107                 tmp_user.lg_flags |= SMB_ATF_ANON;
 108                 tmp_user.lg_e_username = "anonymous";
 109         } else {
 110                 tmp_user.lg_e_username = tmp_user.lg_username;
 111         }










 112         tmp_user.lg_e_domain = tmp_user.lg_domain;

 113 
 114         if ((token = smb_logon(&tmp_user)) == NULL) {

















































 115                 uid = ADT_NO_ATTRIB;
 116                 gid = ADT_NO_ATTRIB;
 117                 sid = NT_NULL_SIDSTR;
 118                 username = tmp_user.lg_e_username;
 119                 domain = tmp_user.lg_e_domain;
 120                 status = ADT_FAILURE;
 121                 retval = ADT_FAIL_VALUE_AUTH;
 122         } else {
 123                 uid = token->tkn_user.i_id;
 124                 gid = token->tkn_primary_grp.i_id;
 125                 smb_sid_tostr(token->tkn_user.i_sid, sidbuf);
 126                 sid = sidbuf;
 127                 username = token->tkn_account_name;
 128                 domain = token->tkn_domain_name;
 129                 status = ADT_SUCCESS;
 130                 retval = ADT_SUCCESS;
 131         }
 132 
 133         if (adt_start_session(&ah, NULL, 0)) {
 134                 syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
 135                 smb_token_destroy(token);
 136                 return (NULL);
 137         }
 138 
 139         if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
 140                 syslog(LOG_AUTH | LOG_ALERT,
 141                     "adt_alloc_event(ADT_smbd_session): %m");
 142                 (void) adt_end_session(ah);
 143                 smb_token_destroy(token);
 144                 return (NULL);
 145         }
 146 
 147         (void) memset(&termid, 0, sizeof (au_tid_addr_t));
 148         termid.at_port = user_info->lg_local_port;
 149 
 150         if (user_info->lg_clnt_ipaddr.a_family == AF_INET) {
 151                 termid.at_addr[0] = user_info->lg_clnt_ipaddr.a_ipv4;
 152                 termid.at_type = AU_IPv4;
 153         } else {
 154                 bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
 155                     sizeof (in6_addr_t));
 156                 termid.at_type = AU_IPv6;
 157         }
 158         adt_set_termid(ah, &termid);
 159 
 160         if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
 161                 syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
 162                 adt_free_event(event);
 163                 (void) adt_end_session(ah);
 164                 smb_token_destroy(token);
 165                 return (NULL);
 166         }
 167 
 168         event->adt_smbd_session.domain = domain;
 169         event->adt_smbd_session.username = username;
 170         event->adt_smbd_session.sid = sid;
 171 
 172         if (adt_put_event(event, status, retval))
 173                 syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
 174 
 175         adt_free_event(event);
 176 
 177         if (token) {
 178                 if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
 179                         syslog(LOG_ERR, "smbd_user_auth_logon: %m");
 180                         (void) adt_end_session(ah);
 181                         smb_token_destroy(token);
 182                         return (NULL);
 183                 }
 184 
 185                 entry->sa_handle = ah;
 186                 entry->sa_uid = uid;
 187                 entry->sa_gid = gid;
 188                 entry->sa_username = strdup(username);
 189                 entry->sa_domain = strdup(domain);
 190 
 191                 smb_autohome_add(token);
 192                 smbd_audit_link(entry);
 193                 token->tkn_audit_sid = entry->sa_audit_sid;



 194         }
 195 
 196         return (token);





 197 }
 198 
 199 /*
 200  * Logon due to a subsequent SmbSessionSetupX on an existing session.
 201  * The user was authenticated during the initial session setup.
 202  */
 203 void
 204 smbd_user_nonauth_logon(uint32_t audit_sid)
 205 {
 206         smb_audit_t *entry;
 207 
 208         (void) mutex_lock(&smbd_audit_lock);
 209         entry = smbd_audit_list;
 210 
 211         while (entry) {
 212                 if (entry->sa_audit_sid == audit_sid) {
 213                         ++entry->sa_refcnt;
 214                         break;
 215                 }
 216 




   3  *
   4  * The contents of this file are subject to the terms of the
   5  * Common Development and Distribution License (the "License").
   6  * You may not use this file except in compliance with the License.
   7  *
   8  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
   9  * or http://www.opensolaris.org/os/licensing.
  10  * See the License for the specific language governing permissions
  11  * and limitations under the License.
  12  *
  13  * When distributing Covered Code, include this CDDL HEADER in each
  14  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
  15  * If applicable, add the following below this CDDL HEADER, with the
  16  * fields enclosed by brackets "[]" replaced with your own identifying
  17  * information: Portions Copyright [yyyy] [name of copyright owner]
  18  *
  19  * CDDL HEADER END
  20  */
  21 /*
  22  * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
  23  * Copyright 2018 Nexenta Systems, Inc.  All rights reserved.
  24  */
  25 
  26 #include <sys/types.h>
  27 #include <errno.h>
  28 #include <synch.h>
  29 #include <stdio.h>
  30 #include <stdlib.h>
  31 #include <unistd.h>
  32 #include <string.h>
  33 #include <strings.h>
  34 #include <syslog.h>
  35 #include <fcntl.h>
  36 #include <bsm/adt.h>
  37 #include <bsm/adt_event.h>
  38 #include <bsm/audit_uevents.h>
  39 #include <pwd.h>
  40 #include <nss_dbdefs.h>
  41 #include <sys/idmap.h>
  42 #include "smbd.h"
  43 


  59         uint32_t sa_refcnt;
  60         char *sa_domain;
  61         char *sa_username;
  62 } smb_audit_t;
  63 
  64 static smb_audit_t *smbd_audit_list;
  65 static mutex_t smbd_audit_lock;
  66 
  67 /*
  68  * Unique identifier for audit sessions in the audit list.
  69  * Used to lookup an audit session on logoff.
  70  */
  71 static uint32_t smbd_audit_sid;
  72 
  73 static void smbd_audit_link(smb_audit_t *);
  74 static smb_audit_t *smbd_audit_unlink(uint32_t);
  75 
  76 
  77 /*
  78  * Invoked at user logon due to SmbSessionSetupX.  Authenticate the
  79  * user.
  80  *
  81  * On error, returns NULL, and status in user_info->lg_status
  82  */
  83 smb_token_t *
  84 smbd_user_auth_logon(smb_logon_t *user_info)
  85 {
  86         smb_token_t *token;



  87         smb_logon_t tmp_user;
  88         char *p;
  89         char *buf = NULL;







  90 
  91         if (user_info->lg_username == NULL ||
  92             user_info->lg_domain == NULL ||
  93             user_info->lg_workstation == NULL) {
  94                 user_info->lg_status = NT_STATUS_INVALID_PARAMETER;
  95                 return (NULL);
  96         }
  97 
  98         /*
  99          * Avoid modifying the caller-provided struct because it
 100          * may or may not point to allocated strings etc.
 101          * Copy to tmp_user, auth, then copy the (out) lg_status
 102          * member back to the caller-provided struct.
 103          */
 104         tmp_user = *user_info;
 105         if (tmp_user.lg_username[0] == '\0') {
 106                 tmp_user.lg_flags |= SMB_ATF_ANON;
 107                 tmp_user.lg_e_username = "anonymous";
 108         } else {
 109                 tmp_user.lg_e_username = tmp_user.lg_username;
 110         }
 111 
 112         /* Handle user@domain format. */
 113         if (tmp_user.lg_domain[0] == '\0' &&
 114             (p = strchr(tmp_user.lg_e_username, '@')) != NULL) {
 115                 buf = strdup(tmp_user.lg_e_username);
 116                 p = buf + (p - tmp_user.lg_e_username);
 117                 *p = '\0';
 118                 tmp_user.lg_e_domain = p + 1;
 119                 tmp_user.lg_e_username = buf;
 120         } else {
 121                 tmp_user.lg_e_domain = tmp_user.lg_domain;
 122         }
 123 
 124         token = smb_logon(&tmp_user);
 125         user_info->lg_status = tmp_user.lg_status;
 126 
 127         if (token == NULL) {
 128                 if (user_info->lg_status == 0) /* should not happen */
 129                         user_info->lg_status = NT_STATUS_INTERNAL_ERROR;
 130         }
 131 
 132         if (!smbd_logon_audit(token, &user_info->lg_clnt_ipaddr,
 133             tmp_user.lg_e_username, tmp_user.lg_e_domain)) {
 134                 user_info->lg_status = NT_STATUS_AUDIT_FAILED;
 135                 goto errout;
 136         }
 137 
 138         if (token) {
 139                 smb_autohome_add(token);
 140         }
 141 
 142         if (buf != NULL)
 143                 free(buf);
 144 
 145         return (token);
 146 
 147 errout:
 148         if (buf != NULL)
 149                 free(buf);
 150         smb_token_destroy(token);
 151         return (NULL);
 152 }
 153 
 154 /* Start an audit session and audit the event. */
 155 boolean_t
 156 smbd_logon_audit(smb_token_t *token, smb_inaddr_t *ipaddr, char *username,
 157     char *domain)
 158 {
 159         smb_audit_t *entry;
 160         adt_session_data_t *ah = NULL;
 161         adt_event_data_t *event;
 162         au_tid_addr_t termid;
 163         char sidbuf[SMB_SID_STRSZ];
 164         uid_t uid;
 165         gid_t gid;
 166         char *sid;
 167         int status;
 168         int retval;
 169 
 170         if (username == NULL)
 171                 username = "";
 172 
 173         if (token == NULL) {
 174                 uid = ADT_NO_ATTRIB;
 175                 gid = ADT_NO_ATTRIB;
 176                 sid = NT_NULL_SIDSTR;
 177                 /* use the 'default' username and domain we were given */

 178                 status = ADT_FAILURE;
 179                 retval = ADT_FAIL_VALUE_AUTH;
 180         } else {
 181                 uid = token->tkn_user.i_id;
 182                 gid = token->tkn_primary_grp.i_id;
 183                 smb_sid_tostr(token->tkn_user.i_sid, sidbuf);
 184                 sid = sidbuf;
 185                 username = token->tkn_account_name;
 186                 domain = token->tkn_domain_name;
 187                 status = ADT_SUCCESS;
 188                 retval = ADT_SUCCESS;
 189         }
 190 
 191         if (adt_start_session(&ah, NULL, 0)) {
 192                 syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
 193                 goto errout;

 194         }
 195 
 196         if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
 197                 syslog(LOG_AUTH | LOG_ALERT,
 198                     "adt_alloc_event(ADT_smbd_session): %m");
 199                 goto errout;


 200         }
 201 
 202         (void) memset(&termid, 0, sizeof (au_tid_addr_t));
 203         termid.at_port = 445;
 204 
 205         if (ipaddr->a_family == AF_INET) {
 206                 termid.at_addr[0] = ipaddr->a_ipv4;
 207                 termid.at_type = AU_IPv4;
 208         } else {
 209                 bcopy(&ipaddr->a_ip, termid.at_addr,
 210                     sizeof (in6_addr_t));
 211                 termid.at_type = AU_IPv6;
 212         }
 213         adt_set_termid(ah, &termid);
 214 
 215         if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
 216                 syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
 217                 adt_free_event(event);
 218                 goto errout;


 219         }
 220 
 221         event->adt_smbd_session.domain = domain;
 222         event->adt_smbd_session.username = username;
 223         event->adt_smbd_session.sid = sid;
 224 
 225         if (adt_put_event(event, status, retval))
 226                 syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
 227 
 228         adt_free_event(event);
 229 
 230         if (token) {
 231                 if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
 232                         syslog(LOG_ERR, "smbd_user_auth_logon: %m");
 233                         goto errout;


 234                 }
 235 
 236                 entry->sa_handle = ah;
 237                 entry->sa_uid = uid;
 238                 entry->sa_gid = gid;
 239                 entry->sa_username = strdup(username);
 240                 entry->sa_domain = strdup(domain);
 241 

 242                 smbd_audit_link(entry);
 243                 token->tkn_audit_sid = entry->sa_audit_sid;
 244                 adt_get_auid(ah, &token->tkn_auid);
 245                 adt_get_mask(ah, &token->tkn_amask);
 246                 adt_get_asid(ah, &token->tkn_asid);
 247         }
 248 
 249         return (B_TRUE);
 250 errout:
 251         if (ah != NULL)
 252                 (void) adt_end_session(ah);
 253 
 254         return (B_FALSE);
 255 }
 256 
 257 /*
 258  * Logon due to a subsequent SmbSessionSetupX on an existing session.
 259  * The user was authenticated during the initial session setup.
 260  */
 261 void
 262 smbd_user_nonauth_logon(uint32_t audit_sid)
 263 {
 264         smb_audit_t *entry;
 265 
 266         (void) mutex_lock(&smbd_audit_lock);
 267         entry = smbd_audit_list;
 268 
 269         while (entry) {
 270                 if (entry->sa_audit_sid == audit_sid) {
 271                         ++entry->sa_refcnt;
 272                         break;
 273                 }
 274