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.
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.
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]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
26 #include <sys/types.h>
37 #include <bsm/adt_event.h>
38 #include <bsm/audit_uevents.h>
40 #include <nss_dbdefs.h>
41 #include <sys/idmap.h>
46 * An audit session is established at user logon and terminated at user
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.
53 typedef struct smb_audit
{
54 struct smb_audit
*sa_next
;
55 adt_session_data_t
*sa_handle
;
58 uint32_t sa_audit_sid
;
64 static smb_audit_t
*smbd_audit_list
;
65 static mutex_t smbd_audit_lock
;
68 * Unique identifier for audit sessions in the audit list.
69 * Used to lookup an audit session on logoff.
71 static uint32_t smbd_audit_sid
;
73 static void smbd_audit_link(smb_audit_t
*);
74 static smb_audit_t
*smbd_audit_unlink(uint32_t);
78 * Invoked at user logon due to SmbSessionSetupX. Authenticate the
79 * user, start an audit session and audit the event.
82 smbd_user_auth_logon(smb_logon_t
*user_info
)
86 adt_session_data_t
*ah
;
87 adt_event_data_t
*event
;
90 char sidbuf
[SMB_SID_STRSZ
];
99 if (user_info
->lg_username
== NULL
||
100 user_info
->lg_domain
== NULL
||
101 user_info
->lg_workstation
== NULL
) {
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";
110 tmp_user
.lg_e_username
= tmp_user
.lg_username
;
112 tmp_user
.lg_e_domain
= tmp_user
.lg_domain
;
114 if ((token
= smb_logon(&tmp_user
)) == NULL
) {
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
;
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
);
127 username
= token
->tkn_account_name
;
128 domain
= token
->tkn_domain_name
;
129 status
= ADT_SUCCESS
;
130 retval
= ADT_SUCCESS
;
133 if (adt_start_session(&ah
, NULL
, 0)) {
134 syslog(LOG_AUTH
| LOG_ALERT
, "adt_start_session: %m");
135 smb_token_destroy(token
);
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
);
147 (void) memset(&termid
, 0, sizeof (au_tid_addr_t
));
148 termid
.at_port
= user_info
->lg_local_port
;
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
;
154 bcopy(&user_info
->lg_clnt_ipaddr
.a_ip
, termid
.at_addr
,
155 sizeof (in6_addr_t
));
156 termid
.at_type
= AU_IPv6
;
158 adt_set_termid(ah
, &termid
);
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
);
168 event
->adt_smbd_session
.domain
= domain
;
169 event
->adt_smbd_session
.username
= username
;
170 event
->adt_smbd_session
.sid
= sid
;
172 if (adt_put_event(event
, status
, retval
))
173 syslog(LOG_AUTH
| LOG_ALERT
, "adt_put_event: %m");
175 adt_free_event(event
);
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
);
185 entry
->sa_handle
= ah
;
188 entry
->sa_username
= strdup(username
);
189 entry
->sa_domain
= strdup(domain
);
191 smb_autohome_add(token
);
192 smbd_audit_link(entry
);
193 token
->tkn_audit_sid
= entry
->sa_audit_sid
;
200 * Logon due to a subsequent SmbSessionSetupX on an existing session.
201 * The user was authenticated during the initial session setup.
204 smbd_user_nonauth_logon(uint32_t audit_sid
)
208 (void) mutex_lock(&smbd_audit_lock
);
209 entry
= smbd_audit_list
;
212 if (entry
->sa_audit_sid
== audit_sid
) {
217 entry
= entry
->sa_next
;
220 (void) mutex_unlock(&smbd_audit_lock
);
224 * Invoked at user logoff due to SmbLogoffX. If this is the final
225 * logoff for this user on the session, audit the event and terminate
229 smbd_user_auth_logoff(uint32_t audit_sid
)
232 adt_session_data_t
*ah
;
233 adt_event_data_t
*event
;
235 char buf
[NSS_LINELEN_PASSWD
];
237 if ((entry
= smbd_audit_unlink(audit_sid
)) == NULL
)
240 if (IDMAP_ID_IS_EPHEMERAL(entry
->sa_uid
)) {
241 smb_autohome_remove(entry
->sa_username
);
243 struct passwd
*result
;
244 getpwuid_r(entry
->sa_uid
, &pw
, buf
, sizeof (buf
), &result
);
248 smb_autohome_remove(pw
.pw_name
);
251 ah
= entry
->sa_handle
;
253 if ((event
= adt_alloc_event(ah
, ADT_smbd_logoff
)) == NULL
) {
254 syslog(LOG_AUTH
| LOG_ALERT
,
255 "adt_alloc_event(ADT_smbd_logoff): %m");
257 event
->adt_smbd_logoff
.domain
= entry
->sa_domain
;
258 event
->adt_smbd_logoff
.username
= entry
->sa_username
;
260 if (adt_put_event(event
, ADT_SUCCESS
, ADT_SUCCESS
))
261 syslog(LOG_AUTH
| LOG_ALERT
, "adt_put_event: %m");
263 adt_free_event(event
);
266 (void) adt_end_session(ah
);
268 free(entry
->sa_username
);
269 free(entry
->sa_domain
);
274 * Allocate an id and link an audit handle onto the global list.
277 smbd_audit_link(smb_audit_t
*entry
)
279 (void) mutex_lock(&smbd_audit_lock
);
283 } while ((smbd_audit_sid
== 0) || (smbd_audit_sid
== (uint32_t)-1));
285 entry
->sa_audit_sid
= smbd_audit_sid
;
286 entry
->sa_refcnt
= 1;
287 entry
->sa_next
= smbd_audit_list
;
288 smbd_audit_list
= entry
;
290 (void) mutex_unlock(&smbd_audit_lock
);
294 * Unlink an audit handle. If the reference count reaches 0, the entry
295 * is removed from the list and returned. Otherwise the entry remains
296 * on the list and a null pointer is returned.
299 smbd_audit_unlink(uint32_t audit_sid
)
304 (void) mutex_lock(&smbd_audit_lock
);
305 ppe
= &smbd_audit_list
;
310 if (entry
->sa_audit_sid
== audit_sid
) {
311 if (entry
->sa_refcnt
== 0)
314 if ((--entry
->sa_refcnt
) != 0)
317 *ppe
= entry
->sa_next
;
318 (void) mutex_unlock(&smbd_audit_lock
);
322 ppe
= &(*ppe
)->sa_next
;
325 (void) mutex_unlock(&smbd_audit_lock
);