idmap_api.c revision 61b364a9162c5e321625fcd2f640da7e1dd2417e
/*
* 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 2008 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* libidmap API
*/
#include <stdlib.h>
#include <inttypes.h>
#include <errno.h>
#include <strings.h>
#include <ctype.h>
#include <dlfcn.h>
#include <libintl.h>
#include <ucontext.h>
#include "idmap_impl.h"
/*LINTLIBRARY*/
/*
* The following structure determines where the log messages from idmapdlog()
*
* logstate.max_pri is integer cutoff necessary to silence low-priority
* messages to stderr. Syslog has its own means so there a boolean
* logstate.write_syslog is enough.
*
* logstate.degraded is a mode used by idmapd in its degraded state.
*/
static struct {
int max_pri; /* Max priority written to stderr */
static int idmap_stat2errno(idmap_stat);
static idmap_stat idmap_strdupnull(char **, const char *);
return (IDMAP_ERR_ARG);\
}\
return (IDMAP_ERR_MEMORY);\
}\
return (IDMAP_ERR_MEMORY);\
}\
if (argu) {\
}\
if (itera)\
return (iretcod);
return (IDMAP_ERR_ARG);\
}\
return (IDMAP_ERR_ARG);\
}
/*
* Free memory allocated by libidmap API
*
* Input:
* ptr - memory to be freed
*/
void
idmap_free(void *ptr)
{
}
#define MIN_STACK_NEEDS 16384
/*
*
* Output:
* handle - idmap handle
*/
{
struct idmap_handle *hptr;
return (IDMAP_ERR_MEMORY);
/*
* clnt_door_call() alloca()s sendsz bytes (twice too, once for
* the call args buffer and once for the call result buffer), so
* we want to pick a sendsz that will be large enough, but not
* too large.
*/
if (stack_getbounds(&st) == 0) {
/*
* Estimate how much stack space is left;
* st.ss_sp is the top of stack.
*/
/* stack grows up */
else
/* stack grows down */
/*
* Take much of the stack space left, divided by two,
* but leave enough for our needs (just a guess!), and
* if we can't, then roll the dice.
*/
if (sendsz < MIN_STACK_NEEDS)
sendsz = 0; /* RPC call may fail */
else if (sendsz > IDMAP_MAX_DOOR_RPC)
}
return (IDMAP_ERR_RPC);
}
return (IDMAP_SUCCESS);
}
/*
* Finalize idmap handle
*
* Input:
* handle - idmap handle
*/
{
struct idmap_handle *hptr;
return (IDMAP_SUCCESS);
case _IDMAP_HANDLE_RPC_DOORS:
if (clnt) {
}
break;
default:
break;
}
return (IDMAP_SUCCESS);
}
{
if (clntstat != RPC_SUCCESS) {
return (_idmap_rpc2stat(clnt));
}
#if 0
if (clntstat != RPC_SUCCESS) {
goto cleanup;
}
#endif
}
{
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 (clntstat != RPC_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);
}
/*
* 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) {
if (retcode != IDMAP_SUCCESS)
goto errout;
}
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
*/
{
/* sanity checks */
return (IDMAP_ERR_ARG);
}
/* 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);
/* 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);
/* 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);
/* 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);
/* 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);
/* 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;
return (IDMAP_ERR_ARG);
}
TIMEOUT);
if (clntstat != RPC_SUCCESS) {
goto out;
}
goto out;
}
continue;
}
case IDMAP_UID:
break;
case IDMAP_GID:
break;
case IDMAP_POSIXID:
break;
case IDMAP_SID:
case IDMAP_USID:
case IDMAP_GSID:
break;
}
}
break;
case IDMAP_NONE:
break;
default:
break;
}
}
out:
return (retcode);
}
/*
* Destroy the "get mapping" handle
*/
void
{
return;
}
/*
* Get windows to unix mapping
*/
{
return (IDMAP_ERR_ARG);
}
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 (clntstat != RPC_SUCCESS)
return (_idmap_rpc2stat(clnt));
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)
if (rc != IDMAP_SUCCESS)
out:
if (retcode != IDMAP_SUCCESS)
return (retcode);
}
/*
* Get unix to windows mapping
*/
{
return (IDMAP_ERR_ARG);
}
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 (clntstat != RPC_SUCCESS)
return (_idmap_rpc2stat(clnt));
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)
if (rc != IDMAP_SUCCESS)
goto out;
}
}
}
out:
if (retcode != IDMAP_SUCCESS)
return (retcode);
}
#define gettext(s) s
static stat_table_t stattable[] = {
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},
{-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
*/
/* ARGSUSED */
const char *
{
int i;
}
return (gettext("Unknown error"));
}
static int
{
int i;
}
return (EINVAL);
}
/*
* Get status code from string
*/
idmap_string2stat(const char *str)
{
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);
}
static
{
return (IDMAP_SUCCESS);
if (retval != IDMAP_SUCCESS)
return (retval);
if (retval != IDMAP_SUCCESS) {
return (retval);
}
if (retval != IDMAP_SUCCESS) {
return (retval);
}
return (retval);
}
{
return (IDMAP_SUCCESS);
case IDMAP_MAP_TYPE_DS_AD:
break;
case IDMAP_MAP_TYPE_DS_NLDAP:
break;
break;
case IDMAP_MAP_TYPE_EPHEMERAL:
break;
case IDMAP_MAP_TYPE_LOCAL_SID:
break;
case IDMAP_MAP_TYPE_KNOWN_SID:
break;
}
return (retval);
}
/*
* This routine is similar to idmap_info_cpy, but the strings
* are moved from the "from" info to the "to" info.
* This routine is equivelent of:
*
* idmap_info_cpy(to,from);
* idmap_info_free(from);
*/
{
return (IDMAP_SUCCESS);
}
return (retval);
}
void
{
return;
case IDMAP_MAP_TYPE_DS_AD:
break;
case IDMAP_MAP_TYPE_DS_NLDAP:
break;
break;
case IDMAP_MAP_TYPE_EPHEMERAL:
break;
case IDMAP_MAP_TYPE_LOCAL_SID:
break;
}
}
/*
* Get uid given Windows name
*/
{
int is_user = 1;
int is_wuser = -1;
return (IDMAP_ERR_ARG);
/* Get mapping */
return (rc);
(void) idmap_fini(ih);
/*
* XXX Until we have diagonal mapping support, check if
* the given name belongs to a user
*/
return (IDMAP_ERR_NOTUSER);
return (rc);
}
/*
* Get gid given Windows name
*/
{
int is_user = 0;
int is_wuser = -1;
return (IDMAP_ERR_ARG);
/* Get mapping */
return (rc);
(void) idmap_fini(ih);
/*
* XXX Until we have diagonal mapping support, check if
* the given name belongs to a group
*/
return (IDMAP_ERR_NOTGROUP);
return (rc);
}
/*
* Get winname given pid
*/
static idmap_retcode
{
int len;
return (IDMAP_ERR_ARG);
/* Get mapping */
return (rc);
(void) idmap_fini(ih);
/* 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);
}
} else {
else
}
return (rc);
}
/*
* Get winname given uid
*/
{
}
/*
* Get winname given gid
*/
{
}
/* printflike */
void
}
/*
* We don't want to fill up the logs with useless messages when
* we're degraded, but we still want to log.
*/
if (logstate.write_syslog)
}
void
idmap_log_stderr(int pri)
{
}
void
{
}
void
{
}