Print this page
NEX-17589 Get "too high" smbd error when copy big file to cifs share
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
Reviewed by: Evan Layton <evan.layton@nexenta.com>
Reviewed by: Matt Barden <matt.barden@nexenta.com>
NEX-17795 SMB logon should tolerate idmap problems
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Joyce McIntosh <joyce.mcintosh@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-9190 Files with owners not in /etc/passwd and not having inherited ACL's are prevented from seeing ownership/permissions via SMB
Reviewed by: Gordon Ross <gordon.ross@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
NEX-4083 Upstream changes from illumos 5917 and 5995
Reviewed by: Matt Barden <matt.barden@nexenta.com>
Reviewed by: Kevin Crowe <kevin.crowe@nexenta.com>
Reviewed by: Yuri Pankov <yuri.pankov@nexenta.com>
SMB-50 User-mode SMB server
Includes work by these authors:
Thomas Keiser <thomas.keiser@nexenta.com>
Albert Lee <trisk@nexenta.com>
| Split |
Close |
| Expand all |
| Collapse all |
--- old/usr/src/uts/common/fs/smbsrv/smb_idmap.c
+++ new/usr/src/uts/common/fs/smbsrv/smb_idmap.c
1 1 /*
2 2 * CDDL HEADER START
3 3 *
4 4 * The contents of this file are subject to the terms of the
5 5 * Common Development and Distribution License (the "License").
6 6 * You may not use this file except in compliance with the License.
7 7 *
8 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 9 * or http://www.opensolaris.org/os/licensing.
10 10 * See the License for the specific language governing permissions
11 11 * and limitations under the License.
12 12 *
|
↓ open down ↓ |
12 lines elided |
↑ open up ↑ |
13 13 * When distributing Covered Code, include this CDDL HEADER in each
14 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 15 * If applicable, add the following below this CDDL HEADER, with the
16 16 * fields enclosed by brackets "[]" replaced with your own identifying
17 17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 18 *
19 19 * CDDL HEADER END
20 20 */
21 21 /*
22 22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 - * Copyright 2013 Nexenta Systems, Inc. All rights reserved.
23 + * Copyright 2018 Nexenta Systems, Inc. All rights reserved.
24 24 */
25 25
26 26 /*
27 27 * SMB server interface to idmap
28 28 * (smb_idmap_get..., smb_idmap_batch_...)
29 29 *
30 - * There are three implementations of this interface:
31 - * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
32 - * lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c (libfksmbsrv)
33 - * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
30 + * There are three implementations of this interface.
31 + * This is the kernel version of these routines. See also:
32 + * $SRC/lib/smbsrv/libfksmbsrv/common/fksmb_idmap.c
33 + * $SRC/lib/smbsrv/libsmb/common/smb_idmap.c
34 34 *
35 35 * There are enough differences (relative to the code size)
36 36 * that it's more trouble than it's worth to merge them.
37 37 *
38 38 * This one differs from the others in that it:
39 39 * calls kernel (kidmap_...) interfaces
40 - * domain SIDs are shared, not strdup'ed
40 + * returned domain SIDs are shared, not strdup'ed
41 41 */
42 42
43 43 /*
44 44 * SMB ID mapping
45 45 *
46 46 * Solaris ID mapping service (aka Winchester) works with domain SIDs
47 47 * and RIDs where domain SIDs are in string format. CIFS service works
48 48 * with binary SIDs understandable by CIFS clients. A layer of SMB ID
49 49 * mapping functions are implemeted to hide the SID conversion details
50 50 * and also hide the handling of array of batch mapping requests.
51 51 */
52 52
53 53 #include <sys/param.h>
54 54 #include <sys/types.h>
55 55 #include <sys/tzfile.h>
56 56 #include <sys/atomic.h>
57 57 #include <sys/kidmap.h>
58 58 #include <sys/time.h>
59 59 #include <sys/spl.h>
60 60 #include <sys/random.h>
61 61 #include <smbsrv/smb_kproto.h>
62 62 #include <smbsrv/smb_fsops.h>
63 63 #include <smbsrv/smbinfo.h>
64 64 #include <smbsrv/smb_xdr.h>
65 65 #include <smbsrv/smb_vops.h>
66 66 #include <smbsrv/smb_idmap.h>
67 67
68 68 #include <sys/sid.h>
69 69 #include <sys/priv_names.h>
70 70
71 71 static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
72 72
73 73 /*
74 74 * smb_idmap_getsid
75 75 *
76 76 * Maps the given Solaris ID to a Windows SID using the
77 77 * simple mapping API.
78 78 */
79 79 idmap_stat
80 80 smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
81 81 {
82 82 smb_idmap_t sim;
83 83
84 84 switch (idtype) {
85 85 case SMB_IDMAP_USER:
86 86 sim.sim_stat = kidmap_getsidbyuid(global_zone, id,
87 87 (const char **)&sim.sim_domsid, &sim.sim_rid);
88 88 break;
89 89
90 90 case SMB_IDMAP_GROUP:
91 91 sim.sim_stat = kidmap_getsidbygid(global_zone, id,
92 92 (const char **)&sim.sim_domsid, &sim.sim_rid);
93 93 break;
94 94
95 95 case SMB_IDMAP_EVERYONE:
96 96 /* Everyone S-1-1-0 */
|
↓ open down ↓ |
46 lines elided |
↑ open up ↑ |
97 97 sim.sim_domsid = "S-1-1";
98 98 sim.sim_rid = 0;
99 99 sim.sim_stat = IDMAP_SUCCESS;
100 100 break;
101 101
102 102 default:
103 103 ASSERT(0);
104 104 return (IDMAP_ERR_ARG);
105 105 }
106 106
107 + /*
108 + * IDMAP_ERR_NOTFOUND is an advisory error
109 + * and idmap will generate a local sid.
110 + */
111 + if (sim.sim_stat == IDMAP_ERR_NOTFOUND &&
112 + sim.sim_domsid != NULL)
113 + sim.sim_stat = IDMAP_SUCCESS;
114 +
107 115 if (sim.sim_stat != IDMAP_SUCCESS)
108 116 return (sim.sim_stat);
109 117
110 118 if (sim.sim_domsid == NULL)
111 119 return (IDMAP_ERR_NOMAPPING);
112 120
113 121 sim.sim_sid = smb_sid_fromstr(sim.sim_domsid);
114 122 if (sim.sim_sid == NULL)
115 123 return (IDMAP_ERR_INTERNAL);
116 124
117 125 *sid = smb_sid_splice(sim.sim_sid, sim.sim_rid);
118 126 smb_sid_free(sim.sim_sid);
119 127 if (*sid == NULL)
120 128 sim.sim_stat = IDMAP_ERR_INTERNAL;
121 129
122 130 return (sim.sim_stat);
123 131 }
124 132
125 133 /*
126 134 * smb_idmap_getid
127 135 *
128 136 * Maps the given Windows SID to a Unix ID using the
129 137 * simple mapping API.
130 138 */
131 139 idmap_stat
132 140 smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *idtype)
133 141 {
134 142 smb_idmap_t sim;
135 143 char sidstr[SMB_SID_STRSZ];
136 144
137 145 smb_sid_tostr(sid, sidstr);
138 146 if (smb_sid_splitstr(sidstr, &sim.sim_rid) != 0)
139 147 return (IDMAP_ERR_SID);
140 148 sim.sim_domsid = sidstr;
141 149 sim.sim_id = id;
142 150
143 151 switch (*idtype) {
144 152 case SMB_IDMAP_USER:
145 153 sim.sim_stat = kidmap_getuidbysid(global_zone, sim.sim_domsid,
146 154 sim.sim_rid, sim.sim_id);
147 155 break;
148 156
149 157 case SMB_IDMAP_GROUP:
150 158 sim.sim_stat = kidmap_getgidbysid(global_zone, sim.sim_domsid,
151 159 sim.sim_rid, sim.sim_id);
152 160 break;
153 161
154 162 case SMB_IDMAP_UNKNOWN:
155 163 sim.sim_stat = kidmap_getpidbysid(global_zone, sim.sim_domsid,
156 164 sim.sim_rid, sim.sim_id, &sim.sim_idtype);
157 165 break;
158 166
159 167 default:
160 168 ASSERT(0);
161 169 return (IDMAP_ERR_ARG);
162 170 }
163 171
164 172 *idtype = sim.sim_idtype;
165 173
166 174 return (sim.sim_stat);
|
↓ open down ↓ |
50 lines elided |
↑ open up ↑ |
167 175 }
168 176
169 177 /*
170 178 * smb_idmap_batch_create
171 179 *
172 180 * Creates and initializes the context for batch ID mapping.
173 181 */
174 182 idmap_stat
175 183 smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
176 184 {
177 - ASSERT(sib);
185 + ASSERT(sib != NULL);
178 186
179 187 bzero(sib, sizeof (smb_idmap_batch_t));
180 188
181 189 sib->sib_idmaph = kidmap_get_create(global_zone);
182 190
183 191 sib->sib_flags = flags;
184 192 sib->sib_nmap = nmap;
185 193 sib->sib_size = nmap * sizeof (smb_idmap_t);
186 194 sib->sib_maps = kmem_zalloc(sib->sib_size, KM_SLEEP);
187 195
188 196 return (IDMAP_SUCCESS);
189 197 }
190 198
191 199 /*
192 200 * smb_idmap_batch_destroy
193 201 *
|
↓ open down ↓ |
6 lines elided |
↑ open up ↑ |
194 202 * Frees the batch ID mapping context.
195 203 * If ID mapping is Solaris -> Windows it frees memories
196 204 * allocated for binary SIDs.
197 205 */
198 206 void
199 207 smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
200 208 {
201 209 char *domsid;
202 210 int i;
203 211
204 - ASSERT(sib);
205 - ASSERT(sib->sib_maps);
212 + ASSERT(sib != NULL);
213 + ASSERT(sib->sib_maps != NULL);
206 214
207 - if (sib->sib_idmaph)
215 + if (sib->sib_idmaph) {
208 216 kidmap_get_destroy(sib->sib_idmaph);
217 + sib->sib_idmaph = NULL;
218 + }
209 219
210 220 if (sib->sib_flags & SMB_IDMAP_ID2SID) {
211 221 /*
212 222 * SIDs are allocated only when mapping
213 223 * UID/GID to SIDs
214 224 */
215 225 for (i = 0; i < sib->sib_nmap; i++)
216 226 smb_sid_free(sib->sib_maps[i].sim_sid);
217 227 } else if (sib->sib_flags & SMB_IDMAP_SID2ID) {
218 228 /*
219 229 * SID prefixes are allocated only when mapping
220 230 * SIDs to UID/GID
221 231 */
222 232 for (i = 0; i < sib->sib_nmap; i++) {
223 233 domsid = sib->sib_maps[i].sim_domsid;
224 234 if (domsid)
225 235 smb_mem_free(domsid);
226 236 }
227 237 }
228 238
229 - if (sib->sib_size && sib->sib_maps)
239 + if (sib->sib_size && sib->sib_maps) {
230 240 kmem_free(sib->sib_maps, sib->sib_size);
241 + sib->sib_maps = NULL;
242 + }
231 243 }
232 244
233 245 /*
234 246 * smb_idmap_batch_getid
235 247 *
236 248 * Queue a request to map the given SID to a UID or GID.
237 249 *
238 250 * sim->sim_id should point to variable that's supposed to
239 251 * hold the returned UID/GID. This needs to be setup by caller
240 252 * of this function.
241 253 *
|
↓ open down ↓ |
1 lines elided |
↑ open up ↑ |
242 254 * If requested ID type is known, it's passed as 'idtype',
243 255 * if it's unknown it'll be returned in sim->sim_idtype.
244 256 */
245 257 idmap_stat
246 258 smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
247 259 smb_sid_t *sid, int idtype)
248 260 {
249 261 char strsid[SMB_SID_STRSZ];
250 262 idmap_stat idm_stat;
251 263
252 - ASSERT(idmaph);
253 - ASSERT(sim);
254 - ASSERT(sid);
264 + ASSERT(idmaph != NULL);
265 + ASSERT(sim != NULL);
266 + ASSERT(sid != NULL);
255 267
256 268 smb_sid_tostr(sid, strsid);
257 269 if (smb_sid_splitstr(strsid, &sim->sim_rid) != 0)
258 270 return (IDMAP_ERR_SID);
271 + /* Note: Free sim_domsid in smb_idmap_batch_destroy */
259 272 sim->sim_domsid = smb_mem_strdup(strsid);
273 + sim->sim_idtype = idtype;
260 274
261 275 switch (idtype) {
262 276 case SMB_IDMAP_USER:
263 277 idm_stat = kidmap_batch_getuidbysid(idmaph, sim->sim_domsid,
264 278 sim->sim_rid, sim->sim_id, &sim->sim_stat);
265 279 break;
266 280
267 281 case SMB_IDMAP_GROUP:
268 282 idm_stat = kidmap_batch_getgidbysid(idmaph, sim->sim_domsid,
269 283 sim->sim_rid, sim->sim_id, &sim->sim_stat);
270 284 break;
271 285
272 286 case SMB_IDMAP_UNKNOWN:
273 287 idm_stat = kidmap_batch_getpidbysid(idmaph, sim->sim_domsid,
274 288 sim->sim_rid, sim->sim_id, &sim->sim_idtype,
275 289 &sim->sim_stat);
276 290 break;
277 291
278 292 default:
279 293 ASSERT(0);
280 294 return (IDMAP_ERR_ARG);
281 295 }
282 296
|
↓ open down ↓ |
13 lines elided |
↑ open up ↑ |
283 297 return (idm_stat);
284 298 }
285 299
286 300 /*
287 301 * smb_idmap_batch_getsid
288 302 *
289 303 * Queue a request to map the given UID/GID to a SID.
290 304 *
291 305 * sim->sim_domsid and sim->sim_rid will contain the mapping
292 306 * result upon successful process of the batched request.
307 + * Stash the type for error reporting (caller saves the ID).
293 308 */
294 309 idmap_stat
295 310 smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
296 311 uid_t id, int idtype)
297 312 {
298 313 idmap_stat idm_stat;
299 314
315 + sim->sim_idtype = idtype;
300 316 switch (idtype) {
301 317 case SMB_IDMAP_USER:
302 318 idm_stat = kidmap_batch_getsidbyuid(idmaph, id,
303 319 (const char **)&sim->sim_domsid, &sim->sim_rid,
304 320 &sim->sim_stat);
305 321 break;
306 322
307 323 case SMB_IDMAP_GROUP:
308 324 idm_stat = kidmap_batch_getsidbygid(idmaph, id,
309 325 (const char **)&sim->sim_domsid, &sim->sim_rid,
310 326 &sim->sim_stat);
311 327 break;
312 328
313 329 case SMB_IDMAP_OWNERAT:
314 330 /* Current Owner S-1-5-32-766 */
315 331 sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
316 332 sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
317 333 sim->sim_stat = IDMAP_SUCCESS;
318 334 idm_stat = IDMAP_SUCCESS;
319 335 break;
320 336
321 337 case SMB_IDMAP_GROUPAT:
322 338 /* Current Group S-1-5-32-767 */
323 339 sim->sim_domsid = NT_BUILTIN_DOMAIN_SIDSTR;
324 340 sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
325 341 sim->sim_stat = IDMAP_SUCCESS;
326 342 idm_stat = IDMAP_SUCCESS;
327 343 break;
328 344
329 345 case SMB_IDMAP_EVERYONE:
330 346 /* Everyone S-1-1-0 */
331 347 sim->sim_domsid = NT_WORLD_AUTH_SIDSTR;
332 348 sim->sim_rid = 0;
333 349 sim->sim_stat = IDMAP_SUCCESS;
334 350 idm_stat = IDMAP_SUCCESS;
|
↓ open down ↓ |
25 lines elided |
↑ open up ↑ |
335 351 break;
336 352
337 353 default:
338 354 ASSERT(0);
339 355 return (IDMAP_ERR_ARG);
340 356 }
341 357
342 358 return (idm_stat);
343 359 }
344 360
361 +static void
362 +smb_idmap_bgm_report(smb_idmap_batch_t *sib, smb_idmap_t *sim)
363 +{
364 +
365 + if ((sib->sib_flags & SMB_IDMAP_ID2SID) != 0) {
366 + /*
367 + * Note: The ID and type we asked idmap to map
368 + * were saved in *sim_id and sim_idtype.
369 + */
370 + uint_t id = (sim->sim_id == NULL) ?
371 + 0 : (uint_t)*sim->sim_id;
372 + cmn_err(CE_WARN, "Can't get SID for "
373 + "ID=%u type=%d, status=%d",
374 + id, sim->sim_idtype, sim->sim_stat);
375 + }
376 +
377 + if ((sib->sib_flags & SMB_IDMAP_SID2ID) != 0) {
378 + cmn_err(CE_WARN, "Can't get ID for SID %s-%u, status=%d",
379 + sim->sim_domsid, sim->sim_rid, sim->sim_stat);
380 + }
381 +}
382 +
345 383 /*
346 384 * smb_idmap_batch_getmappings
347 385 *
348 386 * trigger ID mapping service to get the mappings for queued
349 387 * requests.
350 388 *
351 389 * Checks the result of all the queued requests.
352 390 * If this is a Solaris -> Windows mapping it generates
353 391 * binary SIDs from returned (domsid, rid) pairs.
354 392 */
355 393 idmap_stat
356 394 smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
357 395 {
358 396 idmap_stat idm_stat = IDMAP_SUCCESS;
397 + smb_idmap_t *sim;
359 398 int i;
360 399
361 400 idm_stat = kidmap_get_mappings(sib->sib_idmaph);
362 401 if (idm_stat != IDMAP_SUCCESS)
363 402 return (idm_stat);
364 403
365 404 /*
366 405 * Check the status for all the queued requests
367 406 */
368 - for (i = 0; i < sib->sib_nmap; i++) {
369 - if (sib->sib_maps[i].sim_stat != IDMAP_SUCCESS)
370 - return (sib->sib_maps[i].sim_stat);
407 + for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
408 + if (sim->sim_stat != IDMAP_SUCCESS) {
409 + smb_idmap_bgm_report(sib, sim);
410 + if ((sib->sib_flags & SMB_IDMAP_SKIP_ERRS) == 0) {
411 + return (sim->sim_stat);
412 + }
413 + }
371 414 }
372 415
373 416 if (smb_idmap_batch_binsid(sib) != 0)
374 417 idm_stat = IDMAP_ERR_OTHER;
375 418
376 419 return (idm_stat);
377 420 }
378 421
379 422 /*
380 423 * smb_idmap_batch_binsid
381 424 *
382 425 * Convert sidrids to binary sids
383 426 *
384 427 * Returns 0 if successful and non-zero upon failure.
385 428 */
386 429 static int
387 430 smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
388 431 {
|
↓ open down ↓ |
8 lines elided |
↑ open up ↑ |
389 432 smb_sid_t *sid;
390 433 smb_idmap_t *sim;
391 434 int i;
392 435
393 436 if (sib->sib_flags & SMB_IDMAP_SID2ID)
394 437 /* This operation is not required */
395 438 return (0);
396 439
397 440 sim = sib->sib_maps;
398 441 for (i = 0; i < sib->sib_nmap; sim++, i++) {
399 - ASSERT(sim->sim_domsid);
442 + ASSERT(sim->sim_domsid != NULL);
400 443 if (sim->sim_domsid == NULL)
401 444 return (1);
402 445
403 446 if ((sid = smb_sid_fromstr(sim->sim_domsid)) == NULL)
404 447 return (1);
405 448
406 449 sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
407 450 smb_sid_free(sid);
408 451 }
409 452
410 453 return (0);
411 454 }
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX