1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown/*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * CDDL HEADER START
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown *
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * The contents of this file are subject to the terms of the
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Common Development and Distribution License (the "License").
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * You may not use this file except in compliance with the License.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown *
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * or http://www.opensolaris.org/os/licensing.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * See the License for the specific language governing permissions
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * and limitations under the License.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown *
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * When distributing Covered Code, include this CDDL HEADER in each
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * If applicable, add the following below this CDDL HEADER, with the
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * fields enclosed by brackets "[]" replaced with your own identifying
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * information: Portions Copyright [yyyy] [name of copyright owner]
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown *
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * CDDL HEADER END
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown/*
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown/*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Retrieve directory information for standard UNIX users/groups.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * (NB: not just from files, but all nsswitch sources.)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <pwd.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <grp.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <malloc.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <string.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <stdlib.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <netdb.h>
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh#include <libuutil.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <note.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <errno.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include "idmapd.h"
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include "directory.h"
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include "directory_private.h"
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include <rpcsvc/idmap_prot.h>
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include "directory_server_impl.h"
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown#include "sidutil.h"
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownstatic directory_error_t machine_sid_dav(directory_values_rpc *lvals,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown unsigned int rid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownstatic directory_error_t directory_provider_nsswitch_populate(
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_rpc *pent, struct passwd *pwd, struct group *grp,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown idmap_utf8str_list *attrs);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown/*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Retrieve information by name.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Called indirectly through the directory_provider_static structure.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownstatic
1fcced4c370617db71610fecffd5451a5894ca5eJordan Browndirectory_error_t
1fcced4c370617db71610fecffd5451a5894ca5eJordan Browndirectory_provider_nsswitch_get(
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_rpc *del,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown idmap_utf8str_list *ids,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown idmap_utf8str types,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown idmap_utf8str_list *attrs)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown{
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int i;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown RDLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* 6835280 spurious lint error if the strlen is in the declaration */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int host_name_len = strlen(_idmapdstate.hostname);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char my_host_name[host_name_len + 1];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) strcpy(my_host_name, _idmapdstate.hostname);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* We use len later, so this is not merely a workaround for 6835280 */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int machine_sid_len = strlen(_idmapdstate.cfg->pgcfg.machine_sid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char my_machine_sid[machine_sid_len + 1];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) strcpy(my_machine_sid, _idmapdstate.cfg->pgcfg.machine_sid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown UNLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown for (i = 0; i < ids->idmap_utf8str_list_len; i++) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown struct passwd *pwd = NULL;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown struct group *grp = NULL;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error_t de;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int type;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Extract the type for this particular ID.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Advance to the next type, if it's there, else keep
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * using this type until we run out of IDs.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown type = *types;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (*(types+1) != '\0')
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown types++;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * If this entry has already been handled, one way or another,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * skip it.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (del[i].status != DIRECTORY_NOT_FOUND)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *id = ids->idmap_utf8str_list_val[i];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (type == DIRECTORY_ID_SID[0]) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Is it our SID?
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Check whether the first part matches, then a "-",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * then a single RID.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (strncasecmp(id, my_machine_sid, machine_sid_len) !=
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown 0)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (id[machine_sid_len] != '-')
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *p;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown uint32_t rid =
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown strtoul(id + machine_sid_len + 1, &p, 10);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (*p != '\0')
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (rid < LOCALRID_UID_MIN) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* Builtin, not handled here */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (rid <= LOCALRID_UID_MAX) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* User */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown errno = 0;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pwd = getpwuid(rid - LOCALRID_UID_MIN);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (pwd == NULL) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (errno == 0) /* Not found */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char buf[40];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int err = errno;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) snprintf(buf, sizeof (buf),
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "%d", err);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_set_error(&del[i],
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error("errno.getpwuid",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "getpwuid: %2 (%1)",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown buf, strerror(err), NULL));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown } else if (rid >= LOCALRID_GID_MIN &&
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown rid <= LOCALRID_GID_MAX) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* Group */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown errno = 0;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown grp = getgrgid(rid - LOCALRID_GID_MIN);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (grp == NULL) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (errno == 0) /* Not found */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char buf[40];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int err = errno;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) snprintf(buf, sizeof (buf),
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "%d", err);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_set_error(&del[i],
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error("errno.getgrgid",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "getgrgid: %2 (%1)",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown buf, strerror(err), NULL));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown } else
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown } else {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int id_len = strlen(id);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char name[id_len + 1];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char domain[id_len + 1];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown split_name(name, domain, id);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (domain[0] != '\0') {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (!domain_eq(domain, my_host_name))
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * If the caller has requested user or group
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * information specifically, we only set one of
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * pwd or grp.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * If the caller has requested either type, we try
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * both in the hopes of getting one.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Note that directory_provider_nsswitch_populate
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * considers it to be an error if both are set.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (type != DIRECTORY_ID_GROUP[0]) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* prep for not found / error case */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown errno = 0;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pwd = getpwnam(name);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (pwd == NULL && errno != 0) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char buf[40];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int err = errno;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) snprintf(buf, sizeof (buf),
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "%d", err);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_set_error(&del[i],
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error("errno.getpwnam",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "getpwnam: %2 (%1)",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown buf, strerror(err), NULL));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (type != DIRECTORY_ID_USER[0]) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /* prep for not found / error case */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown errno = 0;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown grp = getgrnam(name);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (grp == NULL && errno != 0) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char buf[40];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int err = errno;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) snprintf(buf, sizeof (buf),
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "%d", err);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_set_error(&del[i],
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error("errno.getgrnam",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "getgrnam: %2 (%1)",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown buf, strerror(err), NULL));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Didn't find it, don't populate the structure.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Another provider might populate it.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (pwd == NULL && grp == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = directory_provider_nsswitch_populate(&del[i], pwd, grp,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown attrs);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (de != NULL) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_set_error(&del[i], de);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = NULL;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown continue;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return (NULL);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown}
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown/*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Given a pwd structure or a grp structure, and a list of attributes that
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * were requested, populate the structure to return to the caller.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownstatic
1fcced4c370617db71610fecffd5451a5894ca5eJordan Browndirectory_error_t
1fcced4c370617db71610fecffd5451a5894ca5eJordan Browndirectory_provider_nsswitch_populate(
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_entry_rpc *pent,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown struct passwd *pwd,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown struct group *grp,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown idmap_utf8str_list *attrs)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown{
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int j;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_values_rpc *llvals;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int nattrs;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * If it wasn't for this case, everything would be a lot simpler.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * UNIX allows users and groups with the same name. Windows doesn't.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (pwd != NULL && grp != NULL) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return directory_error("Ambiguous.Name",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "Ambiguous name, is both a user and a group",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown NULL);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown nattrs = attrs->idmap_utf8str_list_len;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown llvals = calloc(nattrs, sizeof (directory_values_rpc));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (llvals == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown goto nomem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pent->directory_entry_rpc_u.attrs.attrs_val = llvals;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pent->directory_entry_rpc_u.attrs.attrs_len = nattrs;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pent->status = DIRECTORY_FOUND;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown for (j = 0; j < nattrs; j++) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_values_rpc *val;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *a;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error_t de;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * We're going to refer to these a lot, so make a shorthand
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * copy.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown a = attrs->idmap_utf8str_list_val[j];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown val = &llvals[j];
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Start by assuming no errors and that we don't have
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * the information
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown val->found = FALSE;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = NULL;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (pwd != NULL) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Handle attributes for user entries.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh if (uu_strcaseeq(a, "cn")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = pwd->pw_name;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "objectClass")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown static const char *objectClasses[] = {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "top",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "posixAccount",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown };
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, objectClasses,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh UU_NELEM(objectClasses));
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "gidNumber")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = uint_list_dav(val, &pwd->pw_gid, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "objectSid")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = machine_sid_dav(val,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pwd->pw_uid + LOCALRID_UID_MIN);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "displayName")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = pwd->pw_gecos;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "distinguishedName")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *dn;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown RDLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) asprintf(&dn,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "uid=%s,ou=people,dc=%s",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pwd->pw_name, _idmapdstate.hostname);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown UNLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (dn == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown goto nomem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *cdn = dn;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &cdn, 1);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown free(dn);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "uid")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = pwd->pw_name;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "uidNumber")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = uint_list_dav(val, &pwd->pw_uid, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "gecos")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = pwd->pw_gecos;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "homeDirectory")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = pwd->pw_dir;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "loginShell")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = pwd->pw_shell;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-canonicalName")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *canon;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown RDLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) asprintf(&canon, "%s@%s",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown pwd->pw_name, _idmapdstate.hostname);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown UNLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (canon == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown goto nomem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *ccanon = canon;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &ccanon, 1);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown free(canon);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-provider")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *provider = "UNIX-passwd";
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &provider, 1);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown } else if (grp != NULL) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Handle attributes for group entries.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh if (uu_strcaseeq(a, "cn")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = grp->gr_name;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "objectClass")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown static const char *objectClasses[] = {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "top",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "posixGroup",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown };
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, objectClasses,
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh UU_NELEM(objectClasses));
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "gidNumber")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = uint_list_dav(val, &grp->gr_gid, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "objectSid")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = machine_sid_dav(val,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown grp->gr_gid + LOCALRID_GID_MIN);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "displayName")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *p = grp->gr_name;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &p, 1);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "distinguishedName")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *dn;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown RDLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) asprintf(&dn,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "cn=%s,ou=group,dc=%s",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown grp->gr_name, _idmapdstate.hostname);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown UNLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (dn == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown goto nomem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *cdn = dn;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &cdn, 1);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown free(dn);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "memberUid")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown /*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * NEEDSWORK: There is probably a non-cast
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * way to do this, but I don't immediately
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * see it.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char * const *members =
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (const char * const *)grp->gr_mem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, members, 0);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-canonicalName")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char *canon;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown RDLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) asprintf(&canon, "%s@%s",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown grp->gr_name, _idmapdstate.hostname);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown UNLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (canon == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown goto nomem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *ccanon = canon;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &ccanon, 1);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown free(canon);
cb174861876aea6950a7ab4ce944aff84b1914cdjoyce mcintosh } else if (uu_strcaseeq(a, "x-sun-provider")) {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown const char *provider = "UNIX-group";
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = str_list_dav(val, &provider, 1);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (de != NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return (de);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown }
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return (NULL);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownnomem:
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return (directory_error("ENOMEM.users",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "No memory allocating return value for user lookup", NULL));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown}
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown/*
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * Populate a directory attribute value with a SID based on our machine SID
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * and the specified RID.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown *
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * It's a bit perverse that we must take a text-format SID and turn it into
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * a binary-format SID, only to have the caller probably turn it back into
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown * text format, but SIDs are carried across LDAP in binary format.
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownstatic
1fcced4c370617db71610fecffd5451a5894ca5eJordan Browndirectory_error_t
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownmachine_sid_dav(directory_values_rpc *lvals, unsigned int rid)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown{
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown sid_t *sid;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_error_t de;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown RDLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown int len = strlen(_idmapdstate.cfg->pgcfg.machine_sid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown char buf[len + 100]; /* 100 is enough space for any RID */
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown (void) snprintf(buf, sizeof (buf), "%s-%u",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown _idmapdstate.cfg->pgcfg.machine_sid, rid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown UNLOCK_CONFIG();
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown sid = sid_fromstr(buf);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown if (sid == NULL)
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown goto nomem;
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown sid_to_le(sid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown de = bin_list_dav(lvals, sid, 1, sid_len(sid));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown sid_free(sid);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return (de);
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownnomem:
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown return (directory_error("ENOMEM.machine_sid_dav",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "Out of memory allocating return value for lookup", NULL));
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown}
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brownstruct directory_provider_static directory_provider_nsswitch = {
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown "files",
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown directory_provider_nsswitch_get,
1fcced4c370617db71610fecffd5451a5894ca5eJordan Brown};