summaryrefslogtreecommitdiffstats
path: root/source3/smbd/session.c
diff options
context:
space:
mode:
Diffstat (limited to 'source3/smbd/session.c')
-rw-r--r--source3/smbd/session.c218
1 files changed, 218 insertions, 0 deletions
diff --git a/source3/smbd/session.c b/source3/smbd/session.c
new file mode 100644
index 0000000..abc7991
--- /dev/null
+++ b/source3/smbd/session.c
@@ -0,0 +1,218 @@
+/*
+ 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;
+}