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*12065SKeyur.Desai@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw */
245331Samw
255331Samw #include <sys/types.h>
265331Samw #include <errno.h>
275331Samw #include <synch.h>
285331Samw #include <stdio.h>
295331Samw #include <stdlib.h>
305331Samw #include <unistd.h>
315331Samw #include <string.h>
325331Samw #include <strings.h>
335331Samw #include <syslog.h>
345331Samw #include <fcntl.h>
355331Samw #include <bsm/adt.h>
365331Samw #include <bsm/adt_event.h>
375331Samw #include <bsm/audit_uevents.h>
38*12065SKeyur.Desai@Sun.COM #include <pwd.h>
39*12065SKeyur.Desai@Sun.COM #include <nss_dbdefs.h>
40*12065SKeyur.Desai@Sun.COM #include <sys/idmap.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 *
smbd_user_auth_logon(smb_logon_t * user_info)8111963SAfshin.Ardakani@Sun.COM smbd_user_auth_logon(smb_logon_t *user_info)
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;
886432Sas200622 char sidbuf[SMB_SID_STRSZ];
898670SJose.Borrego@Sun.COM char *username;
908670SJose.Borrego@Sun.COM char *domain;
915331Samw uid_t uid;
925331Samw gid_t gid;
935331Samw char *sid;
945331Samw int status;
955331Samw int retval;
965331Samw
9711963SAfshin.Ardakani@Sun.COM if ((token = smb_logon(user_info)) == NULL) {
985331Samw uid = ADT_NO_ATTRIB;
995331Samw gid = ADT_NO_ATTRIB;
1006432Sas200622 sid = NT_NULL_SIDSTR;
10111963SAfshin.Ardakani@Sun.COM username = user_info->lg_e_username;
10211963SAfshin.Ardakani@Sun.COM domain = user_info->lg_e_domain;
1035331Samw status = ADT_FAILURE;
1045331Samw retval = ADT_FAIL_VALUE_AUTH;
1055331Samw } else {
1068670SJose.Borrego@Sun.COM uid = token->tkn_user.i_id;
1078670SJose.Borrego@Sun.COM gid = token->tkn_primary_grp.i_id;
1088670SJose.Borrego@Sun.COM smb_sid_tostr(token->tkn_user.i_sid, sidbuf);
1096432Sas200622 sid = sidbuf;
1108670SJose.Borrego@Sun.COM username = token->tkn_account_name;
1118670SJose.Borrego@Sun.COM domain = token->tkn_domain_name;
1125331Samw status = ADT_SUCCESS;
1135331Samw retval = ADT_SUCCESS;
1145331Samw }
1155331Samw
1165331Samw if (adt_start_session(&ah, NULL, 0)) {
1175331Samw syslog(LOG_AUTH | LOG_ALERT, "adt_start_session: %m");
1185331Samw smb_token_destroy(token);
1195331Samw return (NULL);
1205331Samw }
1215331Samw
1225331Samw if ((event = adt_alloc_event(ah, ADT_smbd_session)) == NULL) {
1235331Samw syslog(LOG_AUTH | LOG_ALERT,
1245331Samw "adt_alloc_event(ADT_smbd_session): %m");
1255331Samw (void) adt_end_session(ah);
1265331Samw smb_token_destroy(token);
1275331Samw return (NULL);
1285331Samw }
1295331Samw
1305331Samw (void) memset(&termid, 0, sizeof (au_tid_addr_t));
13111963SAfshin.Ardakani@Sun.COM termid.at_port = user_info->lg_local_port;
1328670SJose.Borrego@Sun.COM
13311963SAfshin.Ardakani@Sun.COM if (user_info->lg_clnt_ipaddr.a_family == AF_INET) {
13411963SAfshin.Ardakani@Sun.COM termid.at_addr[0] = user_info->lg_clnt_ipaddr.a_ipv4;
1358670SJose.Borrego@Sun.COM termid.at_type = AU_IPv4;
1368670SJose.Borrego@Sun.COM } else {
13711963SAfshin.Ardakani@Sun.COM bcopy(&user_info->lg_clnt_ipaddr.a_ip, termid.at_addr,
13811963SAfshin.Ardakani@Sun.COM IPV6_ADDR_LEN);
1398670SJose.Borrego@Sun.COM termid.at_type = AU_IPv6;
1408670SJose.Borrego@Sun.COM }
1415331Samw adt_set_termid(ah, &termid);
1425331Samw
1435331Samw if (adt_set_user(ah, uid, gid, uid, gid, NULL, ADT_NEW)) {
1445331Samw syslog(LOG_AUTH | LOG_ALERT, "adt_set_user: %m");
1455331Samw adt_free_event(event);
1465331Samw (void) adt_end_session(ah);
1475331Samw smb_token_destroy(token);
1485331Samw return (NULL);
1495331Samw }
1505331Samw
1518670SJose.Borrego@Sun.COM event->adt_smbd_session.domain = domain;
1528670SJose.Borrego@Sun.COM event->adt_smbd_session.username = username;
1535331Samw event->adt_smbd_session.sid = sid;
1545331Samw
1555331Samw if (adt_put_event(event, status, retval))
1565331Samw syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
1575331Samw
1585331Samw adt_free_event(event);
1595331Samw
1605331Samw if (token) {
1615331Samw if ((entry = malloc(sizeof (smb_audit_t))) == NULL) {
1625331Samw syslog(LOG_ERR, "smbd_user_auth_logon: %m");
1635331Samw (void) adt_end_session(ah);
1645331Samw smb_token_destroy(token);
1655331Samw return (NULL);
1665331Samw }
1675331Samw
1685331Samw entry->sa_handle = ah;
1695331Samw entry->sa_uid = uid;
1705331Samw entry->sa_gid = gid;
1718670SJose.Borrego@Sun.COM entry->sa_username = strdup(username);
1728670SJose.Borrego@Sun.COM entry->sa_domain = strdup(domain);
1735331Samw
17411337SWilliam.Krier@Sun.COM smb_autohome_add(token);
1755331Samw smbd_audit_link(entry);
1765331Samw token->tkn_audit_sid = entry->sa_audit_sid;
1775331Samw }
1785331Samw
1795331Samw return (token);
1805331Samw }
1815331Samw
1825331Samw /*
1835331Samw * Logon due to a subsequent SmbSessionSetupX on an existing session.
1845331Samw * The user was authenticated during the initial session setup.
1855331Samw */
1865331Samw void
smbd_user_nonauth_logon(uint32_t audit_sid)1875331Samw smbd_user_nonauth_logon(uint32_t audit_sid)
1885331Samw {
1895331Samw smb_audit_t *entry;
1905331Samw
1915331Samw (void) mutex_lock(&smbd_audit_lock);
1925331Samw entry = smbd_audit_list;
1935331Samw
1945331Samw while (entry) {
1955331Samw if (entry->sa_audit_sid == audit_sid) {
1965331Samw ++entry->sa_refcnt;
1975331Samw break;
1985331Samw }
1995331Samw
2005331Samw entry = entry->sa_next;
2015331Samw }
2025331Samw
2035331Samw (void) mutex_unlock(&smbd_audit_lock);
2045331Samw }
2055331Samw
2065331Samw /*
2075331Samw * Invoked at user logoff due to SmbLogoffX. If this is the final
2085331Samw * logoff for this user on the session, audit the event and terminate
2095331Samw * the audit session.
2105331Samw */
2115331Samw void
smbd_user_auth_logoff(uint32_t audit_sid)2125331Samw smbd_user_auth_logoff(uint32_t audit_sid)
2135331Samw {
2145331Samw smb_audit_t *entry;
2155331Samw adt_session_data_t *ah;
2165331Samw adt_event_data_t *event;
217*12065SKeyur.Desai@Sun.COM struct passwd pw;
218*12065SKeyur.Desai@Sun.COM char buf[NSS_LINELEN_PASSWD];
2195331Samw
2205331Samw if ((entry = smbd_audit_unlink(audit_sid)) == NULL)
2215331Samw return;
2225331Samw
223*12065SKeyur.Desai@Sun.COM if (IDMAP_ID_IS_EPHEMERAL(entry->sa_uid)) {
224*12065SKeyur.Desai@Sun.COM smb_autohome_remove(entry->sa_username);
225*12065SKeyur.Desai@Sun.COM } else {
226*12065SKeyur.Desai@Sun.COM if (getpwuid_r(entry->sa_uid, &pw, buf, sizeof (buf)) == NULL)
227*12065SKeyur.Desai@Sun.COM return;
228*12065SKeyur.Desai@Sun.COM
229*12065SKeyur.Desai@Sun.COM smb_autohome_remove(pw.pw_name);
230*12065SKeyur.Desai@Sun.COM }
2315331Samw
2325331Samw ah = entry->sa_handle;
2335331Samw
2345331Samw if ((event = adt_alloc_event(ah, ADT_smbd_logoff)) == NULL) {
2355331Samw syslog(LOG_AUTH | LOG_ALERT,
2365331Samw "adt_alloc_event(ADT_smbd_logoff): %m");
2375331Samw } else {
2385331Samw event->adt_smbd_logoff.domain = entry->sa_domain;
2395331Samw event->adt_smbd_logoff.username = entry->sa_username;
2405331Samw
2415331Samw if (adt_put_event(event, ADT_SUCCESS, ADT_SUCCESS))
2425331Samw syslog(LOG_AUTH | LOG_ALERT, "adt_put_event: %m");
2435331Samw
2445331Samw adt_free_event(event);
2455331Samw }
2465331Samw
2475331Samw (void) adt_end_session(ah);
2485331Samw
2495331Samw free(entry->sa_username);
2505331Samw free(entry->sa_domain);
2515331Samw free(entry);
2525331Samw }
2535331Samw
2545331Samw /*
2555331Samw * Allocate an id and link an audit handle onto the global list.
2565331Samw */
2575331Samw static void
smbd_audit_link(smb_audit_t * entry)2585331Samw smbd_audit_link(smb_audit_t *entry)
2595331Samw {
2605331Samw (void) mutex_lock(&smbd_audit_lock);
2615331Samw
2625331Samw do {
2635331Samw ++smbd_audit_sid;
2645331Samw } while ((smbd_audit_sid == 0) || (smbd_audit_sid == (uint32_t)-1));
2655331Samw
2665331Samw entry->sa_audit_sid = smbd_audit_sid;
2675331Samw entry->sa_refcnt = 1;
2685331Samw entry->sa_next = smbd_audit_list;
2695331Samw smbd_audit_list = entry;
2705331Samw
2715331Samw (void) mutex_unlock(&smbd_audit_lock);
2725331Samw }
2735331Samw
2745331Samw /*
2755331Samw * Unlink an audit handle. If the reference count reaches 0, the entry
2765331Samw * is removed from the list and returned. Otherwise the entry remains
2775331Samw * on the list and a null pointer is returned.
2785331Samw */
2795331Samw static smb_audit_t *
smbd_audit_unlink(uint32_t audit_sid)2805331Samw smbd_audit_unlink(uint32_t audit_sid)
2815331Samw {
2825331Samw smb_audit_t *entry;
2835331Samw smb_audit_t **ppe;
2845331Samw
2855331Samw (void) mutex_lock(&smbd_audit_lock);
2865331Samw ppe = &smbd_audit_list;
2875331Samw
2885331Samw while (*ppe) {
2895331Samw entry = *ppe;
2905331Samw
2915331Samw if (entry->sa_audit_sid == audit_sid) {
2925331Samw if (entry->sa_refcnt == 0)
2935331Samw break;
2945331Samw
2955331Samw if ((--entry->sa_refcnt) != 0)
2965331Samw break;
2975331Samw
2985331Samw *ppe = entry->sa_next;
2995331Samw (void) mutex_unlock(&smbd_audit_lock);
3005331Samw return (entry);
3015331Samw }
3025331Samw
3035331Samw ppe = &(*ppe)->sa_next;
3045331Samw }
3055331Samw
3065331Samw (void) mutex_unlock(&smbd_audit_lock);
3075331Samw return (NULL);
3085331Samw }
309