Coverage Report

Created: 2025-07-23 07:04

/src/samba/source3/smbd/share_access.c
Line
Count
Source (jump to first uncovered line)
1
/*
2
   Unix SMB/CIFS implementation.
3
   Check access based on valid users, read list and friends
4
   Copyright (C) Volker Lendecke 2005
5
6
   This program is free software; you can redistribute it and/or modify
7
   it under the terms of the GNU General Public License as published by
8
   the Free Software Foundation; either version 3 of the License, or
9
   (at your option) any later version.
10
11
   This program is distributed in the hope that it will be useful,
12
   but WITHOUT ANY WARRANTY; without even the implied warranty of
13
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
14
   GNU General Public License for more details.
15
16
   You should have received a copy of the GNU General Public License
17
   along with this program.  If not, see <http://www.gnu.org/licenses/>.
18
*/
19
20
#include "includes.h"
21
#include "smbd/smbd.h"
22
#include "smbd/globals.h"
23
#include "../libcli/security/security.h"
24
25
/*
26
 * Check whether a user is contained in the list provided.
27
 *
28
 * Please note that the user name and share names passed in here mainly for
29
 * the substitution routines that expand the parameter values, the decision
30
 * whether a user is in the list is done after a lookup_name on the expanded
31
 * parameter value, solely based on comparing the SIDs in token.
32
 *
33
 * The other use is the netgroup check when using @group or &group.
34
 */
35
36
bool token_contains_name_in_list(const char *username,
37
         const char *domain,
38
         const char *sharename,
39
         const struct security_token *token,
40
         const char **list,
41
         bool *match)
42
0
{
43
0
  *match = false;
44
0
  if (list == NULL) {
45
0
    return true;
46
0
  }
47
0
  while (*list != NULL) {
48
0
    TALLOC_CTX *frame = talloc_stackframe();
49
0
    bool ok;
50
51
0
          ok = token_contains_name(frame, username, domain, sharename,
52
0
           token, *list, match);
53
0
    TALLOC_FREE(frame);
54
0
    if (!ok) {
55
0
      return false;
56
0
    }
57
0
    if (*match) {
58
0
      return true;
59
0
    }
60
0
    list += 1;
61
0
  }
62
0
  return true;
63
0
}
64
65
/*
66
 * Check whether the user described by "token" has access to share snum.
67
 *
68
 * This looks at "invalid users" and "valid users".
69
 *
70
 * Please note that the user name and share names passed in here mainly for
71
 * the substitution routines that expand the parameter values, the decision
72
 * whether a user is in the list is done after a lookup_name on the expanded
73
 * parameter value, solely based on comparing the SIDs in token.
74
 *
75
 * The other use is the netgroup check when using @group or &group.
76
 */
77
78
bool user_ok_token(const char *username, const char *domain,
79
       const struct security_token *token, int snum)
80
0
{
81
0
  const struct loadparm_substitution *lp_sub =
82
0
    loadparm_s3_global_substitution();
83
0
  bool match;
84
0
  bool ok;
85
86
0
  if (lp_invalid_users(snum) != NULL) {
87
0
    ok = token_contains_name_in_list(username, domain,
88
0
             lp_servicename(talloc_tos(), lp_sub, snum),
89
0
             token,
90
0
             lp_invalid_users(snum),
91
0
             &match);
92
0
    if (!ok) {
93
0
      return false;
94
0
    }
95
0
    if (match) {
96
0
      DEBUG(10, ("User %s in 'invalid users'\n", username));
97
0
      return False;
98
0
    }
99
0
  }
100
101
0
  if (lp_valid_users(snum) != NULL) {
102
0
    ok = token_contains_name_in_list(username, domain,
103
0
             lp_servicename(talloc_tos(), lp_sub, snum),
104
0
             token,
105
0
             lp_valid_users(snum),
106
0
             &match);
107
0
    if (!ok) {
108
0
      return false;
109
0
    }
110
0
    if (!match) {
111
0
      DEBUG(10, ("User %s not in 'valid users'\n",
112
0
           username));
113
0
      return False;
114
0
    }
115
0
  }
116
117
0
  DEBUG(10, ("user_ok_token: share %s is ok for unix user %s\n",
118
0
       lp_servicename(talloc_tos(), lp_sub, snum), username));
119
120
0
  return True;
121
0
}
122
123
/*
124
 * Check whether the user described by "token" is restricted to read-only
125
 * access on share snum.
126
 *
127
 * This looks at "read list", "write list" and "read only".
128
 *
129
 * Please note that the user name and share names passed in here mainly for
130
 * the substitution routines that expand the parameter values, the decision
131
 * whether a user is in the list is done after a lookup_name on the expanded
132
 * parameter value, solely based on comparing the SIDs in token.
133
 *
134
 * The other use is the netgroup check when using @group or &group.
135
 */
136
137
bool is_share_read_only_for_token(const char *username,
138
          const char *domain,
139
          const struct security_token *token,
140
          connection_struct *conn,
141
          bool *_read_only)
142
0
{
143
0
  const struct loadparm_substitution *lp_sub =
144
0
    loadparm_s3_global_substitution();
145
0
  int snum = SNUM(conn);
146
0
  bool read_only = conn->read_only;
147
0
  bool match;
148
0
  bool ok;
149
150
0
  if (lp_read_list(snum) != NULL) {
151
0
    ok = token_contains_name_in_list(username, domain,
152
0
             lp_servicename(talloc_tos(), lp_sub, snum),
153
0
             token,
154
0
             lp_read_list(snum),
155
0
             &match);
156
0
    if (!ok) {
157
0
      return false;
158
0
    }
159
0
    if (match) {
160
0
      read_only = true;
161
0
    }
162
0
  }
163
164
0
  if (lp_write_list(snum) != NULL) {
165
0
    ok = token_contains_name_in_list(username, domain,
166
0
             lp_servicename(talloc_tos(), lp_sub, snum),
167
0
             token,
168
0
             lp_write_list(snum),
169
0
             &match);
170
0
    if (!ok) {
171
0
      return false;
172
0
    }
173
0
    if (match) {
174
0
      read_only = false;
175
0
    }
176
0
  }
177
178
0
  DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
179
0
      "%s\n", lp_servicename(talloc_tos(), lp_sub, snum),
180
0
      read_only ? "read-only" : "read-write", username));
181
182
0
  *_read_only = read_only;
183
0
  return true;
184
0
}