/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License (the "License").
* You may not use this file except in compliance with the License.
*
* You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
* See the License for the specific language governing permissions
* and limitations under the License.
*
* When distributing Covered Code, include this CDDL HEADER in each
* file and include the License file at usr/src/OPENSOLARIS.LICENSE.
* If applicable, add the following below this CDDL HEADER, with the
* fields enclosed by brackets "[]" replaced with your own identifying
* information: Portions Copyright [yyyy] [name of copyright owner]
*
* CDDL HEADER END
*/
/*
* Copyright Milan Jurik 2012. All rights reserved.
* Copyright 2014 Nexenta Systems, Inc. All rights reserved.
* Copyright 2015 Joyent, Inc.
*/
/*
* libidmap API
*/
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <strings.h>
#include <ctype.h>
#include <dlfcn.h>
#include <libintl.h>
#include <syslog.h>
#include <assert.h>
#include "idmap_impl.h"
#include "idmap_cache.h"
static int idmap_stat2errno(idmap_stat);
static idmap_stat idmap_strdupnull(char **, const char *);
return (IDMAP_ERR_MEMORY);\
}\
return (IDMAP_ERR_MEMORY);\
}\
return (IDMAP_ERR_ARG);\
}\
return (IDMAP_ERR_ARG);\
}
/*
* Free memory allocated by libidmap API
*
* Input:
* ptr - memory to be freed
*/
void
{
}
static idmap_stat
{
if (retcode != IDMAP_SUCCESS)
return (retcode);
}
{
if (rc < 0)
return (rc);
/* xdr doesn't guarantee 0-termination of char[]: */
return (rc);
}
/*
* Sometimes the property is not set. In that case, str is set to NULL but
* otherwise IDMAP_SUCCESS is returned.
*/
{
if (rc < 0)
return (rc);
return (rc);
}
/*
* Create/Initialize handle for updates
*
* Output:
* udthandle - update handle
*/
{
return (IDMAP_ERR_ARG);
}
return (IDMAP_ERR_MEMORY);
}
return (IDMAP_SUCCESS);
}
/*
* All the updates specified by the update handle are committed
* in a single transaction. i.e either all succeed or none.
*
* Input:
* udthandle - update handle with the update requests
*
* Return value:
* Status of the commit
*/
{
return (IDMAP_ERR_ARG);
}
TIMEOUT);
if (retcode != IDMAP_SUCCESS)
goto out;
if (retcode != IDMAP_SUCCESS) {
if (udthandle->error_index < 0)
goto out;
&res.error_rule);
if (retcode != IDMAP_SUCCESS) {
goto out;
}
&res.conflict_rule);
if (retcode != IDMAP_SUCCESS) {
goto out;
}
}
out:
/* reset handle so that it can be used again */
if (retcode == IDMAP_SUCCESS) {
}
return (retcode);
}
static void
{
if (windomain)
if (winname)
if (unixname)
if (is_nt4)
*is_nt4 = 0;
if (is_user)
*is_user = -1;
if (is_wuser)
*is_wuser = -1;
if (direction)
}
static idmap_stat
{
return (IDMAP_ERR_NORESULT);
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (is_user)
if (is_wuser)
if (is_nt4)
if (direction)
return (IDMAP_SUCCESS);
return (retcode);
}
/*
* Retrieve the index of the failed batch element. error_index == -1
* indicates failure at the beginning, -2 at the end.
*
* If idmap_udt_commit didn't return error, the returned value is undefined.
*
* Return value:
* IDMAP_SUCCESS
*/
{
if (error_index)
return (IDMAP_SUCCESS);
}
/*
* Retrieve the rule which caused the batch to fail. If
* idmap_udt_commit didn't return error or if error_index is < 0, the
* retrieved rule is undefined.
*
* Return value:
* IDMAP_ERR_NORESULT if there is no error rule.
* IDMAP_SUCCESS if the rule was obtained OK.
* other error code (IDMAP_ERR_NOMEMORY etc)
*/
{
udthandle->error_index < 0)
return (IDMAP_ERR_NORESULT);
return (idmap_namerule2parts(
direction));
}
/*
* Retrieve the rule with which there was a conflict. TODO: retrieve
* the value.
*
* Return value:
* IDMAP_ERR_NORESULT if there is no error rule.
* IDMAP_SUCCESS if the rule was obtained OK.
* other error code (IDMAP_ERR_NOMEMORY etc)
*/
{
return (IDMAP_ERR_NORESULT);
}
return (idmap_namerule2parts(
direction));
}
/*
* Destroy the update handle
*/
void
{
return;
}
{
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
return (IDMAP_SUCCESS);
/* The batch should still be usable */
if (rule)
return (retcode);
}
/* ARGSUSED */
{
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
return (IDMAP_SUCCESS);
if (rule)
return (retcode);
}
/* ARGSUSED */
{
if (retcode != IDMAP_SUCCESS)
goto errout;
return (IDMAP_SUCCESS);
return (retcode);
}
/*
* Set the number of entries requested per batch by the iterator
*
* Input:
* iter - iterator
* limit - number of entries requested per batch
*/
{
return (IDMAP_ERR_ARG);
}
return (IDMAP_SUCCESS);
}
/*
* Create iterator to get name-based mapping rules
*
* Input:
* windomain - Windows domain
* is_user - user or group rules
* winname - Windows user or group name
* unixname - Unix user or group name
*
* Output:
* iter - iterator
*/
{
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
return (IDMAP_SUCCESS);
if (arg) {
}
if (tmpiter)
return (retcode);
}
/*
* Iterate through the name-based mapping rules
*
* Input:
* iter - iterator
*
* Output:
* windomain - Windows domain
* winname - Windows user or group name
* unixname - Unix user or group name
* is_nt4 - NT4 or AD
* direction - bi(0), win2unix(1), unix2win(2)
*
* Return value:
* 0 - done
* 1 - more results available
* < 0 - error
*/
{
return (IDMAP_ERR_ARG);
}
if (retcode != IDMAP_SUCCESS)
return (retcode);
return (retcode);
}
}
return (IDMAP_SUCCESS);
return (IDMAP_ERR_ARG);
}
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (is_nt4)
if (is_user)
if (is_wuser)
if (direction)
else
return (IDMAP_NEXT);
return (retcode);
}
/*
*
* Output:
* iter - iterator
*/
{
return (IDMAP_SUCCESS);
}
/*
*
* Input:
* iter - iterator
*
* Output:
* sid - SID in canonical form
* pid - UID or GID
*
* Return value:
* 0 - done
* 1 - more results available
* < 0 - error
*/
{
char *str;
if (sidprefix)
if (rid)
*rid = UINT32_MAX;
if (winname)
if (windomain)
if (unixname)
if (pid)
*pid = UINT32_MAX;
if (is_user)
*is_user = -1;
if (is_wuser)
*is_wuser = -1;
if (direction)
return (IDMAP_ERR_ARG);
}
if (retcode != IDMAP_SUCCESS)
return (retcode);
return (retcode);
}
}
return (IDMAP_SUCCESS);
return (IDMAP_ERR_ARG);
}
if (sidprefix) {
goto errout;
}
}
}
if (rid)
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
if (pid)
if (direction)
if (is_user)
if (is_wuser)
if (info) {
}
else
return (IDMAP_NEXT);
return (retcode);
}
/*
* Destroy the iterator
*/
void
{
return;
case IDMAP_LIST_NAMERULES:
break;
case IDMAP_LIST_MAPPINGS:
break;
default:
return;
};
}
}
}
/*
*
* Input:
* gh - "get mapping" handle
*/
{
/* allocate the handle */
return (IDMAP_ERR_MEMORY);
}
return (IDMAP_SUCCESS);
}
/*
* Given SID, get UID
*
* Input:
* sidprefix - SID prefix
* rid - RID
* flag - flag
*
* Output:
* stat - status of the get request
* uid - POSIX UID if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
}
/*
* Given SID, get UID
*
* Input:
* sidprefix - SID prefix
* rid - RID
* flag - flag
*
* Output:
* stat - status of the get request
* uid - POSIX UID if stat = 0
* how - mapping type if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
/* sanity checks */
return (IDMAP_ERR_ARG);
return (IDMAP_ERR_ARG);
if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
!(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
return (retcode);
}
}
/* Extend the request array and the return list */
goto errout;
/* Setup the request */
goto errout;
}
/* Setup pointers for the result */
return (IDMAP_SUCCESS);
/* Batch created so far should still be usable */
if (mapping)
return (retcode);
}
/*
* Given SID, get GID
*
* Input:
* sidprefix - SID prefix
* rid - rid
* flag - flag
*
* Output:
* stat - status of the get request
* gid - POSIX GID if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
}
/*
* Given SID, get GID
*
* Input:
* sidprefix - SID prefix
* rid - rid
* flag - flag
*
* Output:
* stat - status of the get request
* gid - POSIX GID if stat = 0
* how - mapping type if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
/* sanity checks */
return (IDMAP_ERR_ARG);
return (IDMAP_ERR_ARG);
if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
!(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
return (retcode);
}
}
/* Extend the request array and the return list */
goto errout;
/* Setup the request */
goto errout;
}
/* Setup pointers for the result */
return (IDMAP_SUCCESS);
if (mapping)
return (retcode);
}
/*
*
* Input:
* sidprefix - SID prefix
* rid - rid
* flag - flag
*
* Output:
* stat - status of the get request
* is_user - user or group
* pid - POSIX UID if stat = 0 and is_user = 1
* POSIX GID if stat = 0 and is_user = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
}
/*
*
* Input:
* sidprefix - SID prefix
* rid - rid
* flag - flag
*
* Output:
* stat - status of the get request
* is_user - user or group
* pid - POSIX UID if stat = 0 and is_user = 1
* POSIX GID if stat = 0 and is_user = 0
* how - mapping type if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
/* sanity checks */
return (IDMAP_ERR_ARG);
return (IDMAP_ERR_ARG);
if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
!(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
is_user);
return (retcode);
}
}
/* Extend the request array and the return list */
goto errout;
/* Setup the request */
goto errout;
}
/* Setup pointers for the result */
return (IDMAP_SUCCESS);
if (mapping)
return (retcode);
}
/*
* Given UID, get SID
*
* Input:
* uid - POSIX UID
* flag - flag
*
* Output:
* stat - status of the get request
* sid - SID prefix (if stat == 0)
* rid - rid
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
}
/*
* Given UID, get SID
*
* Input:
* uid - POSIX UID
* flag - flag
*
* Output:
* stat - status of the get request
* sid - SID prefix (if stat == 0)
* rid - rid
* how - mapping type if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
/* sanity checks */
return (IDMAP_ERR_ARG);
return (IDMAP_ERR_ARG);
if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
!(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
return (retcode);
}
}
/* Extend the request array and the return list */
goto errout;
/* Setup the request */
/* Setup pointers for the result */
return (IDMAP_SUCCESS);
if (mapping)
return (retcode);
}
/*
* Given GID, get SID
*
* Input:
* gid - POSIX GID
* flag - flag
*
* Output:
* stat - status of the get request
* sidprefix - SID prefix (if stat == 0)
* rid - rid
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
}
/*
* Given GID, get SID
*
* Input:
* gid - POSIX GID
* flag - flag
*
* Output:
* stat - status of the get request
* sidprefix - SID prefix (if stat == 0)
* rid - rid
* how - mapping type if stat = 0
*
* Note: The output parameters will be set by idmap_get_mappings()
*/
{
/* sanity checks */
return (IDMAP_ERR_ARG);
return (IDMAP_ERR_ARG);
if ((flag & IDMAP_REQ_FLG_USE_CACHE) &&
!(flag & IDMAP_REQ_FLG_MAPPING_INFO)) {
return (retcode);
}
}
/* Extend the request array and the return list */
goto errout;
/* Setup the request */
/* Setup pointers for the result */
return (IDMAP_SUCCESS);
if (mapping)
return (retcode);
}
/*
* Process the batched "get mapping" requests. The results (i.e.
* status and identity) will be available in the data areas
* provided by individual requests.
*/
{
int i;
int direction;
return (IDMAP_ERR_ARG);
}
TIMEOUT);
if (retcode != IDMAP_SUCCESS) {
goto out;
}
goto out;
}
continue;
}
case IDMAP_UID:
else
}
break;
case IDMAP_GID:
else
}
break;
case IDMAP_POSIXID:
break;
case IDMAP_SID:
case IDMAP_USID:
case IDMAP_GSID:
break;
}
}
else /* req_id->idtype == IDMAP_GID */
}
break;
case IDMAP_NONE:
break;
default:
break;
}
}
}
out:
return (retcode);
}
/*
* Destroy the "get mapping" handle
*/
void
{
return;
}
/*
* Get windows to unix mapping
*/
{
if (pid)
*pid = UINT32_MAX;
if (unixname)
if (direction)
} else if (winname) {
if (retcode != IDMAP_SUCCESS)
goto out;
if (retcode != IDMAP_SUCCESS)
goto out;
} else {
return (IDMAP_ERR_ARG);
}
if (*is_user == 1)
else if (*is_user == 0)
else
if (*is_wuser == 1)
else if (*is_wuser == 0)
else
TIMEOUT);
if (retcode != IDMAP_SUCCESS)
goto out;
if (retcode == IDMAP_SUCCESS)
goto out;
}
*is_user = 1;
*is_user = 0;
} else {
goto out;
}
*is_wuser = 1;
*is_wuser = 0;
} else {
goto out;
}
if (direction)
if (pid)
if (rc != IDMAP_SUCCESS)
out:
if (retcode != IDMAP_SUCCESS)
return (retcode);
}
/*
* Get unix to windows mapping
*/
{
if (sidprefix)
if (winname)
if (windomain)
if (rid)
*rid = UINT32_MAX;
if (direction)
} else if (unixname) {
} else {
return (IDMAP_ERR_ARG);
}
else if (*is_wuser == -1)
else if (*is_wuser == 0)
else if (*is_wuser == 1)
TIMEOUT);
if (retcode != IDMAP_SUCCESS)
return (retcode);
if (retcode == IDMAP_SUCCESS)
goto out;
}
*is_wuser = 1;
*is_wuser = 0;
else
*is_wuser = -1;
}
goto errout;
}
}
if (rid)
if (rc != IDMAP_SUCCESS)
if (rc != IDMAP_SUCCESS)
goto out;
}
}
}
out:
if (retcode != IDMAP_SUCCESS)
return (retcode);
}
#define gettext(s) s
gettext("Duplicate rule or conflicts with an existing "
"Windows to UNIX name-based rule"), EINVAL},
gettext("Duplicate rule or conflicts with an existing "
"Unix to Windows name-based rule"), EINVAL},
gettext("Invalid or illegal UTF-8 sequence found in "
"a given Windows entity name or domain name"), EINVAL},
gettext("Mapping not found and none created (see -c option)"),
EINVAL},
gettext("Undefined property"),
EINVAL},
gettext("No AD servers"),
EINVAL},
{-1, NULL, 0}
};
/*
* Get description of status code
*
* Input:
* status - Status code returned by libidmap API call
*
* Return Value:
* human-readable localized description of idmap_stat
*/
const char *
{
int i;
}
}
static int
{
int i;
}
return (EINVAL);
}
/*
* Get status code from string
*/
{
return (IDMAP_ERR_INTERNAL);
#define return_cmp(a) \
return (IDMAP_ERR_ ## a);
return_cmp(DB);
return (IDMAP_ERR_OTHER);
}
/*
* Map the given status to one that can be returned by the protocol
*/
{
switch (status) {
case IDMAP_ERR_MEMORY:
case IDMAP_ERR_CACHE:
return (IDMAP_ERR_INTERNAL);
}
return (status);
}
/*
* This is a convenience routine which duplicates a string after
* checking for NULL pointers. This function will return success if
* either the 'to' OR 'from' pointers are NULL.
*/
static idmap_stat
{
return (IDMAP_SUCCESS);
return (IDMAP_SUCCESS);
}
return (IDMAP_ERR_MEMORY);
return (IDMAP_SUCCESS);
}
{
return (IDMAP_SUCCESS);
if (retval != IDMAP_SUCCESS)
return (retval);
if (retval != IDMAP_SUCCESS) {
return (retval);
}
if (retval != IDMAP_SUCCESS) {
return (retval);
}
return (retval);
}
/*
* Move the contents of the "info" structure from "from" to "to".
*/
void
{
}
void
{
return;
}
void
{
}
/*
* Get uid given Windows name
*/
{
int direction;
return (IDMAP_ERR_ARG);
if (flag & IDMAP_REQ_FLG_USE_CACHE) {
return (rc);
}
/* Get mapping */
/* If we have not got the domain don't store UID to winname */
}
return (rc);
}
/*
* Get gid given Windows name
*/
{
int is_user = 0;
int direction;
return (IDMAP_ERR_ARG);
if (flag & IDMAP_REQ_FLG_USE_CACHE) {
return (rc);
}
/* Get mapping */
/* If we have not got the domain don't store GID to winname */
}
return (rc);
}
/*
* Get winname given pid
*/
char **domain)
{
int len;
int direction;
return (IDMAP_ERR_ARG);
if (flag & IDMAP_REQ_FLG_USE_CACHE) {
if (is_user)
else
if (rc == IDMAP_SUCCESS)
goto out;
if (rc == IDMAP_ERR_MEMORY)
return (rc);
}
/* Get mapping */
/* Return on error */
if (rc != IDMAP_SUCCESS)
return (rc);
/*
* The given PID may have been mapped to a locally
* generated SID in which case there isn't any
* Windows name
*/
return (IDMAP_ERR_NORESULT);
}
if (flag & IDMAP_REQ_FLG_USE_CACHE) {
if (is_user)
else
}
out:
} else {
else
}
return (rc);
}
/*
* Get winname given uid
*/
{
}
/*
* Get winname given gid
*/
{
}
{
if (rc1 != IDMAP_SUCCESS)
return (rc1);
return (rc2);
}
/*
* syslog is the default logger.
* It can be overwritten by supplying a logger
* with idmap_set_logger()
*/
void
{
}
/*
* Helper functions that concatenate two parts of a name and then
* look up a value, so that the same set of functions can be used to
* process both "in" and "out" parameters.
*/
static
{
int err;
return (err == 0);
}
static
{
int err;
return (err == 0);
}
static
void
{
char *s;
switch (i64) {
case IDMAP_POSIXID:
break;
case IDMAP_UID:
break;
case IDMAP_GID:
break;
case IDMAP_SID:
break;
case IDMAP_USID:
break;
case IDMAP_GSID:
break;
case IDMAP_NONE:
break;
default:
break;
}
}
}
void
{
char *s;
}
void
{
int err;
}
}