~zulcss/samba/server-dailies-3.4

« back to all changes in this revision

Viewing changes to source3/smbd/share_access.c

  • Committer: Chuck Short
  • Date: 2010-09-28 20:38:39 UTC
  • Revision ID: zulcss@ubuntu.com-20100928203839-pgjulytsi9ue63x1
Initial version

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
 
22
/*
 
23
 * No prefix means direct username
 
24
 * @name means netgroup first, then unix group
 
25
 * &name means netgroup
 
26
 * +name means unix group
 
27
 * + and & may be combined
 
28
 */
 
29
 
 
30
static bool do_group_checks(const char **name, const char **pattern)
 
31
{
 
32
        if ((*name)[0] == '@') {
 
33
                *pattern = "&+";
 
34
                *name += 1;
 
35
                return True;
 
36
        }
 
37
 
 
38
        if (((*name)[0] == '+') && ((*name)[1] == '&')) {
 
39
                *pattern = "+&";
 
40
                *name += 2;
 
41
                return True;
 
42
        }
 
43
 
 
44
        if ((*name)[0] == '+') {
 
45
                *pattern = "+";
 
46
                *name += 1;
 
47
                return True;
 
48
        }
 
49
 
 
50
        if (((*name)[0] == '&') && ((*name)[1] == '+')) {
 
51
                *pattern = "&+";
 
52
                *name += 2;
 
53
                return True;
 
54
        }
 
55
 
 
56
        if ((*name)[0] == '&') {
 
57
                *pattern = "&";
 
58
                *name += 1;
 
59
                return True;
 
60
        }
 
61
 
 
62
        return False;
 
63
}
 
64
 
 
65
static bool token_contains_name(TALLOC_CTX *mem_ctx,
 
66
                                const char *username,
 
67
                                const char *domain,
 
68
                                const char *sharename,
 
69
                                const struct nt_user_token *token,
 
70
                                const char *name)
 
71
{
 
72
        const char *prefix;
 
73
        DOM_SID sid;
 
74
        enum lsa_SidType type;
 
75
 
 
76
        if (username != NULL) {
 
77
                name = talloc_sub_basic(mem_ctx, username, domain, name);
 
78
        }
 
79
        if (sharename != NULL) {
 
80
                name = talloc_string_sub(mem_ctx, name, "%S", sharename);
 
81
        }
 
82
 
 
83
        if (name == NULL) {
 
84
                /* This is too security sensitive, better panic than return a
 
85
                 * result that might be interpreted in a wrong way. */
 
86
                smb_panic("substitutions failed");
 
87
        }
 
88
        
 
89
        /* check to see is we already have a SID */
 
90
 
 
91
        if ( string_to_sid( &sid, name ) ) {
 
92
                DEBUG(5,("token_contains_name: Checking for SID [%s] in token\n", name));
 
93
                return nt_token_check_sid( &sid, token );
 
94
        }
 
95
 
 
96
        if (!do_group_checks(&name, &prefix)) {
 
97
                if (!lookup_name_smbconf(mem_ctx, name, LOOKUP_NAME_ALL,
 
98
                                 NULL, NULL, &sid, &type)) {
 
99
                        DEBUG(5, ("lookup_name %s failed\n", name));
 
100
                        return False;
 
101
                }
 
102
                if (type != SID_NAME_USER) {
 
103
                        DEBUG(5, ("%s is a %s, expected a user\n",
 
104
                                  name, sid_type_lookup(type)));
 
105
                        return False;
 
106
                }
 
107
                return nt_token_check_sid(&sid, token);
 
108
        }
 
109
 
 
110
        for (/* initialized above */ ; *prefix != '\0'; prefix++) {
 
111
                if (*prefix == '+') {
 
112
                        if (!lookup_name_smbconf(mem_ctx, name,
 
113
                                         LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
 
114
                                         NULL, NULL, &sid, &type)) {
 
115
                                DEBUG(5, ("lookup_name %s failed\n", name));
 
116
                                return False;
 
117
                        }
 
118
                        if ((type != SID_NAME_DOM_GRP) &&
 
119
                            (type != SID_NAME_ALIAS) &&
 
120
                            (type != SID_NAME_WKN_GRP)) {
 
121
                                DEBUG(5, ("%s is a %s, expected a group\n",
 
122
                                          name, sid_type_lookup(type)));
 
123
                                return False;
 
124
                        }
 
125
                        if (nt_token_check_sid(&sid, token)) {
 
126
                                return True;
 
127
                        }
 
128
                        continue;
 
129
                }
 
130
                if (*prefix == '&') {
 
131
                        if (user_in_netgroup(username, name)) {
 
132
                                return True;
 
133
                        }
 
134
                        continue;
 
135
                }
 
136
                smb_panic("got invalid prefix from do_groups_check");
 
137
        }
 
138
        return False;
 
139
}
 
140
 
 
141
/*
 
142
 * Check whether a user is contained in the list provided.
 
143
 *
 
144
 * Please note that the user name and share names passed in here mainly for
 
145
 * the substitution routines that expand the parameter values, the decision
 
146
 * whether a user is in the list is done after a lookup_name on the expanded
 
147
 * parameter value, solely based on comparing the SIDs in token.
 
148
 *
 
149
 * The other use is the netgroup check when using @group or &group.
 
150
 */
 
151
 
 
152
bool token_contains_name_in_list(const char *username,
 
153
                                 const char *domain,
 
154
                                 const char *sharename,
 
155
                                 const struct nt_user_token *token,
 
156
                                 const char **list)
 
157
{
 
158
        TALLOC_CTX *mem_ctx;
 
159
 
 
160
        if (list == NULL) {
 
161
                return False;
 
162
        }
 
163
 
 
164
        if ( (mem_ctx = talloc_new(NULL)) == NULL ) {
 
165
                smb_panic("talloc_new failed");
 
166
        }
 
167
 
 
168
        while (*list != NULL) {
 
169
                if (token_contains_name(mem_ctx, username, domain, sharename,
 
170
                                        token, *list)) {
 
171
                        TALLOC_FREE(mem_ctx);
 
172
                        return True;
 
173
                }
 
174
                list += 1;
 
175
        }
 
176
 
 
177
        TALLOC_FREE(mem_ctx);
 
178
        return False;
 
179
}
 
180
 
 
181
/*
 
182
 * Check whether the user described by "token" has access to share snum.
 
183
 *
 
184
 * This looks at "invalid users", "valid users" and "only user/username"
 
185
 *
 
186
 * Please note that the user name and share names passed in here mainly for
 
187
 * the substitution routines that expand the parameter values, the decision
 
188
 * whether a user is in the list is done after a lookup_name on the expanded
 
189
 * parameter value, solely based on comparing the SIDs in token.
 
190
 *
 
191
 * The other use is the netgroup check when using @group or &group.
 
192
 */
 
193
 
 
194
bool user_ok_token(const char *username, const char *domain,
 
195
                   const struct nt_user_token *token, int snum)
 
196
{
 
197
        if (lp_invalid_users(snum) != NULL) {
 
198
                if (token_contains_name_in_list(username, domain,
 
199
                                                lp_servicename(snum),
 
200
                                                token,
 
201
                                                lp_invalid_users(snum))) {
 
202
                        DEBUG(10, ("User %s in 'invalid users'\n", username));
 
203
                        return False;
 
204
                }
 
205
        }
 
206
 
 
207
        if (lp_valid_users(snum) != NULL) {
 
208
                if (!token_contains_name_in_list(username, domain,
 
209
                                                 lp_servicename(snum), token,
 
210
                                                 lp_valid_users(snum))) {
 
211
                        DEBUG(10, ("User %s not in 'valid users'\n",
 
212
                                   username));
 
213
                        return False;
 
214
                }
 
215
        }
 
216
 
 
217
        if (lp_onlyuser(snum)) {
 
218
                const char *list[2];
 
219
                list[0] = lp_username(snum);
 
220
                list[1] = NULL;
 
221
                if ((list[0] == NULL) || (*list[0] == '\0')) {
 
222
                        DEBUG(0, ("'only user = yes' and no 'username ='\n"));
 
223
                        return False;
 
224
                }
 
225
                if (!token_contains_name_in_list(NULL, domain,
 
226
                                                 lp_servicename(snum),
 
227
                                                 token, list)) {
 
228
                        DEBUG(10, ("%s != 'username'\n", username));
 
229
                        return False;
 
230
                }
 
231
        }
 
232
 
 
233
        DEBUG(10, ("user_ok_token: share %s is ok for unix user %s\n",
 
234
                   lp_servicename(snum), username));
 
235
 
 
236
        return True;
 
237
}
 
238
 
 
239
/*
 
240
 * Check whether the user described by "token" is restricted to read-only
 
241
 * access on share snum.
 
242
 *
 
243
 * This looks at "invalid users", "valid users" and "only user/username"
 
244
 *
 
245
 * Please note that the user name and share names passed in here mainly for
 
246
 * the substitution routines that expand the parameter values, the decision
 
247
 * whether a user is in the list is done after a lookup_name on the expanded
 
248
 * parameter value, solely based on comparing the SIDs in token.
 
249
 *
 
250
 * The other use is the netgroup check when using @group or &group.
 
251
 */
 
252
 
 
253
bool is_share_read_only_for_token(const char *username,
 
254
                                  const char *domain,
 
255
                                  const struct nt_user_token *token,
 
256
                                  connection_struct *conn)
 
257
{
 
258
        int snum = SNUM(conn);
 
259
        bool result = conn->read_only;
 
260
 
 
261
        if (lp_readlist(snum) != NULL) {
 
262
                if (token_contains_name_in_list(username, domain,
 
263
                                                lp_servicename(snum), token,
 
264
                                                lp_readlist(snum))) {
 
265
                        result = True;
 
266
                }
 
267
        }
 
268
 
 
269
        if (lp_writelist(snum) != NULL) {
 
270
                if (token_contains_name_in_list(username, domain,
 
271
                                                lp_servicename(snum), token,
 
272
                                                lp_writelist(snum))) {
 
273
                        result = False;
 
274
                }
 
275
        }
 
276
 
 
277
        DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
 
278
                  "%s\n", lp_servicename(snum),
 
279
                  result ? "read-only" : "read-write", username));
 
280
 
 
281
        return result;
 
282
}