1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-27 03:21:53 +03:00
samba-mirror/source3/smbd/session.c
Stefan Metzmacher 4c6156eddd s3:smbd: fix SAFE_FREE() vs. TALLOC_FREE() in list_sessions()
It's very unlikely that sessionid_traverse_read() fails,
but we should not segfault.

Signed-off-by: Stefan Metzmacher <metze@samba.org>
Reviewed-by: Ralph Boehme <slow@samba.org>
Reviewed-by: Jeremy Allison <jra@samba.org>
2019-03-28 23:09:33 +00:00

219 lines
6.0 KiB
C

/*
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 <http://www.gnu.org/licenses/>.
*/
/* 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;
}