xref: /onnv-gate/usr/src/lib/smbsrv/libsmb/common/smb_idmap.c (revision 12914:e95332bf1454)
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