15331Samw /*
25331Samw * CDDL HEADER START
35331Samw *
45331Samw * The contents of this file are subject to the terms of the
55331Samw * Common Development and Distribution License (the "License").
65331Samw * You may not use this file except in compliance with the License.
75331Samw *
85331Samw * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
95331Samw * or http://www.opensolaris.org/os/licensing.
105331Samw * See the License for the specific language governing permissions
115331Samw * and limitations under the License.
125331Samw *
135331Samw * When distributing Covered Code, include this CDDL HEADER in each
145331Samw * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
155331Samw * If applicable, add the following below this CDDL HEADER, with the
165331Samw * fields enclosed by brackets "[]" replaced with your own identifying
175331Samw * information: Portions Copyright [yyyy] [name of copyright owner]
185331Samw *
195331Samw * CDDL HEADER END
205331Samw */
215331Samw /*
22*12914SJoyce.McIntosh@Sun.COM * Copyright (c) 2007, 2010, Oracle and/or its affiliates. All rights reserved.
235331Samw */
245331Samw
2511963SAfshin.Ardakani@Sun.COM #include <syslog.h>
265331Samw #include <strings.h>
275331Samw #include <smbsrv/libsmb.h>
285331Samw
295331Samw static int smb_idmap_batch_binsid(smb_idmap_batch_t *sib);
305331Samw
315331Samw /*
32*12914SJoyce.McIntosh@Sun.COM * Report an idmap error.
335331Samw */
345331Samw void
smb_idmap_check(const char * s,idmap_stat stat)3511963SAfshin.Ardakani@Sun.COM smb_idmap_check(const char *s, idmap_stat stat)
365331Samw {
3711963SAfshin.Ardakani@Sun.COM if (stat != IDMAP_SUCCESS) {
3811963SAfshin.Ardakani@Sun.COM if (s == NULL)
3911963SAfshin.Ardakani@Sun.COM s = "smb_idmap_check";
4011963SAfshin.Ardakani@Sun.COM
41*12914SJoyce.McIntosh@Sun.COM syslog(LOG_ERR, "%s: %s", s, idmap_stat2string(stat));
425331Samw }
435331Samw }
445331Samw
455331Samw /*
465331Samw * smb_idmap_getsid
475331Samw *
485331Samw * Tries to get a mapping for the given uid/gid
495331Samw */
505331Samw idmap_stat
smb_idmap_getsid(uid_t id,int idtype,smb_sid_t ** sid)516432Sas200622 smb_idmap_getsid(uid_t id, int idtype, smb_sid_t **sid)
525331Samw {
535331Samw smb_idmap_batch_t sib;
545331Samw idmap_stat stat;
555331Samw
565331Samw stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_ID2SID);
575331Samw if (stat != IDMAP_SUCCESS)
585331Samw return (stat);
595331Samw
605331Samw stat = smb_idmap_batch_getsid(sib.sib_idmaph, &sib.sib_maps[0],
615331Samw id, idtype);
625331Samw
635331Samw if (stat != IDMAP_SUCCESS) {
645331Samw smb_idmap_batch_destroy(&sib);
655331Samw return (stat);
665331Samw }
675331Samw
685331Samw stat = smb_idmap_batch_getmappings(&sib);
695331Samw
705331Samw if (stat != IDMAP_SUCCESS) {
715331Samw smb_idmap_batch_destroy(&sib);
725331Samw return (stat);
735331Samw }
745331Samw
756432Sas200622 *sid = smb_sid_dup(sib.sib_maps[0].sim_sid);
765331Samw
775331Samw smb_idmap_batch_destroy(&sib);
785331Samw
795331Samw return (IDMAP_SUCCESS);
805331Samw }
815331Samw
825331Samw /*
835772Sas200622 * smb_idmap_getid
845772Sas200622 *
855772Sas200622 * Tries to get a mapping for the given SID
865772Sas200622 */
875772Sas200622 idmap_stat
smb_idmap_getid(smb_sid_t * sid,uid_t * id,int * id_type)886432Sas200622 smb_idmap_getid(smb_sid_t *sid, uid_t *id, int *id_type)
895772Sas200622 {
905772Sas200622 smb_idmap_batch_t sib;
915772Sas200622 smb_idmap_t *sim;
925772Sas200622 idmap_stat stat;
935772Sas200622
945772Sas200622 stat = smb_idmap_batch_create(&sib, 1, SMB_IDMAP_SID2ID);
955772Sas200622 if (stat != IDMAP_SUCCESS)
965772Sas200622 return (stat);
975772Sas200622
985772Sas200622 sim = &sib.sib_maps[0];
995772Sas200622 sim->sim_id = id;
1005772Sas200622 stat = smb_idmap_batch_getid(sib.sib_idmaph, sim, sid, *id_type);
1015772Sas200622 if (stat != IDMAP_SUCCESS) {
1025772Sas200622 smb_idmap_batch_destroy(&sib);
1035772Sas200622 return (stat);
1045772Sas200622 }
1055772Sas200622
1065772Sas200622 stat = smb_idmap_batch_getmappings(&sib);
1075772Sas200622
1085772Sas200622 if (stat != IDMAP_SUCCESS) {
1095772Sas200622 smb_idmap_batch_destroy(&sib);
1105772Sas200622 return (stat);
1115772Sas200622 }
1125772Sas200622
1135772Sas200622 *id_type = sim->sim_idtype;
1145772Sas200622 smb_idmap_batch_destroy(&sib);
1155772Sas200622
1165772Sas200622 return (IDMAP_SUCCESS);
1175772Sas200622 }
1185772Sas200622
1195772Sas200622 /*
1205331Samw * smb_idmap_batch_create
1215331Samw *
1225331Samw * Creates and initializes the context for batch ID mapping.
1235331Samw */
1245331Samw idmap_stat
smb_idmap_batch_create(smb_idmap_batch_t * sib,uint16_t nmap,int flags)1255331Samw smb_idmap_batch_create(smb_idmap_batch_t *sib, uint16_t nmap, int flags)
1265331Samw {
12711963SAfshin.Ardakani@Sun.COM idmap_stat stat;
1285331Samw
1295331Samw if (!sib)
1305331Samw return (IDMAP_ERR_ARG);
1315331Samw
1325331Samw bzero(sib, sizeof (smb_idmap_batch_t));
133*12914SJoyce.McIntosh@Sun.COM stat = idmap_get_create(&sib->sib_idmaph);
1348334SJose.Borrego@Sun.COM
13511963SAfshin.Ardakani@Sun.COM if (stat != IDMAP_SUCCESS) {
13611963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_create", stat);
1375331Samw return (stat);
13811963SAfshin.Ardakani@Sun.COM }
1395331Samw
1405331Samw sib->sib_flags = flags;
1415331Samw sib->sib_nmap = nmap;
1425331Samw sib->sib_size = nmap * sizeof (smb_idmap_t);
1435331Samw sib->sib_maps = malloc(sib->sib_size);
1445331Samw if (!sib->sib_maps)
1455331Samw return (IDMAP_ERR_MEMORY);
1465331Samw
1475331Samw bzero(sib->sib_maps, sib->sib_size);
1485331Samw return (IDMAP_SUCCESS);
1495331Samw }
1505331Samw
1515331Samw /*
1525331Samw * smb_idmap_batch_destroy
1535331Samw *
1545331Samw * Frees the batch ID mapping context.
1555331Samw */
1565331Samw void
smb_idmap_batch_destroy(smb_idmap_batch_t * sib)1575331Samw smb_idmap_batch_destroy(smb_idmap_batch_t *sib)
1585331Samw {
1595331Samw int i;
1605331Samw
1616432Sas200622 if (sib == NULL)
1625331Samw return;
1635331Samw
1645331Samw if (sib->sib_idmaph) {
1655331Samw idmap_get_destroy(sib->sib_idmaph);
1665331Samw sib->sib_idmaph = NULL;
1675331Samw }
1685331Samw
1696432Sas200622 if (sib->sib_maps == NULL)
1705331Samw return;
1715331Samw
1725772Sas200622 if (sib->sib_flags & SMB_IDMAP_ID2SID) {
1735331Samw /*
1745331Samw * SIDs are allocated only when mapping
1755331Samw * UID/GID to SIDs
1765331Samw */
1776432Sas200622 for (i = 0; i < sib->sib_nmap; i++)
1786432Sas200622 smb_sid_free(sib->sib_maps[i].sim_sid);
1795331Samw }
1805331Samw
1815331Samw if (sib->sib_size && sib->sib_maps) {
1825331Samw free(sib->sib_maps);
1835331Samw sib->sib_maps = NULL;
1845331Samw }
1855331Samw }
1865331Samw
1875331Samw /*
1885331Samw * smb_idmap_batch_getid
1895331Samw *
1905331Samw * Queue a request to map the given SID to a UID or GID.
1915331Samw *
1925331Samw * sim->sim_id should point to variable that's supposed to
1935331Samw * hold the returned UID/GID. This needs to be setup by caller
1945331Samw * of this function.
1955331Samw * If requested ID type is known, it's passed as 'idtype',
1965331Samw * if it's unknown it'll be returned in sim->sim_idtype.
1975331Samw */
1985331Samw idmap_stat
smb_idmap_batch_getid(idmap_get_handle_t * idmaph,smb_idmap_t * sim,smb_sid_t * sid,int idtype)1995331Samw smb_idmap_batch_getid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
2006432Sas200622 smb_sid_t *sid, int idtype)
2015331Samw {
2026432Sas200622 char sidstr[SMB_SID_STRSZ];
2036432Sas200622 smb_sid_t *tmpsid;
2045331Samw idmap_stat stat;
2055331Samw int flag = 0;
2065331Samw
2078670SJose.Borrego@Sun.COM if (idmaph == NULL || sim == NULL || sid == NULL)
2085331Samw return (IDMAP_ERR_ARG);
2095331Samw
2108670SJose.Borrego@Sun.COM if ((tmpsid = smb_sid_split(sid, &sim->sim_rid)) == NULL)
2115331Samw return (IDMAP_ERR_MEMORY);
2125331Samw
2136432Sas200622 smb_sid_tostr(tmpsid, sidstr);
2146432Sas200622 sim->sim_domsid = sidstr;
21511963SAfshin.Ardakani@Sun.COM sim->sim_idtype = idtype;
2166432Sas200622 smb_sid_free(tmpsid);
2175331Samw
2185331Samw switch (idtype) {
2195331Samw case SMB_IDMAP_USER:
2205331Samw stat = idmap_get_uidbysid(idmaph, sim->sim_domsid,
2215331Samw sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
22211963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_uidbysid", stat);
2235331Samw break;
2245331Samw
2255331Samw case SMB_IDMAP_GROUP:
2265331Samw stat = idmap_get_gidbysid(idmaph, sim->sim_domsid,
2275331Samw sim->sim_rid, flag, sim->sim_id, &sim->sim_stat);
22811963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_gidbysid", stat);
2295331Samw break;
2305331Samw
2315331Samw case SMB_IDMAP_UNKNOWN:
2325331Samw stat = idmap_get_pidbysid(idmaph, sim->sim_domsid,
2335331Samw sim->sim_rid, flag, sim->sim_id, &sim->sim_idtype,
2345331Samw &sim->sim_stat);
23511963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_pidbysid", stat);
2365331Samw break;
2375331Samw
2385331Samw default:
2395331Samw return (IDMAP_ERR_ARG);
2405331Samw }
2415331Samw
2425331Samw return (stat);
2435331Samw }
2445331Samw
2455331Samw /*
2465331Samw * smb_idmap_batch_getsid
2475331Samw *
2485331Samw * Queue a request to map the given UID/GID to a SID.
2495331Samw *
2505331Samw * sim->sim_domsid and sim->sim_rid will contain the mapping
2515331Samw * result upon successful process of the batched request.
2525331Samw */
2535331Samw idmap_stat
smb_idmap_batch_getsid(idmap_get_handle_t * idmaph,smb_idmap_t * sim,uid_t id,int idtype)2545331Samw smb_idmap_batch_getsid(idmap_get_handle_t *idmaph, smb_idmap_t *sim,
2555331Samw uid_t id, int idtype)
2565331Samw {
2575331Samw idmap_stat stat;
2585331Samw int flag = 0;
2595331Samw
2605331Samw if (!idmaph || !sim)
2615331Samw return (IDMAP_ERR_ARG);
2625331Samw
2635331Samw switch (idtype) {
2645331Samw case SMB_IDMAP_USER:
2655331Samw stat = idmap_get_sidbyuid(idmaph, id, flag,
2665331Samw &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
26711963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_sidbyuid", stat);
2685331Samw break;
2695331Samw
2705331Samw case SMB_IDMAP_GROUP:
2715331Samw stat = idmap_get_sidbygid(idmaph, id, flag,
2725331Samw &sim->sim_domsid, &sim->sim_rid, &sim->sim_stat);
27311963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_sidbygid", stat);
2745331Samw break;
2755331Samw
27611447Samw@Sun.COM case SMB_IDMAP_OWNERAT:
27711447Samw@Sun.COM /* Current Owner S-1-5-32-766 */
27811447Samw@Sun.COM sim->sim_domsid = strdup(NT_BUILTIN_DOMAIN_SIDSTR);
27911447Samw@Sun.COM sim->sim_rid = SECURITY_CURRENT_OWNER_RID;
28011447Samw@Sun.COM sim->sim_stat = IDMAP_SUCCESS;
28111447Samw@Sun.COM stat = IDMAP_SUCCESS;
28211447Samw@Sun.COM break;
28311447Samw@Sun.COM
28411447Samw@Sun.COM case SMB_IDMAP_GROUPAT:
28511447Samw@Sun.COM /* Current Group S-1-5-32-767 */
28611447Samw@Sun.COM sim->sim_domsid = strdup(NT_BUILTIN_DOMAIN_SIDSTR);
28711447Samw@Sun.COM sim->sim_rid = SECURITY_CURRENT_GROUP_RID;
28811447Samw@Sun.COM sim->sim_stat = IDMAP_SUCCESS;
28911447Samw@Sun.COM stat = IDMAP_SUCCESS;
29011447Samw@Sun.COM break;
29111447Samw@Sun.COM
2925331Samw case SMB_IDMAP_EVERYONE:
2935331Samw /* Everyone S-1-1-0 */
29411447Samw@Sun.COM sim->sim_domsid = strdup(NT_WORLD_AUTH_SIDSTR);
2955331Samw sim->sim_rid = 0;
2965331Samw sim->sim_stat = IDMAP_SUCCESS;
2975331Samw stat = IDMAP_SUCCESS;
2985331Samw break;
2995331Samw
3005331Samw default:
3015331Samw return (IDMAP_ERR_ARG);
3025331Samw }
3035331Samw
3045331Samw return (stat);
3055331Samw }
3065331Samw
3075331Samw /*
3085331Samw * smb_idmap_batch_getmappings
3095331Samw *
3105331Samw * trigger ID mapping service to get the mappings for queued
3115331Samw * requests.
3125331Samw *
3135331Samw * Checks the result of all the queued requests.
3145331Samw */
3155331Samw idmap_stat
smb_idmap_batch_getmappings(smb_idmap_batch_t * sib)3165331Samw smb_idmap_batch_getmappings(smb_idmap_batch_t *sib)
3175331Samw {
3185331Samw idmap_stat stat = IDMAP_SUCCESS;
3197619SJose.Borrego@Sun.COM smb_idmap_t *sim;
3205331Samw int i;
3215331Samw
32211963SAfshin.Ardakani@Sun.COM if ((stat = idmap_get_mappings(sib->sib_idmaph)) != IDMAP_SUCCESS) {
32311963SAfshin.Ardakani@Sun.COM smb_idmap_check("idmap_get_mappings", stat);
3245331Samw return (stat);
32511963SAfshin.Ardakani@Sun.COM }
3265331Samw
3275331Samw /*
3285331Samw * Check the status for all the queued requests
3295331Samw */
3307619SJose.Borrego@Sun.COM for (i = 0, sim = sib->sib_maps; i < sib->sib_nmap; i++, sim++) {
3317619SJose.Borrego@Sun.COM if (sim->sim_stat != IDMAP_SUCCESS) {
3327619SJose.Borrego@Sun.COM if (sib->sib_flags == SMB_IDMAP_SID2ID) {
3339832Samw@Sun.COM smb_tracef("[%d] %d (%d)", sim->sim_idtype,
3347619SJose.Borrego@Sun.COM sim->sim_rid, sim->sim_stat);
3357619SJose.Borrego@Sun.COM }
3367619SJose.Borrego@Sun.COM return (sim->sim_stat);
3375331Samw }
3385331Samw }
3395331Samw
3407619SJose.Borrego@Sun.COM if (smb_idmap_batch_binsid(sib) != 0)
3415331Samw stat = IDMAP_ERR_OTHER;
3425331Samw
3435331Samw return (stat);
3445331Samw }
3455331Samw
3465331Samw /*
3475331Samw * smb_idmap_batch_binsid
3485331Samw *
3495331Samw * Convert sidrids to binary sids
3505331Samw *
3515331Samw * Returns 0 if successful and non-zero upon failure.
3525331Samw */
3535331Samw static int
smb_idmap_batch_binsid(smb_idmap_batch_t * sib)3545331Samw smb_idmap_batch_binsid(smb_idmap_batch_t *sib)
3555331Samw {
3566432Sas200622 smb_sid_t *sid;
3575331Samw smb_idmap_t *sim;
3585331Samw int i;
3595331Samw
3605331Samw if (sib->sib_flags & SMB_IDMAP_SID2ID)
3615331Samw /* This operation is not required */
3625331Samw return (0);
3635331Samw
3645331Samw sim = sib->sib_maps;
3655331Samw for (i = 0; i < sib->sib_nmap; sim++, i++) {
3665331Samw if (sim->sim_domsid == NULL)
3675331Samw return (-1);
3685331Samw
3696432Sas200622 sid = smb_sid_fromstr(sim->sim_domsid);
3705772Sas200622 free(sim->sim_domsid);
3715331Samw if (sid == NULL)
3725331Samw return (-1);
3735331Samw
3746432Sas200622 sim->sim_sid = smb_sid_splice(sid, sim->sim_rid);
3755331Samw free(sid);
3765331Samw }
3775331Samw
3785331Samw return (0);
3795331Samw }
380