/* Unix SMB/CIFS implementation. session handling for utmp and PAM Copyright (C) tridge@samba.org 2001 Copyright (C) abartlet@samba.org 2001 Copyright (C) Gerald (Jerry) Carter 2006 This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ /* a "session" is claimed when we do a SessionSetupX operation and is yielded when the corresponding vuid is destroyed. sessions are used to populate utmp and PAM session structures */ #include "includes.h" #include "smbd/smbd.h" #include "smbd/globals.h" #include "dbwrap/dbwrap.h" #include "session.h" #include "auth.h" #include "../lib/tsocket/tsocket.h" #include "../libcli/security/security.h" #include "messages.h" /******************************************************************** called when a session is created ********************************************************************/ bool session_claim(struct smbXsrv_session *session) { struct auth_session_info *session_info = session->global->auth_session_info; const char *username; const char *hostname; unsigned int id_num; fstring id_str; /* don't register sessions for the guest user - its just too expensive to go through pam session code for browsing etc */ if (security_session_user_level(session_info, NULL) < SECURITY_USER) { return true; } id_num = session->global->session_global_id; snprintf(id_str, sizeof(id_str), "smb/%u", id_num); /* Make clear that we require the optional unix_token in the source3 code */ SMB_ASSERT(session_info->unix_token); username = session_info->unix_info->unix_name; hostname = session->global->channels[0].remote_name; if (!smb_pam_claim_session(username, id_str, hostname)) { DEBUG(1,("pam_session rejected the session for %s [%s]\n", username, id_str)); return false; } if (lp_utmp()) { sys_utmp_claim(username, hostname, id_str, id_num); } return true; } /******************************************************************** called when a session is destroyed ********************************************************************/ void session_yield(struct smbXsrv_session *session) { struct auth_session_info *session_info = session->global->auth_session_info; const char *username; const char *hostname; unsigned int id_num; fstring id_str = ""; id_num = session->global->session_global_id; snprintf(id_str, sizeof(id_str), "smb/%u", id_num); /* Make clear that we require the optional unix_token in the source3 code */ SMB_ASSERT(session_info->unix_token); username = session_info->unix_info->unix_name; hostname = session->global->channels[0].remote_name; if (lp_utmp()) { sys_utmp_yield(username, hostname, id_str, id_num); } smb_pam_close_session(username, id_str, hostname); } /******************************************************************** ********************************************************************/ struct session_list { TALLOC_CTX *mem_ctx; int count; const char *filter_user; const char *filter_machine; struct sessionid *sessions; }; static int gather_sessioninfo(const char *key, struct sessionid *session, void *private_data) { struct session_list *sesslist = (struct session_list *)private_data; /* filter the session if required */ if (sesslist->filter_user && (sesslist->filter_user[0] != '\0') && !strequal(session->username, sesslist->filter_user)) { return 0; } if (sesslist->filter_machine && (sesslist->filter_machine[0] != '\0') && !strequal(session->remote_machine, sesslist->filter_machine)) { return 0; } if (!process_exists(session->pid)) { return 0; } sesslist->sessions = talloc_realloc( sesslist->mem_ctx, sesslist->sessions, struct sessionid, sesslist->count+1); if (!sesslist->sessions) { sesslist->count = 0; return -1; } memcpy(&sesslist->sessions[sesslist->count], session, sizeof(struct sessionid)); sesslist->count++; DEBUG(7, ("gather_sessioninfo session from %s@%s\n", session->username, session->remote_machine)); return 0; } /******************************************************************** ********************************************************************/ int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list) { struct session_list sesslist; NTSTATUS status; sesslist.mem_ctx = mem_ctx; sesslist.count = 0; sesslist.filter_user = NULL; sesslist.filter_machine = NULL; sesslist.sessions = NULL; status = sessionid_traverse_read(gather_sessioninfo, (void *) &sesslist); if (!NT_STATUS_IS_OK(status)) { DBG_ERR("Session traverse failed: %s\n", nt_errstr(status)); TALLOC_FREE(sesslist.sessions); *session_list = NULL; return 0; } *session_list = sesslist.sessions; return sesslist.count; } /******************************************************************** find the sessions that match the given username and machine ********************************************************************/ int find_sessions(TALLOC_CTX *mem_ctx, const char *username, const char *machine, struct sessionid **session_list) { struct session_list sesslist; NTSTATUS status; sesslist.mem_ctx = mem_ctx; sesslist.count = 0; sesslist.filter_user = username; sesslist.filter_machine = machine; sesslist.sessions = NULL; status = sessionid_traverse_read(gather_sessioninfo, (void *)&sesslist); if (!NT_STATUS_IS_OK(status)) { DEBUG(3, ("Session traverse failed: %s\n", nt_errstr(status))); TALLOC_FREE(sesslist.sessions); *session_list = NULL; return 0; } *session_list = sesslist.sessions; return sesslist.count; }