xref: /onnv-gate/usr/src/cmd/smbsrv/smbd/smbd_logon.c (revision 6432:98715880dd9e)
15331Samw /*
25331Samw  * CDDL HEADER START
35331Samw  *
45331Samw  * The contents of this file are subject to the terms of the
55331Samw  * Common Development and Distribution License (the "License").
65331Samw  * You may not use this file except in compliance with the License.
75331Samw  *
85331Samw  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw  * or http://www.opensolaris.org/os/licensing.
105331Samw  * See the License for the specific language governing permissions
115331Samw  * and limitations under the License.
125331Samw  *
135331Samw  * When distributing Covered Code, include this CDDL HEADER in each
145331Samw  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw  * If applicable, add the following below this CDDL HEADER, with the
165331Samw  * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw  * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw  *
195331Samw  * CDDL HEADER END
205331Samw  */
215331Samw /*
22*6432Sas200622  * Copyright 2008 Sun Microsystems, Inc.  All rights reserved.
235331Samw  * Use is subject to license terms.
245331Samw  */
255331Samw 
265331Samw #pragma ident	"%Z%%M%	%I%	%E% SMI"
275331Samw 
285331Samw #include <sys/types.h>
295331Samw #include <errno.h>
305331Samw #include <synch.h>
315331Samw #include <stdio.h>
325331Samw #include <stdlib.h>
335331Samw #include <unistd.h>
345331Samw #include <string.h>
355331Samw #include <strings.h>
365331Samw #include <syslog.h>
375331Samw #include <fcntl.h>
385331Samw #include <bsm/adt.h>
395331Samw #include <bsm/adt_event.h>
405331Samw #include <bsm/audit_uevents.h>
415331Samw #include "smbd.h"
425331Samw 
435331Samw 
445331Samw /*
455331Samw  * An audit session is established at user logon and terminated at user
465331Samw  * logoff.
475331Samw  *
485331Samw  * SMB audit handles are allocated when users logon (SmbSessionSetupX)
495331Samw  * and deallocted when a user logs off (SmbLogoffX).  Each time an SMB
505331Samw  * audit handle is allocated it is added to a global list.
515331Samw  */
525331Samw typedef struct smb_audit {
535331Samw 	struct smb_audit *sa_next;
545331Samw 	adt_session_data_t *sa_handle;
555331Samw 	uid_t sa_uid;
565331Samw 	gid_t sa_gid;
575331Samw 	uint32_t sa_audit_sid;
585331Samw 	uint32_t sa_refcnt;
595331Samw 	char *sa_domain;
605331Samw 	char *sa_username;
615331Samw } smb_audit_t;
625331Samw 
635331Samw static smb_audit_t *smbd_audit_list;
645331Samw static mutex_t smbd_audit_lock;
655331Samw 
665331Samw /*
675331Samw  * Unique identifier for audit sessions in the audit list.
685331Samw  * Used to lookup an audit session on logoff.
695331Samw  */
705331Samw static uint32_t smbd_audit_sid;
715331Samw 
725331Samw static void smbd_audit_link(smb_audit_t *);
735331Samw static smb_audit_t *smbd_audit_unlink(uint32_t);
745331Samw 
755331Samw 
765331Samw /*
775331Samw  * Invoked at user logon due to SmbSessionSetupX.  Authenticate the
785331Samw  * user, start an audit session and audit the event.
795331Samw  */
805331Samw smb_token_t *
815331Samw smbd_user_auth_logon(netr_client_t *clnt)
825331Samw {
835331Samw 	smb_token_t *token;
845331Samw 	smb_audit_t *entry;
855331Samw 	adt_session_data_t *ah;
865331Samw 	adt_event_data_t *event;
875331Samw 	au_tid_addr_t termid;
88*6432Sas200622 	char sidbuf[SMB_SID_STRSZ];
895331Samw 	uid_t uid;
905331Samw 	gid_t gid;
915331Samw 	char *sid;
925331Samw 	int status;
935331Samw 	int retval;
945331Samw 
955331Samw 	if ((token = smb_logon(clnt)) == NULL) {
965331Samw 		uid = ADT_NO_ATTRIB;
975331Samw 		gid = ADT_NO_ATTRIB;
98*6432Sas200622 		sid = NT_NULL_SIDSTR;
995331Samw 		status = ADT_FAILURE;
1005331Samw 		retval = ADT_FAIL_VALUE_AUTH;
1015331Samw 	} else {
1025331Samw 		uid = token->tkn_user->i_id;
1035331Samw 		gid = token->tkn_primary_grp->i_id;
104*6432Sas200622 		smb_sid_tostr(token->tkn_user->i_sidattr.sid, sidbuf);
105*6432Sas200622 		sid = sidbuf;
1065331Samw 		status = ADT_SUCCESS;
1075331Samw 		retval = ADT_SUCCESS;
1085331Samw 	}
1095331Samw 
1105331Samw 	if (adt_start_session(&ah, NULL, 0)) {
1115331Samw 		syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
1125331Samw 		smb_token_destroy(token);
1135331Samw 		return (NULL);
1145331Samw 	}
1155331Samw 
1165331Samw 	if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
1175331Samw 		syslog(LOG_AUTH | LOG_ALERT,
1185331Samw 		    "adt_alloc_event(ADT_smbd_session): %m");
1195331Samw 		(void) adt_end_session(ah);
1205331Samw 		smb_token_destroy(token);
1215331Samw 		return (NULL);
1225331Samw 	}
1235331Samw 
1245331Samw 	(void) memset(&termid, 0, sizeof (au_tid_addr_t));
1255331Samw 	termid.at_port = clnt->local_port;
1265331Samw 	termid.at_type = AU_IPv4;
1275331Samw 	termid.at_addr[0] = clnt->ipaddr;
1285331Samw 	adt_set_termid(ah, &termid);
1295331Samw 
1305331Samw 	if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
1315331Samw 		syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
1325331Samw 		adt_free_event(event);
1335331Samw 		(void) adt_end_session(ah);
1345331Samw 		smb_token_destroy(token);
1355331Samw 		return (NULL);
1365331Samw 	}
1375331Samw 
1385331Samw 	event->adt_smbd_session.domain = clnt->domain;
1395331Samw 	event->adt_smbd_session.username = clnt->username;
1405331Samw 	event->adt_smbd_session.sid = sid;
1415331Samw 
1425331Samw 	if (adt_put_event(event, status, retval))
1435331Samw 		syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
1445331Samw 
1455331Samw 	adt_free_event(event);
1465331Samw 
1475331Samw 	if (token) {
1485331Samw 		if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
1495331Samw 			syslog(LOG_ERR, "smbd_user_auth_logon: %m");
1505331Samw 			(void) adt_end_session(ah);
1515331Samw 			smb_token_destroy(token);
1525331Samw 			return (NULL);
1535331Samw 		}
1545331Samw 
1555331Samw 		entry->sa_handle = ah;
1565331Samw 		entry->sa_uid = uid;
1575331Samw 		entry->sa_gid = gid;
1585331Samw 		entry->sa_username = strdup(clnt->username);
1595331Samw 		entry->sa_domain = strdup(clnt->domain);
1605331Samw 
1615331Samw 		(void) smb_autohome_add(entry->sa_username);
1625331Samw 		smbd_audit_link(entry);
1635331Samw 		token->tkn_audit_sid = entry->sa_audit_sid;
1645331Samw 	}
1655331Samw 
1665331Samw 	return (token);
1675331Samw }
1685331Samw 
1695331Samw /*
1705331Samw  * Logon due to a subsequent SmbSessionSetupX on an existing session.
1715331Samw  * The user was authenticated during the initial session setup.
1725331Samw  */
1735331Samw void
1745331Samw smbd_user_nonauth_logon(uint32_t audit_sid)
1755331Samw {
1765331Samw 	smb_audit_t *entry;
1775331Samw 
1785331Samw 	(void) mutex_lock(&smbd_audit_lock);
1795331Samw 	entry = smbd_audit_list;
1805331Samw 
1815331Samw 	while (entry) {
1825331Samw 		if (entry->sa_audit_sid == audit_sid) {
1835331Samw 			++entry->sa_refcnt;
1845331Samw 			break;
1855331Samw 		}
1865331Samw 
1875331Samw 		entry = entry->sa_next;
1885331Samw 	}
1895331Samw 
1905331Samw 	(void) mutex_unlock(&smbd_audit_lock);
1915331Samw }
1925331Samw 
1935331Samw /*
1945331Samw  * Invoked at user logoff due to SmbLogoffX.  If this is the final
1955331Samw  * logoff for this user on the session, audit the event and terminate
1965331Samw  * the audit session.
1975331Samw  */
1985331Samw void
1995331Samw smbd_user_auth_logoff(uint32_t audit_sid)
2005331Samw {
2015331Samw 	smb_audit_t *entry;
2025331Samw 	adt_session_data_t *ah;
2035331Samw 	adt_event_data_t *event;
2045331Samw 
2055331Samw 	if ((entry = smbd_audit_unlink(audit_sid)) == NULL)
2065331Samw 		return;
2075331Samw 
2085331Samw 	(void) smb_autohome_remove(entry->sa_username);
2095331Samw 
2105331Samw 	ah = entry->sa_handle;
2115331Samw 
2125331Samw 	if ((event = adt_alloc_event(ah, ADT_smbd_logoff)) == NULL) {
2135331Samw 		syslog(LOG_AUTH | LOG_ALERT,
2145331Samw 		    "adt_alloc_event(ADT_smbd_logoff): %m");
2155331Samw 	} else {
2165331Samw 		event->adt_smbd_logoff.domain = entry->sa_domain;
2175331Samw 		event->adt_smbd_logoff.username = entry->sa_username;
2185331Samw 
2195331Samw 		if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS))
2205331Samw 			syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
2215331Samw 
2225331Samw 		adt_free_event(event);
2235331Samw 	}
2245331Samw 
2255331Samw 	(void) adt_end_session(ah);
2265331Samw 
2275331Samw 	free(entry->sa_username);
2285331Samw 	free(entry->sa_domain);
2295331Samw 	free(entry);
2305331Samw }
2315331Samw 
2325331Samw /*
2335331Samw  * Allocate an id and link an audit handle onto the global list.
2345331Samw  */
2355331Samw static void
2365331Samw smbd_audit_link(smb_audit_t *entry)
2375331Samw {
2385331Samw 	(void) mutex_lock(&smbd_audit_lock);
2395331Samw 
2405331Samw 	do {
2415331Samw 		++smbd_audit_sid;
2425331Samw 	} while ((smbd_audit_sid == 0) || (smbd_audit_sid == (uint32_t)-1));
2435331Samw 
2445331Samw 	entry->sa_audit_sid = smbd_audit_sid;
2455331Samw 	entry->sa_refcnt = 1;
2465331Samw 	entry->sa_next = smbd_audit_list;
2475331Samw 	smbd_audit_list = entry;
2485331Samw 
2495331Samw 	(void) mutex_unlock(&smbd_audit_lock);
2505331Samw }
2515331Samw 
2525331Samw /*
2535331Samw  * Unlink an audit handle.  If the reference count reaches 0, the entry
2545331Samw  * is removed from the list and returned.  Otherwise the entry remains
2555331Samw  * on the list and a null pointer is returned.
2565331Samw  */
2575331Samw static smb_audit_t *
2585331Samw smbd_audit_unlink(uint32_t audit_sid)
2595331Samw {
2605331Samw 	smb_audit_t *entry;
2615331Samw 	smb_audit_t **ppe;
2625331Samw 
2635331Samw 	(void) mutex_lock(&smbd_audit_lock);
2645331Samw 	ppe = &smbd_audit_list;
2655331Samw 
2665331Samw 	while (*ppe) {
2675331Samw 		entry = *ppe;
2685331Samw 
2695331Samw 		if (entry->sa_audit_sid == audit_sid) {
2705331Samw 			if (entry->sa_refcnt == 0)
2715331Samw 				break;
2725331Samw 
2735331Samw 			if ((--entry->sa_refcnt) != 0)
2745331Samw 				break;
2755331Samw 
2765331Samw 			*ppe = entry->sa_next;
2775331Samw 			(void) mutex_unlock(&smbd_audit_lock);
2785331Samw 			return (entry);
2795331Samw 		}
2805331Samw 
2815331Samw 		ppe = &(*ppe)->sa_next;
2825331Samw 	}
2835331Samw 
2845331Samw 	(void) mutex_unlock(&smbd_audit_lock);
2855331Samw 	return (NULL);
2865331Samw }
287