xref: /onnv-gate/usr/src/cmd/smbsrv/smbd/smbd_logon.c (revision 5331:3047ad28a67b)
1*5331Samw /*
2*5331Samw  * CDDL HEADER START
3*5331Samw  *
4*5331Samw  * The contents of this file are subject to the terms of the
5*5331Samw  * Common Development and Distribution License (the "License").
6*5331Samw  * You may not use this file except in compliance with the License.
7*5331Samw  *
8*5331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9*5331Samw  * or http://www.opensolaris.org/os/licensing.
10*5331Samw  * See the License for the specific language governing permissions
11*5331Samw  * and limitations under the License.
12*5331Samw  *
13*5331Samw  * When distributing Covered Code, include this CDDL HEADER in each
14*5331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15*5331Samw  * If applicable, add the following below this CDDL HEADER, with the
16*5331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
17*5331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
18*5331Samw  *
19*5331Samw  * CDDL HEADER END
20*5331Samw  */
21*5331Samw /*
22*5331Samw  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
23*5331Samw  * Use is subject to license terms.
24*5331Samw  */
25*5331Samw 
26*5331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
27*5331Samw 
28*5331Samw #include <sys/types.h>
29*5331Samw #include <errno.h>
30*5331Samw #include <synch.h>
31*5331Samw #include <stdio.h>
32*5331Samw #include <stdlib.h>
33*5331Samw #include <unistd.h>
34*5331Samw #include <string.h>
35*5331Samw #include <strings.h>
36*5331Samw #include <syslog.h>
37*5331Samw #include <fcntl.h>
38*5331Samw #include <bsm/adt.h>
39*5331Samw #include <bsm/adt_event.h>
40*5331Samw #include <bsm/audit_uevents.h>
41*5331Samw #include "smbd.h"
42*5331Samw 
43*5331Samw 
44*5331Samw /*
45*5331Samw  * An audit session is established at user logon and terminated at user
46*5331Samw  * logoff.
47*5331Samw  *
48*5331Samw  * SMB audit handles are allocated when users logon (SmbSessionSetupX)
49*5331Samw  * and deallocted when a user logs off (SmbLogoffX).  Each time an SMB
50*5331Samw  * audit handle is allocated it is added to a global list.
51*5331Samw  */
52*5331Samw typedef struct smb_audit {
53*5331Samw 	struct smb_audit *sa_next;
54*5331Samw 	adt_session_data_t *sa_handle;
55*5331Samw 	uid_t sa_uid;
56*5331Samw 	gid_t sa_gid;
57*5331Samw 	uint32_t sa_audit_sid;
58*5331Samw 	uint32_t sa_refcnt;
59*5331Samw 	char *sa_domain;
60*5331Samw 	char *sa_username;
61*5331Samw } smb_audit_t;
62*5331Samw 
63*5331Samw static smb_audit_t *smbd_audit_list;
64*5331Samw static mutex_t smbd_audit_lock;
65*5331Samw 
66*5331Samw /*
67*5331Samw  * Unique identifier for audit sessions in the audit list.
68*5331Samw  * Used to lookup an audit session on logoff.
69*5331Samw  */
70*5331Samw static uint32_t smbd_audit_sid;
71*5331Samw 
72*5331Samw static void smbd_audit_link(smb_audit_t *);
73*5331Samw static smb_audit_t *smbd_audit_unlink(uint32_t);
74*5331Samw 
75*5331Samw 
76*5331Samw /*
77*5331Samw  * Invoked at user logon due to SmbSessionSetupX.  Authenticate the
78*5331Samw  * user, start an audit session and audit the event.
79*5331Samw  */
80*5331Samw smb_token_t *
81*5331Samw smbd_user_auth_logon(netr_client_t *clnt)
82*5331Samw {
83*5331Samw 	smb_token_t *token;
84*5331Samw 	smb_audit_t *entry;
85*5331Samw 	adt_session_data_t *ah;
86*5331Samw 	adt_event_data_t *event;
87*5331Samw 	au_tid_addr_t termid;
88*5331Samw 	uid_t uid;
89*5331Samw 	gid_t gid;
90*5331Samw 	char *sid;
91*5331Samw 	int status;
92*5331Samw 	int retval;
93*5331Samw 
94*5331Samw 	if ((token = smb_logon(clnt)) == NULL) {
95*5331Samw 		uid = ADT_NO_ATTRIB;
96*5331Samw 		gid = ADT_NO_ATTRIB;
97*5331Samw 		sid = strdup(NT_NULL_SIDSTR);
98*5331Samw 		status = ADT_FAILURE;
99*5331Samw 		retval = ADT_FAIL_VALUE_AUTH;
100*5331Samw 	} else {
101*5331Samw 		uid = token->tkn_user->i_id;
102*5331Samw 		gid = token->tkn_primary_grp->i_id;
103*5331Samw 		sid = nt_sid_format(token->tkn_user->i_sidattr.sid);
104*5331Samw 		status = ADT_SUCCESS;
105*5331Samw 		retval = ADT_SUCCESS;
106*5331Samw 	}
107*5331Samw 
108*5331Samw 	if (adt_start_session(&ah, NULL, 0)) {
109*5331Samw 		syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
110*5331Samw 		free(sid);
111*5331Samw 		smb_token_destroy(token);
112*5331Samw 		return (NULL);
113*5331Samw 	}
114*5331Samw 
115*5331Samw 	if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
116*5331Samw 		syslog(LOG_AUTH | LOG_ALERT,
117*5331Samw 		    "adt_alloc_event(ADT_smbd_session): %m");
118*5331Samw 		(void) adt_end_session(ah);
119*5331Samw 		free(sid);
120*5331Samw 		smb_token_destroy(token);
121*5331Samw 		return (NULL);
122*5331Samw 	}
123*5331Samw 
124*5331Samw 	(void) memset(&termid, 0, sizeof (au_tid_addr_t));
125*5331Samw 	termid.at_port = clnt->local_port;
126*5331Samw 	termid.at_type = AU_IPv4;
127*5331Samw 	termid.at_addr[0] = clnt->ipaddr;
128*5331Samw 	adt_set_termid(ah, &termid);
129*5331Samw 
130*5331Samw 	if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
131*5331Samw 		syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
132*5331Samw 		adt_free_event(event);
133*5331Samw 		(void) adt_end_session(ah);
134*5331Samw 		free(sid);
135*5331Samw 		smb_token_destroy(token);
136*5331Samw 		return (NULL);
137*5331Samw 	}
138*5331Samw 
139*5331Samw 	event->adt_smbd_session.domain = clnt->domain;
140*5331Samw 	event->adt_smbd_session.username = clnt->username;
141*5331Samw 	event->adt_smbd_session.sid = sid;
142*5331Samw 
143*5331Samw 	if (adt_put_event(event, status, retval))
144*5331Samw 		syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
145*5331Samw 
146*5331Samw 	adt_free_event(event);
147*5331Samw 	free(sid);
148*5331Samw 
149*5331Samw 	if (token) {
150*5331Samw 		if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
151*5331Samw 			syslog(LOG_ERR, "smbd_user_auth_logon: %m");
152*5331Samw 			(void) adt_end_session(ah);
153*5331Samw 			free(sid);
154*5331Samw 			smb_token_destroy(token);
155*5331Samw 			return (NULL);
156*5331Samw 		}
157*5331Samw 
158*5331Samw 		entry->sa_handle = ah;
159*5331Samw 		entry->sa_uid = uid;
160*5331Samw 		entry->sa_gid = gid;
161*5331Samw 		entry->sa_username = strdup(clnt->username);
162*5331Samw 		entry->sa_domain = strdup(clnt->domain);
163*5331Samw 
164*5331Samw 		(void) smb_autohome_add(entry->sa_username);
165*5331Samw 		smbd_audit_link(entry);
166*5331Samw 		token->tkn_audit_sid = entry->sa_audit_sid;
167*5331Samw 	}
168*5331Samw 
169*5331Samw 	return (token);
170*5331Samw }
171*5331Samw 
172*5331Samw /*
173*5331Samw  * Logon due to a subsequent SmbSessionSetupX on an existing session.
174*5331Samw  * The user was authenticated during the initial session setup.
175*5331Samw  */
176*5331Samw void
177*5331Samw smbd_user_nonauth_logon(uint32_t audit_sid)
178*5331Samw {
179*5331Samw 	smb_audit_t *entry;
180*5331Samw 
181*5331Samw 	(void) mutex_lock(&smbd_audit_lock);
182*5331Samw 	entry = smbd_audit_list;
183*5331Samw 
184*5331Samw 	while (entry) {
185*5331Samw 		if (entry->sa_audit_sid == audit_sid) {
186*5331Samw 			++entry->sa_refcnt;
187*5331Samw 			break;
188*5331Samw 		}
189*5331Samw 
190*5331Samw 		entry = entry->sa_next;
191*5331Samw 	}
192*5331Samw 
193*5331Samw 	(void) mutex_unlock(&smbd_audit_lock);
194*5331Samw }
195*5331Samw 
196*5331Samw /*
197*5331Samw  * Invoked at user logoff due to SmbLogoffX.  If this is the final
198*5331Samw  * logoff for this user on the session, audit the event and terminate
199*5331Samw  * the audit session.
200*5331Samw  */
201*5331Samw void
202*5331Samw smbd_user_auth_logoff(uint32_t audit_sid)
203*5331Samw {
204*5331Samw 	smb_audit_t *entry;
205*5331Samw 	adt_session_data_t *ah;
206*5331Samw 	adt_event_data_t *event;
207*5331Samw 
208*5331Samw 	if ((entry = smbd_audit_unlink(audit_sid)) == NULL)
209*5331Samw 		return;
210*5331Samw 
211*5331Samw 	(void) smb_autohome_remove(entry->sa_username);
212*5331Samw 
213*5331Samw 	ah = entry->sa_handle;
214*5331Samw 
215*5331Samw 	if ((event = adt_alloc_event(ah, ADT_smbd_logoff)) == NULL) {
216*5331Samw 		syslog(LOG_AUTH | LOG_ALERT,
217*5331Samw 		    "adt_alloc_event(ADT_smbd_logoff): %m");
218*5331Samw 	} else {
219*5331Samw 		event->adt_smbd_logoff.domain = entry->sa_domain;
220*5331Samw 		event->adt_smbd_logoff.username = entry->sa_username;
221*5331Samw 
222*5331Samw 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS))
223*5331Samw 			syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
224*5331Samw 
225*5331Samw 		adt_free_event(event);
226*5331Samw 	}
227*5331Samw 
228*5331Samw 	(void) adt_end_session(ah);
229*5331Samw 
230*5331Samw 	free(entry->sa_username);
231*5331Samw 	free(entry->sa_domain);
232*5331Samw 	free(entry);
233*5331Samw }
234*5331Samw 
235*5331Samw /*
236*5331Samw  * Allocate an id and link an audit handle onto the global list.
237*5331Samw  */
238*5331Samw static void
239*5331Samw smbd_audit_link(smb_audit_t *entry)
240*5331Samw {
241*5331Samw 	(void) mutex_lock(&smbd_audit_lock);
242*5331Samw 
243*5331Samw 	do {
244*5331Samw 		++smbd_audit_sid;
245*5331Samw 	} while ((smbd_audit_sid == 0) || (smbd_audit_sid == (uint32_t)-1));
246*5331Samw 
247*5331Samw 	entry->sa_audit_sid = smbd_audit_sid;
248*5331Samw 	entry->sa_refcnt = 1;
249*5331Samw 	entry->sa_next = smbd_audit_list;
250*5331Samw 	smbd_audit_list = entry;
251*5331Samw 
252*5331Samw 	(void) mutex_unlock(&smbd_audit_lock);
253*5331Samw }
254*5331Samw 
255*5331Samw /*
256*5331Samw  * Unlink an audit handle.  If the reference count reaches 0, the entry
257*5331Samw  * is removed from the list and returned.  Otherwise the entry remains
258*5331Samw  * on the list and a null pointer is returned.
259*5331Samw  */
260*5331Samw static smb_audit_t *
261*5331Samw smbd_audit_unlink(uint32_t audit_sid)
262*5331Samw {
263*5331Samw 	smb_audit_t *entry;
264*5331Samw 	smb_audit_t **ppe;
265*5331Samw 
266*5331Samw 	(void) mutex_lock(&smbd_audit_lock);
267*5331Samw 	ppe = &smbd_audit_list;
268*5331Samw 
269*5331Samw 	while (*ppe) {
270*5331Samw 		entry = *ppe;
271*5331Samw 
272*5331Samw 		if (entry->sa_audit_sid == audit_sid) {
273*5331Samw 			if (entry->sa_refcnt == 0)
274*5331Samw 				break;
275*5331Samw 
276*5331Samw 			if ((--entry->sa_refcnt) != 0)
277*5331Samw 				break;
278*5331Samw 
279*5331Samw 			*ppe = entry->sa_next;
280*5331Samw 			(void) mutex_unlock(&smbd_audit_lock);
281*5331Samw 			return (entry);
282*5331Samw 		}
283*5331Samw 
284*5331Samw 		ppe = &(*ppe)->sa_next;
285*5331Samw 	}
286*5331Samw 
287*5331Samw 	(void) mutex_unlock(&smbd_audit_lock);
288*5331Samw 	return (NULL);
289*5331Samw }
290