/*
* 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
*/
/*
*/
/*
* Service routines
*/
#include "idmapd.h"
#include "idmap_priv.h"
#include "nldaputils.h"
#include <signal.h>
#include <thread.h>
#include <string.h>
#include <strings.h>
#include <errno.h>
#include <assert.h>
#include <ucred.h>
#include <pwd.h>
#include <auth_attr.h>
#include <secdb.h>
#include <sys/u8_textprep.h>
#include <note.h>
if (retcode == IDMAP_NEXT) {\
return (0);\
} else if (retcode < 0) {\
return (1);\
}
if (rcode == IDMAP_ERR_BUSY)\
else { \
return (1); \
}
goto out; \
} \
}
/* ARGSUSED */
{
return (TRUE);
}
/*
* RPC layer allocates empty strings to replace NULL char *.
* This utility function frees these empty strings.
*/
static
void
{
}
}
}
}
}
static
int
{
int e;
return (IDMAP_SUCCESS);
NULL, U8_VALIDATE_ENTIRE, &e) < 0)
return (IDMAP_ERR_BAD_UTF8);
NULL, U8_VALIDATE_ENTIRE, &e) < 0)
return (IDMAP_ERR_BAD_UTF8);
}
return (IDMAP_SUCCESS);
}
static
int
{
int e;
NULL, U8_VALIDATE_ENTIRE, &e) < 0)
return (IDMAP_ERR_BAD_UTF8);
NULL, U8_VALIDATE_ENTIRE, &e) < 0)
return (IDMAP_ERR_BAD_UTF8);
return (IDMAP_SUCCESS);
}
static
{
int i;
for (i = 0; i < batch->idmap_update_batch_len; i++) {
!= IDMAP_SUCCESS)
return (IDMAP_ERR_BAD_UTF8);
}
return (IDMAP_SUCCESS);
}
/* ARGSUSED */
{
uint_t i;
/* Init */
/* Return success if nothing was requested */
goto out;
/* Get cache handle */
goto out;
/* Get db handle */
goto out;
/* Allocate result array */
sizeof (idmap_id_res));
goto out;
}
/* Allocate hash table to check for duplicate sids */
sizeof (*state.sid_history));
goto out;
}
for (i = 0; i < state.sid_history_size; i++) {
}
/* Get directory-based name mapping info */
goto out;
/* Init our 'done' flags */
/* First stage */
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
(void) sanitize_mapping_request(req);
&state,
req,
res);
&state,
req,
res, 1);
&state,
req,
res, 0);
} else {
continue;
}
if (IDMAP_FATAL_ERROR(retcode)) {
goto out;
}
}
/* Check if we are done */
goto out;
/*
* native LDAP lookups:
* pid2sid:
* - nldap or mixed mode. Lookup nldap by pid or unixname to get
* winname.
* sid2pid:
* - nldap mode. Got winname and sid (either given or found in
* name_cache). Lookup nldap by winname to get pid and
* unixname.
*/
if (state.nldap_nqueries) {
if (IDMAP_FATAL_ERROR(retcode)) {
goto out;
}
if (any_tracing) {
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
"Native LDAP lookup error=%d",
} else {
}
}
}
}
/*
* AD lookups:
* pid2sid:
* - nldap or mixed mode. Got winname from nldap lookup.
* winname2sid could not be resolved locally. Lookup AD
* by winname to get sid.
* - ad mode. Got unixname. Lookup AD by unixname to get
* winname and sid.
* sid2pid:
* - ad or mixed mode. Lookup AD by sid or winname to get
* winname, sid and unixname.
* - any mode. Got either sid or winname but not both. Lookup
* AD by sid or winname to get winname, sid.
*/
if (state.ad_nqueries) {
if (IDMAP_FATAL_ERROR(retcode)) {
goto out;
}
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
/*
* If AD lookup failed Domain Not Found but
* we have a winname and SID, it means that
* - LSA succeeded
* - it's a request a cross-forest trust
* and
* - we were looking for directory-based
* mapping information.
* In that case, we're OK, just go on.
*
* If this seems more convoluted than it
* should be, it is - really, we probably
* shouldn't even be attempting AD lookups
* in this situation, but that's a more
* intricate cleanup that will have to wait
* for later.
*/
"AD lookup - domain not found (ignored)");
continue;
}
}
}
/*
* native LDAP lookups:
* sid2pid:
* - nldap mode. Got winname and sid from AD lookup. Lookup nldap
* by winname to get pid and unixname.
*/
if (state.nldap_nqueries) {
if (IDMAP_FATAL_ERROR(retcode)) {
goto out;
}
if (any_tracing) {
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
}
}
}
/* Reset 'done' flags */
/* Second stage */
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
&state,
req,
res);
&state,
req,
res, 1);
&state,
req,
res, 0);
} else {
/* First stage has already set the error */
continue;
}
if (IDMAP_FATAL_ERROR(retcode)) {
goto out;
}
}
/* Check if we are done */
goto out;
/* Reset our 'done' flags */
/* Update cache in a single transaction */
!= IDMAP_SUCCESS)
goto out;
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
(void) update_cache_sid2pid(
&state,
req,
res);
(void) update_cache_pid2sid(
&state,
req,
res);
}
}
/* Commit if we have at least one successful update */
"COMMIT TRANSACTION;");
else
"END TRANSACTION;");
out:
if (any_tracing) {
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
}
}
} else {
if (any_tracing) {
for (i = 0; i < batch.idmap_mapping_batch_len; i++) {
}
}
}
}
return (TRUE);
}
/* ARGSUSED */
static
int
{
char *str;
char *end;
static int validated_column_names = 0;
if (!validated_column_names) {
}
sizeof (idmap_mapping));
return (1);
str;
else
argv[6]);
argv[7]);
argv[8]);
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_IDMU:
break;
default:
/* Unknown mapping type */
}
}
return (0);
}
/* ARGSUSED */
{
/* Current time */
errno = 0;
goto out;
}
/* Get cache handle */
goto out;
/* Create LIMIT expression. */
if (limit > 0)
else
lbuf[0] = '\0';
/*
* Combine all the above into a giant SELECT statement that
* will return the requested mappings
*/
"u2w, windomain, canon_winname, unixname, is_user, is_wuser, "
"map_type, map_dn, map_attr, map_value, map_windomain, "
"map_winname, map_unixname, map_is_nt4 "
"FROM idmap_cache WHERE %s AND "
"(pid >= 2147483648 OR (expiration = 0 OR "
"expiration ISNULL OR expiration > %d)) "
"%s;",
goto out;
}
/* Execute the SQL statement and update the return buffer */
out:
if (sql)
return (TRUE);
}
/* ARGSUSED */
static
int
{
char *end;
static int validated_column_names = 0;
if (!validated_column_names) {
}
sizeof (idmap_namerule));
argv[3]);
argv[4]);
argv[6]);
else
return (0);
}
/* ARGSUSED */
{
goto out;
/* Get db handle */
goto out;
goto out;
/* Create LIMIT expression. */
if (limit > 0)
else
lbuf[0] = '\0';
/*
* Combine all the above into a giant SELECT statement that
* will return the requested rules
*/
"winname_display, is_nt4, unixname, w2u_order, u2w_order "
"FROM namerules WHERE "
" %s %s %s;",
goto out;
}
/* Execute the SQL statement and update the return buffer */
out:
if (expr)
if (sql)
return (TRUE);
}
static int
{
return (-1);
}
ucred_free(uc);
return (-1);
}
ucred_free(uc);
return (-1);
}
ucred_free(uc);
return (-1);
}
ucred_free(uc);
return (1);
}
/*
* Meaning of the return values is the following: For retcode ==
* IDMAP_SUCCESS, everything went OK and error_index is
* undefined. Otherwise, error_index >=0 shows the failed batch
* element. errro_index == -1 indicates failure at the beginning,
* error_index == -2 at the end.
*/
/* ARGSUSED */
{
int i;
if (verify_rules_auth(rqstp) < 0) {
goto out;
}
if (batch.idmap_update_batch_len == 0 ||
goto out;
}
goto out;
/* Get db handle */
goto out;
goto out;
for (i = 0; i < batch.idmap_update_batch_len; i++) {
case OP_NONE:
break;
case OP_ADD_NAMERULE:
break;
case OP_RM_NAMERULE:
break;
case OP_FLUSH_NAMERULES:
break;
default:
break;
};
res->error_index = i;
if (r2 != IDMAP_SUCCESS)
}
goto out;
}
}
out:
if (trans) {
"COMMIT TRANSACTION;");
/*
* We've updated the rules. Expire the cache
* so that existing mappings will be
* reconsidered.
*/
} else {
}
}
else
"ROLLBACK TRANSACTION;");
}
return (TRUE);
}
static
int
{
if (EMPTY_STRING(from)) {
} else {
return (IDMAP_ERR_MEMORY);
}
}
return (IDMAP_SUCCESS);
}
static
int
{
return (retcode);
} else {
return (IDMAP_SUCCESS);
}
}
static
int
{
if (retcode != IDMAP_SUCCESS)
goto errout;
if (retcode != IDMAP_SUCCESS)
goto errout;
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);
return (retcode);
}
/* ARGSUSED */
{
/* Clear out things we might want to xdr_free on error */
goto out;
/*
* Copy the request. We need to modify it, and
* what we have is a shallow copy. Freeing pointers from
* our copy will lead to problems, since the RPC framework
* has its own copy of those pointers. Besides, we need
* a copy to return.
*/
goto out;
}
/*
* Set up to return the filled-in mapping structure.
* Note that we xdr_free result on error, and that'll take
* care of freeing the mapping structure.
*/
goto out;
/* Set up for the request to the batch API */
/* Do the real work. */
&batch_result, rqstp);
/* Copy what we need out of the batch response */
goto out;
}
goto out;
out:
}
return (TRUE);
}
/* ARGSUSED */
{
/* Init */
/* Just shortcuts: */
switch (request) {
case PROP_LIST_SIZE_LIMIT:
break;
case PROP_DEFAULT_DOMAIN:
break;
case PROP_DOMAIN_NAME:
pgcfg->domain_name);
break;
case PROP_MACHINE_SID:
pgcfg->machine_sid);
break;
case PROP_DOMAIN_CONTROLLER:
sizeof (idmap_ad_disc_ds_t));
}
break;
case PROP_FOREST_NAME:
pgcfg->forest_name);
break;
case PROP_SITE_NAME:
break;
case PROP_GLOBAL_CATALOG:
}
break;
case PROP_AD_UNIXUSER_ATTR:
break;
case PROP_AD_UNIXGROUP_ATTR:
break;
case PROP_NLDAP_WINNAME_ATTR:
break;
break;
default:
break;
}
out:
}
return (TRUE);
}
int
{
if (verify_rules_auth(rqstp) < 0) {
return (TRUE);
}
return (TRUE);
}
/* ARGSUSED */
int
{
return (TRUE);
}
/*
* This function is called by rpc_svc.c when it encounters an error.
*/
void
{
}