4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
23 * Copyright 2014 Nexenta Systems, Inc. All rights reserved.
27 * SMB server interface to idmap
28 * (smb_idmap_get..., smb_idmap_batch_...)
30 * There are two implementations of this interface:
31 * uts/common/fs/smbsrv/smb_idmap.c (smbsrv kmod)
32 * lib/smbsrv/libsmb/common/smb_idmap.c (libsmb)
34 * There are enough differences (relative to the code size)
35 * that it's more trouble than it's worth to merge them.
37 * This one differs from the others in that it:
38 * calls idmap interfaces (libidmap)
39 * domain SIDs returned are allocated
44 #include <smbsrv/libsmb.h>
46 static int smb_idmap_batch_binsid(smb_idmap_batch_t
*sib
);
49 * Report an idmap error.
52 smb_idmap_check(const char *s
, idmap_stat stat
)
54 if (stat
!= IDMAP_SUCCESS
) {
56 s
= "smb_idmap_check";
58 syslog(LOG_ERR
, "%s: %s", s
, idmap_stat2string(stat
));
65 * Tries to get a mapping for the given uid/gid
66 * Allocates ->sim_domsid
69 smb_idmap_getsid(uid_t id
, int idtype
, smb_sid_t
**sid
)
71 smb_idmap_batch_t sib
;
74 stat
= smb_idmap_batch_create(&sib
, 1, SMB_IDMAP_ID2SID
);
75 if (stat
!= IDMAP_SUCCESS
)
78 stat
= smb_idmap_batch_getsid(sib
.sib_idmaph
, &sib
.sib_maps
[0],
81 if (stat
!= IDMAP_SUCCESS
) {
82 smb_idmap_batch_destroy(&sib
);
86 stat
= smb_idmap_batch_getmappings(&sib
);
88 if (stat
!= IDMAP_SUCCESS
) {
89 smb_idmap_batch_destroy(&sib
);
93 *sid
= smb_sid_dup(sib
.sib_maps
[0].sim_sid
);
95 smb_idmap_batch_destroy(&sib
);
97 return (IDMAP_SUCCESS
);
103 * Tries to get a mapping for the given SID
106 smb_idmap_getid(smb_sid_t
*sid
, uid_t
*id
, int *id_type
)
108 smb_idmap_batch_t sib
;
112 stat
= smb_idmap_batch_create(&sib
, 1, SMB_IDMAP_SID2ID
);
113 if (stat
!= IDMAP_SUCCESS
)
116 sim
= &sib
.sib_maps
[0];
118 stat
= smb_idmap_batch_getid(sib
.sib_idmaph
, sim
, sid
, *id_type
);
119 if (stat
!= IDMAP_SUCCESS
) {
120 smb_idmap_batch_destroy(&sib
);
124 stat
= smb_idmap_batch_getmappings(&sib
);
126 if (stat
!= IDMAP_SUCCESS
) {
127 smb_idmap_batch_destroy(&sib
);
131 *id_type
= sim
->sim_idtype
;
132 smb_idmap_batch_destroy(&sib
);
134 return (IDMAP_SUCCESS
);
138 * smb_idmap_batch_create
140 * Creates and initializes the context for batch ID mapping.
143 smb_idmap_batch_create(smb_idmap_batch_t
*sib
, uint16_t nmap
, int flags
)
148 return (IDMAP_ERR_ARG
);
150 bzero(sib
, sizeof (smb_idmap_batch_t
));
151 stat
= idmap_get_create(&sib
->sib_idmaph
);
153 if (stat
!= IDMAP_SUCCESS
) {
154 smb_idmap_check("idmap_get_create", stat
);
158 sib
->sib_flags
= flags
;
159 sib
->sib_nmap
= nmap
;
160 sib
->sib_size
= nmap
* sizeof (smb_idmap_t
);
161 sib
->sib_maps
= malloc(sib
->sib_size
);
163 return (IDMAP_ERR_MEMORY
);
165 bzero(sib
->sib_maps
, sib
->sib_size
);
166 return (IDMAP_SUCCESS
);
170 * smb_idmap_batch_destroy
172 * Frees the batch ID mapping context.
175 smb_idmap_batch_destroy(smb_idmap_batch_t
*sib
)
182 if (sib
->sib_idmaph
) {
183 idmap_get_destroy(sib
->sib_idmaph
);
184 sib
->sib_idmaph
= NULL
;
187 if (sib
->sib_maps
== NULL
)
190 if (sib
->sib_flags
& SMB_IDMAP_ID2SID
) {
192 * SIDs are allocated only when mapping
195 for (i
= 0; i
< sib
->sib_nmap
; i
++) {
196 smb_sid_free(sib
->sib_maps
[i
].sim_sid
);
197 free(sib
->sib_maps
[i
].sim_domsid
);
201 if (sib
->sib_size
&& sib
->sib_maps
) {
203 sib
->sib_maps
= NULL
;
208 * smb_idmap_batch_getid
210 * Queue a request to map the given SID to a UID or GID.
212 * sim->sim_id should point to variable that's supposed to
213 * hold the returned UID/GID. This needs to be setup by caller
215 * If requested ID type is known, it's passed as 'idtype',
216 * if it's unknown it'll be returned in sim->sim_idtype.
219 smb_idmap_batch_getid(idmap_get_handle_t
*idmaph
, smb_idmap_t
*sim
,
220 smb_sid_t
*sid
, int idtype
)
222 char sidstr
[SMB_SID_STRSZ
];
226 if (idmaph
== NULL
|| sim
== NULL
|| sid
== NULL
)
227 return (IDMAP_ERR_ARG
);
229 smb_sid_tostr(sid
, sidstr
);
230 if (smb_sid_splitstr(sidstr
, &sim
->sim_rid
) != 0)
231 return (IDMAP_ERR_SID
);
232 sim
->sim_domsid
= sidstr
;
233 sim
->sim_idtype
= idtype
;
237 stat
= idmap_get_uidbysid(idmaph
, sim
->sim_domsid
,
238 sim
->sim_rid
, flag
, sim
->sim_id
, &sim
->sim_stat
);
239 smb_idmap_check("idmap_get_uidbysid", stat
);
242 case SMB_IDMAP_GROUP
:
243 stat
= idmap_get_gidbysid(idmaph
, sim
->sim_domsid
,
244 sim
->sim_rid
, flag
, sim
->sim_id
, &sim
->sim_stat
);
245 smb_idmap_check("idmap_get_gidbysid", stat
);
248 case SMB_IDMAP_UNKNOWN
:
249 stat
= idmap_get_pidbysid(idmaph
, sim
->sim_domsid
,
250 sim
->sim_rid
, flag
, sim
->sim_id
, &sim
->sim_idtype
,
252 smb_idmap_check("idmap_get_pidbysid", stat
);
256 stat
= IDMAP_ERR_ARG
;
260 /* This was copied by idmap_get_Xbysid. */
261 sim
->sim_domsid
= NULL
;
267 * smb_idmap_batch_getsid
269 * Queue a request to map the given UID/GID to a SID.
271 * sim->sim_domsid and sim->sim_rid will contain the mapping
272 * result upon successful process of the batched request.
273 * NB: sim_domsid allocated by strdup, here or in libidmap
276 smb_idmap_batch_getsid(idmap_get_handle_t
*idmaph
, smb_idmap_t
*sim
,
277 uid_t id
, int idtype
)
283 return (IDMAP_ERR_ARG
);
287 stat
= idmap_get_sidbyuid(idmaph
, id
, flag
,
288 &sim
->sim_domsid
, &sim
->sim_rid
, &sim
->sim_stat
);
289 smb_idmap_check("idmap_get_sidbyuid", stat
);
292 case SMB_IDMAP_GROUP
:
293 stat
= idmap_get_sidbygid(idmaph
, id
, flag
,
294 &sim
->sim_domsid
, &sim
->sim_rid
, &sim
->sim_stat
);
295 smb_idmap_check("idmap_get_sidbygid", stat
);
298 case SMB_IDMAP_OWNERAT
:
299 /* Current Owner S-1-5-32-766 */
300 sim
->sim_domsid
= strdup(NT_BUILTIN_DOMAIN_SIDSTR
);
301 sim
->sim_rid
= SECURITY_CURRENT_OWNER_RID
;
302 sim
->sim_stat
= IDMAP_SUCCESS
;
303 stat
= IDMAP_SUCCESS
;
306 case SMB_IDMAP_GROUPAT
:
307 /* Current Group S-1-5-32-767 */
308 sim
->sim_domsid
= strdup(NT_BUILTIN_DOMAIN_SIDSTR
);
309 sim
->sim_rid
= SECURITY_CURRENT_GROUP_RID
;
310 sim
->sim_stat
= IDMAP_SUCCESS
;
311 stat
= IDMAP_SUCCESS
;
314 case SMB_IDMAP_EVERYONE
:
315 /* Everyone S-1-1-0 */
316 sim
->sim_domsid
= strdup(NT_WORLD_AUTH_SIDSTR
);
318 sim
->sim_stat
= IDMAP_SUCCESS
;
319 stat
= IDMAP_SUCCESS
;
323 return (IDMAP_ERR_ARG
);
330 * smb_idmap_batch_getmappings
332 * trigger ID mapping service to get the mappings for queued
335 * Checks the result of all the queued requests.
338 smb_idmap_batch_getmappings(smb_idmap_batch_t
*sib
)
340 idmap_stat stat
= IDMAP_SUCCESS
;
344 if ((stat
= idmap_get_mappings(sib
->sib_idmaph
)) != IDMAP_SUCCESS
) {
345 smb_idmap_check("idmap_get_mappings", stat
);
350 * Check the status for all the queued requests
352 for (i
= 0, sim
= sib
->sib_maps
; i
< sib
->sib_nmap
; i
++, sim
++) {
353 if (sim
->sim_stat
!= IDMAP_SUCCESS
) {
354 if (sib
->sib_flags
== SMB_IDMAP_SID2ID
) {
355 smb_tracef("[%d] %d (%d)", sim
->sim_idtype
,
356 sim
->sim_rid
, sim
->sim_stat
);
358 return (sim
->sim_stat
);
362 if (smb_idmap_batch_binsid(sib
) != 0)
363 stat
= IDMAP_ERR_OTHER
;
369 * smb_idmap_batch_binsid
371 * Convert sidrids to binary sids
373 * Returns 0 if successful and non-zero upon failure.
376 smb_idmap_batch_binsid(smb_idmap_batch_t
*sib
)
382 if (sib
->sib_flags
& SMB_IDMAP_SID2ID
)
383 /* This operation is not required */
387 for (i
= 0; i
< sib
->sib_nmap
; sim
++, i
++) {
388 if (sim
->sim_domsid
== NULL
)
391 sid
= smb_sid_fromstr(sim
->sim_domsid
);
395 sim
->sim_sid
= smb_sid_splice(sid
, sim
->sim_rid
);