/*
* 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
*/
/*
*/
/*
* (NB: not just from files, but all nsswitch sources.)
*/
#include <pwd.h>
#include <grp.h>
#include <malloc.h>
#include <string.h>
#include <stdlib.h>
#include <netdb.h>
#include <libuutil.h>
#include <note.h>
#include <errno.h>
#include "idmapd.h"
#include "directory.h"
#include "directory_private.h"
#include <rpcsvc/idmap_prot.h>
#include "directory_server_impl.h"
#include "sidutil.h"
unsigned int rid);
/*
* Retrieve information by name.
* Called indirectly through the directory_provider_static structure.
*/
static
{
int i;
/* 6835280 spurious lint error if the strlen is in the declaration */
/* We use len later, so this is not merely a workaround for 6835280 */
for (i = 0; i < ids->idmap_utf8str_list_len; i++) {
int type;
/*
* Extract the type for this particular ID.
* Advance to the next type, if it's there, else keep
* using this type until we run out of IDs.
*/
types++;
/*
* If this entry has already been handled, one way or another,
* skip it.
*/
continue;
if (type == DIRECTORY_ID_SID[0]) {
/*
* Is it our SID?
* Check whether the first part matches, then a "-",
* then a single RID.
*/
0)
continue;
continue;
char *p;
if (*p != '\0')
continue;
if (rid < LOCALRID_UID_MIN) {
/* Builtin, not handled here */
continue;
}
if (rid <= LOCALRID_UID_MAX) {
/* User */
errno = 0;
if (errno == 0) /* Not found */
continue;
"%d", err);
directory_error("errno.getpwuid",
"getpwuid: %2 (%1)",
continue;
}
} else if (rid >= LOCALRID_GID_MIN &&
rid <= LOCALRID_GID_MAX) {
/* Group */
errno = 0;
if (errno == 0) /* Not found */
continue;
"%d", err);
directory_error("errno.getgrgid",
"getgrgid: %2 (%1)",
continue;
}
} else
continue;
} else {
if (domain[0] != '\0') {
continue;
}
/*
* If the caller has requested user or group
* information specifically, we only set one of
* pwd or grp.
* If the caller has requested either type, we try
* both in the hopes of getting one.
* Note that directory_provider_nsswitch_populate
* considers it to be an error if both are set.
*/
if (type != DIRECTORY_ID_GROUP[0]) {
/* prep for not found / error case */
errno = 0;
"%d", err);
directory_error("errno.getpwnam",
"getpwnam: %2 (%1)",
continue;
}
}
if (type != DIRECTORY_ID_USER[0]) {
/* prep for not found / error case */
errno = 0;
"%d", err);
directory_error("errno.getgrnam",
"getgrnam: %2 (%1)",
continue;
}
}
}
/*
* Didn't find it, don't populate the structure.
* Another provider might populate it.
*/
continue;
attrs);
continue;
}
}
return (NULL);
}
/*
* Given a pwd structure or a grp structure, and a list of attributes that
* were requested, populate the structure to return to the caller.
*/
static
{
int j;
int nattrs;
/*
* If it wasn't for this case, everything would be a lot simpler.
* UNIX allows users and groups with the same name. Windows doesn't.
*/
return directory_error("Ambiguous.Name",
"Ambiguous name, is both a user and a group",
NULL);
}
goto nomem;
for (j = 0; j < nattrs; j++) {
char *a;
/*
* We're going to refer to these a lot, so make a shorthand
* copy.
*/
a = attrs->idmap_utf8str_list_val[j];
/*
* Start by assuming no errors and that we don't have
* the information
*/
/*
* Handle attributes for user entries.
*/
if (uu_strcaseeq(a, "cn")) {
} else if (uu_strcaseeq(a, "objectClass")) {
static const char *objectClasses[] = {
"top",
"posixAccount",
};
} else if (uu_strcaseeq(a, "gidNumber")) {
} else if (uu_strcaseeq(a, "objectSid")) {
} else if (uu_strcaseeq(a, "displayName")) {
} else if (uu_strcaseeq(a, "distinguishedName")) {
char *dn;
"uid=%s,ou=people,dc=%s",
goto nomem;
} else if (uu_strcaseeq(a, "uid")) {
} else if (uu_strcaseeq(a, "uidNumber")) {
} else if (uu_strcaseeq(a, "gecos")) {
} else if (uu_strcaseeq(a, "homeDirectory")) {
} else if (uu_strcaseeq(a, "loginShell")) {
} else if (uu_strcaseeq(a, "x-sun-canonicalName")) {
char *canon;
goto nomem;
} else if (uu_strcaseeq(a, "x-sun-provider")) {
}
/*
* Handle attributes for group entries.
*/
if (uu_strcaseeq(a, "cn")) {
} else if (uu_strcaseeq(a, "objectClass")) {
static const char *objectClasses[] = {
"top",
"posixGroup",
};
} else if (uu_strcaseeq(a, "gidNumber")) {
} else if (uu_strcaseeq(a, "objectSid")) {
} else if (uu_strcaseeq(a, "displayName")) {
} else if (uu_strcaseeq(a, "distinguishedName")) {
char *dn;
"cn=%s,ou=group,dc=%s",
goto nomem;
} else if (uu_strcaseeq(a, "memberUid")) {
/*
* NEEDSWORK: There is probably a non-cast
* way to do this, but I don't immediately
* see it.
*/
const char * const *members =
} else if (uu_strcaseeq(a, "x-sun-canonicalName")) {
char *canon;
goto nomem;
} else if (uu_strcaseeq(a, "x-sun-provider")) {
}
}
return (de);
}
return (NULL);
return (directory_error("ENOMEM.users",
"No memory allocating return value for user lookup", NULL));
}
/*
* Populate a directory attribute value with a SID based on our machine SID
* and the specified RID.
*
* It's a bit perverse that we must take a text-format SID and turn it into
* a binary-format SID, only to have the caller probably turn it back into
* text format, but SIDs are carried across LDAP in binary format.
*/
static
{
goto nomem;
return (de);
return (directory_error("ENOMEM.machine_sid_dav",
"Out of memory allocating return value for lookup", NULL));
}
"files",
};