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