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 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)
35 * There are enough differences (relative to the code size)
36 * that it's more trouble than it's worth to merge them.
38 * This one differs from the others in that it:
39 * calls idmap interfaces (libidmap)
40 * uses kmem_... interfaces (libfakekernel)
41 * uses cmn_err instead of syslog, etc.
44 #include <sys/param.h>
45 #include <sys/types.h>
47 #include <smbsrv/smb_kproto.h>
48 #include <smbsrv/smb_idmap.h>
50 static int smb_idmap_batch_binsid(smb_idmap_batch_t
*sib
);
53 * Report an idmap error.
56 smb_idmap_check(const char *s
, idmap_stat stat
)
58 if (stat
!= IDMAP_SUCCESS
) {
60 s
= "smb_idmap_check";
62 cmn_err(CE_NOTE
, "%s: %d", s
, (int)stat
);
69 * Tries to get a mapping for the given uid/gid
70 * Allocates ->sim_domsid
73 smb_idmap_getsid(uid_t id
, int idtype
, smb_sid_t
**sid
)
75 smb_idmap_batch_t sib
;
78 stat
= smb_idmap_batch_create(&sib
, 1, SMB_IDMAP_ID2SID
);
79 if (stat
!= IDMAP_SUCCESS
)
82 stat
= smb_idmap_batch_getsid(sib
.sib_idmaph
, &sib
.sib_maps
[0],
85 if (stat
!= IDMAP_SUCCESS
) {
86 smb_idmap_batch_destroy(&sib
);
90 stat
= smb_idmap_batch_getmappings(&sib
);
92 if (stat
!= IDMAP_SUCCESS
) {
93 smb_idmap_batch_destroy(&sib
);
97 *sid
= smb_sid_dup(sib
.sib_maps
[0].sim_sid
);
99 smb_idmap_batch_destroy(&sib
);
101 return (IDMAP_SUCCESS
);
107 * Tries to get a mapping for the given SID
110 smb_idmap_getid(smb_sid_t
*sid
, uid_t
*id
, int *id_type
)
112 smb_idmap_batch_t sib
;
116 stat
= smb_idmap_batch_create(&sib
, 1, SMB_IDMAP_SID2ID
);
117 if (stat
!= IDMAP_SUCCESS
)
120 sim
= &sib
.sib_maps
[0];
122 stat
= smb_idmap_batch_getid(sib
.sib_idmaph
, sim
, sid
, *id_type
);
123 if (stat
!= IDMAP_SUCCESS
) {
124 smb_idmap_batch_destroy(&sib
);
128 stat
= smb_idmap_batch_getmappings(&sib
);
130 if (stat
!= IDMAP_SUCCESS
) {
131 smb_idmap_batch_destroy(&sib
);
135 *id_type
= sim
->sim_idtype
;
136 smb_idmap_batch_destroy(&sib
);
138 return (IDMAP_SUCCESS
);
142 * smb_idmap_batch_create
144 * Creates and initializes the context for batch ID mapping.
147 smb_idmap_batch_create(smb_idmap_batch_t
*sib
, uint16_t nmap
, int flags
)
152 return (IDMAP_ERR_ARG
);
154 bzero(sib
, sizeof (smb_idmap_batch_t
));
155 stat
= idmap_get_create(&sib
->sib_idmaph
);
157 if (stat
!= IDMAP_SUCCESS
) {
158 smb_idmap_check("idmap_get_create", stat
);
162 sib
->sib_flags
= flags
;
163 sib
->sib_nmap
= nmap
;
164 sib
->sib_size
= nmap
* sizeof (smb_idmap_t
);
165 sib
->sib_maps
= kmem_zalloc(sib
->sib_size
, KM_SLEEP
);
167 return (IDMAP_SUCCESS
);
171 * smb_idmap_batch_destroy
173 * Frees the batch ID mapping context.
176 smb_idmap_batch_destroy(smb_idmap_batch_t
*sib
)
183 if (sib
->sib_idmaph
) {
184 idmap_get_destroy(sib
->sib_idmaph
);
185 sib
->sib_idmaph
= NULL
;
188 if (sib
->sib_maps
== NULL
)
191 if (sib
->sib_flags
& SMB_IDMAP_ID2SID
) {
193 * SIDs are allocated only when mapping
196 for (i
= 0; i
< sib
->sib_nmap
; i
++) {
197 smb_sid_free(sib
->sib_maps
[i
].sim_sid
);
198 /* from strdup() in libidmap */
199 free(sib
->sib_maps
[i
].sim_domsid
);
203 if (sib
->sib_size
&& sib
->sib_maps
) {
204 kmem_free(sib
->sib_maps
, sib
->sib_size
);
205 sib
->sib_maps
= NULL
;
210 * smb_idmap_batch_getid
212 * Queue a request to map the given SID to a UID or GID.
214 * sim->sim_id should point to variable that's supposed to
215 * hold the returned UID/GID. This needs to be setup by caller
217 * If requested ID type is known, it's passed as 'idtype',
218 * if it's unknown it'll be returned in sim->sim_idtype.
221 smb_idmap_batch_getid(idmap_get_handle_t
*idmaph
, smb_idmap_t
*sim
,
222 smb_sid_t
*sid
, int idtype
)
224 char sidstr
[SMB_SID_STRSZ
];
228 if (idmaph
== NULL
|| sim
== NULL
|| sid
== NULL
)
229 return (IDMAP_ERR_ARG
);
231 smb_sid_tostr(sid
, sidstr
);
232 if (smb_sid_splitstr(sidstr
, &sim
->sim_rid
) != 0)
233 return (IDMAP_ERR_SID
);
234 sim
->sim_domsid
= sidstr
;
235 sim
->sim_idtype
= idtype
;
239 stat
= idmap_get_uidbysid(idmaph
, sim
->sim_domsid
,
240 sim
->sim_rid
, flag
, sim
->sim_id
, &sim
->sim_stat
);
241 smb_idmap_check("idmap_get_uidbysid", stat
);
244 case SMB_IDMAP_GROUP
:
245 stat
= idmap_get_gidbysid(idmaph
, sim
->sim_domsid
,
246 sim
->sim_rid
, flag
, sim
->sim_id
, &sim
->sim_stat
);
247 smb_idmap_check("idmap_get_gidbysid", stat
);
250 case SMB_IDMAP_UNKNOWN
:
251 stat
= idmap_get_pidbysid(idmaph
, sim
->sim_domsid
,
252 sim
->sim_rid
, flag
, sim
->sim_id
, &sim
->sim_idtype
,
254 smb_idmap_check("idmap_get_pidbysid", stat
);
258 stat
= IDMAP_ERR_ARG
;
262 /* This was copied by idmap_get_Xbysid. */
263 sim
->sim_domsid
= NULL
;
269 * smb_idmap_batch_getsid
271 * Queue a request to map the given UID/GID to a SID.
273 * sim->sim_domsid and sim->sim_rid will contain the mapping
274 * result upon successful process of the batched request.
275 * NB: sim_domsid allocated by strdup, here or in libidmap
278 smb_idmap_batch_getsid(idmap_get_handle_t
*idmaph
, smb_idmap_t
*sim
,
279 uid_t id
, int idtype
)
285 return (IDMAP_ERR_ARG
);
289 stat
= idmap_get_sidbyuid(idmaph
, id
, flag
,
290 &sim
->sim_domsid
, &sim
->sim_rid
, &sim
->sim_stat
);
291 smb_idmap_check("idmap_get_sidbyuid", stat
);
294 case SMB_IDMAP_GROUP
:
295 stat
= idmap_get_sidbygid(idmaph
, id
, flag
,
296 &sim
->sim_domsid
, &sim
->sim_rid
, &sim
->sim_stat
);
297 smb_idmap_check("idmap_get_sidbygid", stat
);
300 case SMB_IDMAP_OWNERAT
:
301 /* Current Owner S-1-5-32-766 */
302 sim
->sim_domsid
= strdup(NT_BUILTIN_DOMAIN_SIDSTR
);
303 sim
->sim_rid
= SECURITY_CURRENT_OWNER_RID
;
304 sim
->sim_stat
= IDMAP_SUCCESS
;
305 stat
= IDMAP_SUCCESS
;
308 case SMB_IDMAP_GROUPAT
:
309 /* Current Group S-1-5-32-767 */
310 sim
->sim_domsid
= strdup(NT_BUILTIN_DOMAIN_SIDSTR
);
311 sim
->sim_rid
= SECURITY_CURRENT_GROUP_RID
;
312 sim
->sim_stat
= IDMAP_SUCCESS
;
313 stat
= IDMAP_SUCCESS
;
316 case SMB_IDMAP_EVERYONE
:
317 /* Everyone S-1-1-0 */
318 sim
->sim_domsid
= strdup(NT_WORLD_AUTH_SIDSTR
);
320 sim
->sim_stat
= IDMAP_SUCCESS
;
321 stat
= IDMAP_SUCCESS
;
325 return (IDMAP_ERR_ARG
);
332 * smb_idmap_batch_getmappings
334 * trigger ID mapping service to get the mappings for queued
337 * Checks the result of all the queued requests.
340 smb_idmap_batch_getmappings(smb_idmap_batch_t
*sib
)
342 idmap_stat stat
= IDMAP_SUCCESS
;
346 if ((stat
= idmap_get_mappings(sib
->sib_idmaph
)) != IDMAP_SUCCESS
) {
347 smb_idmap_check("idmap_get_mappings", stat
);
352 * Check the status for all the queued requests
354 for (i
= 0, sim
= sib
->sib_maps
; i
< sib
->sib_nmap
; i
++, sim
++) {
355 if (sim
->sim_stat
!= IDMAP_SUCCESS
) {
356 if (sib
->sib_flags
== SMB_IDMAP_SID2ID
) {
357 cmn_err(CE_NOTE
, "[%d] %d (%d)",
362 return (sim
->sim_stat
);
366 if (smb_idmap_batch_binsid(sib
) != 0)
367 stat
= IDMAP_ERR_OTHER
;
373 * smb_idmap_batch_binsid
375 * Convert sidrids to binary sids
377 * Returns 0 if successful and non-zero upon failure.
380 smb_idmap_batch_binsid(smb_idmap_batch_t
*sib
)
386 if (sib
->sib_flags
& SMB_IDMAP_SID2ID
)
387 /* This operation is not required */
391 for (i
= 0; i
< sib
->sib_nmap
; sim
++, i
++) {
392 if (sim
->sim_domsid
== NULL
)
395 sid
= smb_sid_fromstr(sim
->sim_domsid
);
399 sim
->sim_sid
= smb_sid_splice(sid
, sim
->sim_rid
);