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