blob: ab6d4c2f7eb74bd0fa880b2aa1fd84435e64288e [file] [log] [blame]
amwda6c28a2007-10-25 16:34:29 -07001/*
2 * CDDL HEADER START
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/*
Keyur Desaic5866002010-04-02 15:07:12 -060022 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
Matt Barden437d9da2017-05-15 08:36:00 -040023 * Copyright 2017 Nexenta Systems, Inc. All rights reserved.
amwda6c28a2007-10-25 16:34:29 -070024 */
25
amwda6c28a2007-10-25 16:34:29 -070026#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>
Keyur Desaic5866002010-04-02 15:07:12 -060039#include <pwd.h>
40#include <nss_dbdefs.h>
41#include <sys/idmap.h>
amwda6c28a2007-10-25 16:34:29 -070042#include "smbd.h"
43
44
45/*
46 * An audit session is established at user logon and terminated at user
47 * logoff.
48 *
49 * SMB audit handles are allocated when users logon (SmbSessionSetupX)
50 * and deallocted when a user logs off (SmbLogoffX). Each time an SMB
51 * audit handle is allocated it is added to a global list.
52 */
53typedef struct smb_audit {
54 struct smb_audit *sa_next;
55 adt_session_data_t *sa_handle;
56 uid_t sa_uid;
57 gid_t sa_gid;
58 uint32_t sa_audit_sid;
59 uint32_t sa_refcnt;
60 char *sa_domain;
61 char *sa_username;
62} smb_audit_t;
63
64static smb_audit_t *smbd_audit_list;
65static 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 */
71static uint32_t smbd_audit_sid;
72
73static void smbd_audit_link(smb_audit_t *);
74static 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 */
81smb_token_t *
afshin salek ardakani - Sun Microsystems - Irvine United States9fb67ea2010-03-20 13:03:54 -070082smbd_user_auth_logon(smb_logon_t *user_info)
amwda6c28a2007-10-25 16:34:29 -070083{
Matt Barden437d9da2017-05-15 08:36:00 -040084 smb_token_t *token = NULL;
amwda6c28a2007-10-25 16:34:29 -070085 smb_audit_t *entry;
Matt Barden437d9da2017-05-15 08:36:00 -040086 adt_session_data_t *ah = NULL;
amwda6c28a2007-10-25 16:34:29 -070087 adt_event_data_t *event;
Gordon Ross12b65582013-06-21 15:59:58 -040088 smb_logon_t tmp_user;
amwda6c28a2007-10-25 16:34:29 -070089 au_tid_addr_t termid;
as2006226537f382008-04-14 10:40:32 -070090 char sidbuf[SMB_SID_STRSZ];
jose borrego7f667e72009-02-01 19:44:54 -070091 char *username;
92 char *domain;
amwda6c28a2007-10-25 16:34:29 -070093 uid_t uid;
94 gid_t gid;
95 char *sid;
96 int status;
97 int retval;
Matt Barden437d9da2017-05-15 08:36:00 -040098 char *p;
99 char *buf = NULL;
amwda6c28a2007-10-25 16:34:29 -0700100
Gordon Ross12b65582013-06-21 15:59:58 -0400101 if (user_info->lg_username == NULL ||
102 user_info->lg_domain == NULL ||
103 user_info->lg_workstation == NULL) {
104 return (NULL);
105 }
106
107 tmp_user = *user_info;
108 if (tmp_user.lg_username[0] == '\0') {
109 tmp_user.lg_flags |= SMB_ATF_ANON;
110 tmp_user.lg_e_username = "anonymous";
111 } else {
112 tmp_user.lg_e_username = tmp_user.lg_username;
113 }
Matt Barden437d9da2017-05-15 08:36:00 -0400114
115 /* Handle user@domain format. */
116 if (tmp_user.lg_domain[0] == '\0' &&
117 (p = strchr(tmp_user.lg_e_username, '@')) != NULL) {
118 buf = strdup(tmp_user.lg_e_username);
119 if (buf == NULL)
120 goto errout;
121 p = buf + (p - tmp_user.lg_e_username);
122 *p = '\0';
123 tmp_user.lg_e_domain = p + 1;
124 tmp_user.lg_e_username = buf;
125 } else {
126 tmp_user.lg_e_domain = tmp_user.lg_domain;
127 }
Gordon Ross12b65582013-06-21 15:59:58 -0400128
129 if ((token = smb_logon(&tmp_user)) == NULL) {
amwda6c28a2007-10-25 16:34:29 -0700130 uid = ADT_NO_ATTRIB;
131 gid = ADT_NO_ATTRIB;
as2006226537f382008-04-14 10:40:32 -0700132 sid = NT_NULL_SIDSTR;
Gordon Ross12b65582013-06-21 15:59:58 -0400133 username = tmp_user.lg_e_username;
134 domain = tmp_user.lg_e_domain;
amwda6c28a2007-10-25 16:34:29 -0700135 status = ADT_FAILURE;
136 retval = ADT_FAIL_VALUE_AUTH;
137 } else {
jose borrego7f667e72009-02-01 19:44:54 -0700138 uid = token->tkn_user.i_id;
139 gid = token->tkn_primary_grp.i_id;
140 smb_sid_tostr(token->tkn_user.i_sid, sidbuf);
as2006226537f382008-04-14 10:40:32 -0700141 sid = sidbuf;
jose borrego7f667e72009-02-01 19:44:54 -0700142 username = token->tkn_account_name;
143 domain = token->tkn_domain_name;
amwda6c28a2007-10-25 16:34:29 -0700144 status = ADT_SUCCESS;
145 retval = ADT_SUCCESS;
146 }
147
148 if (adt_start_session(&ah, NULL, 0)) {
149 syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
Matt Barden437d9da2017-05-15 08:36:00 -0400150 goto errout;
amwda6c28a2007-10-25 16:34:29 -0700151 }
152
153 if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
154 syslog(LOG_AUTH | LOG_ALERT,
155 "adt_alloc_event(ADT_smbd_session): %m");
Matt Barden437d9da2017-05-15 08:36:00 -0400156 goto errout;
amwda6c28a2007-10-25 16:34:29 -0700157 }
158
159 (void) memset(&termid, 0, sizeof (au_tid_addr_t));
afshin salek ardakani - Sun Microsystems - Irvine United States9fb67ea2010-03-20 13:03:54 -0700160 termid.at_port = user_info->lg_local_port;
jose borrego7f667e72009-02-01 19:44:54 -0700161
afshin salek ardakani - Sun Microsystems - Irvine United States9fb67ea2010-03-20 13:03:54 -0700162 if (user_info->lg_clnt_ipaddr.a_family == AF_INET) {
163 termid.at_addr[0] = user_info->lg_clnt_ipaddr.a_ipv4;
jose borrego7f667e72009-02-01 19:44:54 -0700164 termid.at_type = AU_IPv4;
165 } else {
afshin salek ardakani - Sun Microsystems - Irvine United States9fb67ea2010-03-20 13:03:54 -0700166 bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
Gordon Rossb819cea2013-06-17 10:34:00 -0400167 sizeof (in6_addr_t));
jose borrego7f667e72009-02-01 19:44:54 -0700168 termid.at_type = AU_IPv6;
169 }
amwda6c28a2007-10-25 16:34:29 -0700170 adt_set_termid(ah, &termid);
171
172 if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
173 syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
174 adt_free_event(event);
Matt Barden437d9da2017-05-15 08:36:00 -0400175 goto errout;
amwda6c28a2007-10-25 16:34:29 -0700176 }
177
jose borrego7f667e72009-02-01 19:44:54 -0700178 event->adt_smbd_session.domain = domain;
179 event->adt_smbd_session.username = username;
amwda6c28a2007-10-25 16:34:29 -0700180 event->adt_smbd_session.sid = sid;
181
182 if (adt_put_event(event, status, retval))
183 syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
184
185 adt_free_event(event);
amwda6c28a2007-10-25 16:34:29 -0700186
187 if (token) {
188 if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
189 syslog(LOG_ERR, "smbd_user_auth_logon: %m");
Matt Barden437d9da2017-05-15 08:36:00 -0400190 goto errout;
amwda6c28a2007-10-25 16:34:29 -0700191 }
192
193 entry->sa_handle = ah;
194 entry->sa_uid = uid;
195 entry->sa_gid = gid;
jose borrego7f667e72009-02-01 19:44:54 -0700196 entry->sa_username = strdup(username);
197 entry->sa_domain = strdup(domain);
amwda6c28a2007-10-25 16:34:29 -0700198
Bill Krierfe1c6422009-12-16 16:39:00 -0800199 smb_autohome_add(token);
amwda6c28a2007-10-25 16:34:29 -0700200 smbd_audit_link(entry);
201 token->tkn_audit_sid = entry->sa_audit_sid;
202 }
203
Matt Barden437d9da2017-05-15 08:36:00 -0400204 free(buf);
205
amwda6c28a2007-10-25 16:34:29 -0700206 return (token);
Matt Barden437d9da2017-05-15 08:36:00 -0400207
208errout:
209 free(buf);
210 (void) adt_end_session(ah);
211 smb_token_destroy(token);
212 return (NULL);
amwda6c28a2007-10-25 16:34:29 -0700213}
214
215/*
216 * Logon due to a subsequent SmbSessionSetupX on an existing session.
217 * The user was authenticated during the initial session setup.
218 */
219void
220smbd_user_nonauth_logon(uint32_t audit_sid)
221{
222 smb_audit_t *entry;
223
224 (void) mutex_lock(&smbd_audit_lock);
225 entry = smbd_audit_list;
226
227 while (entry) {
228 if (entry->sa_audit_sid == audit_sid) {
229 ++entry->sa_refcnt;
230 break;
231 }
232
233 entry = entry->sa_next;
234 }
235
236 (void) mutex_unlock(&smbd_audit_lock);
237}
238
239/*
240 * Invoked at user logoff due to SmbLogoffX. If this is the final
241 * logoff for this user on the session, audit the event and terminate
242 * the audit session.
243 */
244void
245smbd_user_auth_logoff(uint32_t audit_sid)
246{
247 smb_audit_t *entry;
248 adt_session_data_t *ah;
249 adt_event_data_t *event;
Keyur Desaic5866002010-04-02 15:07:12 -0600250 struct passwd pw;
251 char buf[NSS_LINELEN_PASSWD];
amwda6c28a2007-10-25 16:34:29 -0700252
253 if ((entry = smbd_audit_unlink(audit_sid)) == NULL)
254 return;
255
Keyur Desaic5866002010-04-02 15:07:12 -0600256 if (IDMAP_ID_IS_EPHEMERAL(entry->sa_uid)) {
257 smb_autohome_remove(entry->sa_username);
258 } else {
259 if (getpwuid_r(entry->sa_uid, &pw, buf, sizeof (buf)) == NULL)
260 return;
261
262 smb_autohome_remove(pw.pw_name);
263 }
amwda6c28a2007-10-25 16:34:29 -0700264
265 ah = entry->sa_handle;
266
267 if ((event = adt_alloc_event(ah, ADT_smbd_logoff)) == NULL) {
268 syslog(LOG_AUTH | LOG_ALERT,
269 "adt_alloc_event(ADT_smbd_logoff): %m");
270 } else {
271 event->adt_smbd_logoff.domain = entry->sa_domain;
272 event->adt_smbd_logoff.username = entry->sa_username;
273
274 if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS))
275 syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
276
277 adt_free_event(event);
278 }
279
280 (void) adt_end_session(ah);
281
282 free(entry->sa_username);
283 free(entry->sa_domain);
284 free(entry);
285}
286
287/*
288 * Allocate an id and link an audit handle onto the global list.
289 */
290static void
291smbd_audit_link(smb_audit_t *entry)
292{
293 (void) mutex_lock(&smbd_audit_lock);
294
295 do {
296 ++smbd_audit_sid;
297 } while ((smbd_audit_sid == 0) || (smbd_audit_sid == (uint32_t)-1));
298
299 entry->sa_audit_sid = smbd_audit_sid;
300 entry->sa_refcnt = 1;
301 entry->sa_next = smbd_audit_list;
302 smbd_audit_list = entry;
303
304 (void) mutex_unlock(&smbd_audit_lock);
305}
306
307/*
308 * Unlink an audit handle. If the reference count reaches 0, the entry
309 * is removed from the list and returned. Otherwise the entry remains
310 * on the list and a null pointer is returned.
311 */
312static smb_audit_t *
313smbd_audit_unlink(uint32_t audit_sid)
314{
315 smb_audit_t *entry;
316 smb_audit_t **ppe;
317
318 (void) mutex_lock(&smbd_audit_lock);
319 ppe = &smbd_audit_list;
320
321 while (*ppe) {
322 entry = *ppe;
323
324 if (entry->sa_audit_sid == audit_sid) {
325 if (entry->sa_refcnt == 0)
326 break;
327
328 if ((--entry->sa_refcnt) != 0)
329 break;
330
331 *ppe = entry->sa_next;
332 (void) mutex_unlock(&smbd_audit_lock);
333 return (entry);
334 }
335
336 ppe = &(*ppe)->sa_next;
337 }
338
339 (void) mutex_unlock(&smbd_audit_lock);
340 return (NULL);
341}