Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/smbd/session.c
Line
Count
Source (jump to first uncovered line)
1
/* 
2
   Unix SMB/CIFS implementation.
3
   session handling for utmp and PAM
4
5
   Copyright (C) tridge@samba.org       2001
6
   Copyright (C) abartlet@samba.org     2001
7
   Copyright (C) Gerald (Jerry) Carter  2006   
8
   
9
   This program is free software; you can redistribute it and/or modify
10
   it under the terms of the GNU General Public License as published by
11
   the Free Software Foundation; either version 3 of the License, or
12
   (at your option) any later version.
13
   
14
   This program is distributed in the hope that it will be useful,
15
   but WITHOUT ANY WARRANTY; without even the implied warranty of
16
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17
   GNU General Public License for more details.
18
   
19
   You should have received a copy of the GNU General Public License
20
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
21
*/
22
23
/* a "session" is claimed when we do a SessionSetupX operation
24
   and is yielded when the corresponding vuid is destroyed.
25
26
   sessions are used to populate utmp and PAM session structures
27
*/
28
29
#include "includes.h"
30
#include "smbd/smbd.h"
31
#include "smbd/globals.h"
32
#include "dbwrap/dbwrap.h"
33
#include "session.h"
34
#include "auth.h"
35
#include "../lib/tsocket/tsocket.h"
36
#include "../libcli/security/security.h"
37
#include "messages.h"
38
39
/********************************************************************
40
 called when a session is created
41
********************************************************************/
42
43
bool session_claim(struct smbXsrv_session *session)
44
0
{
45
0
  struct auth_session_info *session_info =
46
0
    session->global->auth_session_info;
47
0
  const char *username;
48
0
  const char *hostname;
49
0
  unsigned int id_num;
50
0
  fstring id_str;
51
52
  /* don't register sessions for the guest user - its just too
53
     expensive to go through pam session code for browsing etc */
54
0
  if (security_session_user_level(session_info, NULL) < SECURITY_USER) {
55
0
    return true;
56
0
  }
57
58
0
  id_num = session->global->session_global_id;
59
60
0
  snprintf(id_str, sizeof(id_str), "smb/%u", id_num);
61
62
  /* Make clear that we require the optional unix_token in the source3 code */
63
0
  SMB_ASSERT(session_info->unix_token);
64
65
0
  username = session_info->unix_info->unix_name;
66
0
  hostname = session->global->channels[0].remote_name;
67
68
0
  if (!smb_pam_claim_session(username, id_str, hostname)) {
69
0
    DEBUG(1,("pam_session rejected the session for %s [%s]\n",
70
0
        username, id_str));
71
0
    return false;
72
0
  }
73
74
0
  if (lp_utmp()) {
75
0
    sys_utmp_claim(username, hostname, id_str, id_num);
76
0
  }
77
78
0
  return true;
79
0
}
80
81
/********************************************************************
82
 called when a session is destroyed
83
********************************************************************/
84
85
void session_yield(struct smbXsrv_session *session)
86
0
{
87
0
  struct auth_session_info *session_info =
88
0
    session->global->auth_session_info;
89
0
  const char *username;
90
0
  const char *hostname;
91
0
  unsigned int id_num;
92
0
  fstring id_str = "";
93
94
0
  id_num = session->global->session_global_id;
95
96
0
  snprintf(id_str, sizeof(id_str), "smb/%u", id_num);
97
98
  /* Make clear that we require the optional unix_token in the source3 code */
99
0
  SMB_ASSERT(session_info->unix_token);
100
101
0
  username = session_info->unix_info->unix_name;
102
0
  hostname = session->global->channels[0].remote_name;
103
104
0
  if (lp_utmp()) {
105
0
    sys_utmp_yield(username, hostname, id_str, id_num);
106
0
  }
107
108
0
  smb_pam_close_session(username, id_str, hostname);
109
0
}
110
111
/********************************************************************
112
********************************************************************/
113
114
struct session_list {
115
  TALLOC_CTX *mem_ctx;
116
  int count;
117
  const char *filter_user;
118
  const char *filter_machine;
119
  struct sessionid *sessions;
120
};
121
122
static int gather_sessioninfo(const char *key, struct sessionid *session,
123
            void *private_data)
124
0
{
125
0
  struct session_list *sesslist = (struct session_list *)private_data;
126
127
  /* filter the session if required */
128
129
0
  if (sesslist->filter_user &&
130
0
      (sesslist->filter_user[0] != '\0') &&
131
0
      !strequal(session->username, sesslist->filter_user)) {
132
0
    return 0;
133
0
  }
134
135
0
  if (sesslist->filter_machine &&
136
0
      (sesslist->filter_machine[0] != '\0') &&
137
0
      !strequal(session->remote_machine,
138
0
          sesslist->filter_machine)) {
139
0
    return 0;
140
0
  }
141
142
0
  if (!process_exists(session->pid)) {
143
0
    return 0;
144
0
  }
145
146
0
  sesslist->sessions = talloc_realloc(
147
0
    sesslist->mem_ctx, sesslist->sessions, struct sessionid,
148
0
    sesslist->count+1);
149
150
0
  if (!sesslist->sessions) {
151
0
    sesslist->count = 0;
152
0
    return -1;
153
0
  }
154
155
0
  memcpy(&sesslist->sessions[sesslist->count], session,
156
0
         sizeof(struct sessionid));
157
158
0
  sesslist->count++;
159
160
0
  DEBUG(7, ("gather_sessioninfo session from %s@%s\n",
161
0
      session->username, session->remote_machine));
162
163
0
  return 0;
164
0
}
165
166
/********************************************************************
167
********************************************************************/
168
169
int list_sessions(TALLOC_CTX *mem_ctx, struct sessionid **session_list)
170
0
{
171
0
  struct session_list sesslist;
172
0
  NTSTATUS status;
173
174
0
  sesslist.mem_ctx = mem_ctx;
175
0
  sesslist.count = 0;
176
0
  sesslist.filter_user = NULL;
177
0
  sesslist.filter_machine = NULL;
178
0
  sesslist.sessions = NULL;
179
180
0
  status = sessionid_traverse_read(gather_sessioninfo, (void *) &sesslist);
181
0
  if (!NT_STATUS_IS_OK(status)) {
182
0
    DBG_ERR("Session traverse failed: %s\n", nt_errstr(status));
183
0
    TALLOC_FREE(sesslist.sessions);
184
0
    *session_list = NULL;
185
0
    return 0;
186
0
  }
187
188
0
  *session_list = sesslist.sessions;
189
0
  return sesslist.count;
190
0
}
191
192
/********************************************************************
193
find the sessions that match the given username and machine
194
********************************************************************/
195
196
int find_sessions(TALLOC_CTX *mem_ctx, const char *username,
197
      const char *machine, struct sessionid **session_list)
198
0
{
199
0
  struct session_list sesslist;
200
0
  NTSTATUS status;
201
202
0
  sesslist.mem_ctx = mem_ctx;
203
0
  sesslist.count = 0;
204
0
  sesslist.filter_user = username;
205
0
  sesslist.filter_machine = machine;
206
0
  sesslist.sessions = NULL;
207
208
0
  status = sessionid_traverse_read(gather_sessioninfo, (void *)&sesslist);
209
0
  if (!NT_STATUS_IS_OK(status)) {
210
0
    DEBUG(3, ("Session traverse failed: %s\n", nt_errstr(status)));
211
0
    TALLOC_FREE(sesslist.sessions);
212
0
    *session_list = NULL;
213
0
    return 0;
214
0
  }
215
216
0
  *session_list = sesslist.sessions;
217
0
  return sesslist.count;
218
0
}