nfsmapid_server.c revision dd5829d1456ba00e6f704e6a88e7eaae608e3c1b
/*
* 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 2007 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* Door server routines for nfsmapid daemon
* Translate NFSv4 users and groups between numeric and string values
*/
#include <stdio.h>
#include <stdlib.h>
#include <alloca.h>
#include <signal.h>
#include <libintl.h>
#include <limits.h>
#include <errno.h>
#include <string.h>
#include <memory.h>
#include <pwd.h>
#include <grp.h>
#include <door.h>
#include <syslog.h>
#include <fcntl.h>
#include <unistd.h>
#include <assert.h>
#include <deflt.h>
#include <nfs/nfsid_map.h>
#include <idmap.h>
#define DIAG_FILE "/var/run/nfs4_domain"
/*
* idmap_kcall() takes a door descriptor as it's argument when we
* need to (re)establish the in-kernel door handles. When we only
* want to flush the id kernel caches, we don't redo the door setup.
*/
#define FLUSH_KCACHES_ONLY (int)-1
int n4_fd;
extern size_t pwd_buflen;
extern size_t grp_buflen;
extern thread_t sig_thread;
/*
* Prototypes
*/
extern void check_domain(int);
extern void idmap_kcall(int);
extern int _nfssys(int, void *);
extern int valid_domain(const char *);
extern int validate_id_str(const char *);
extern int extract_domain(char *, char **, char **);
extern void update_diag_file(char *);
extern void *cb_update_domain(void *);
extern int cur_domain_null(void);
void
{
int pwd_rc;
char *pwd_buf;
char *user;
char *domain;
goto done;
}
unsigned long id;
/*
* Invalid "user@domain" string. Still, the user
* part might be an encoded uid, so do a final check.
* Remember, domain part of string was not set since
* not a valid string.
*/
if (!validate_id_str(user)) {
goto done;
}
errno = 0;
/*
* We don't accept ephemeral ids from the wire.
*/
goto done;
}
goto done;
}
/*
* String properly constructed. Now we check for domain and
* group validity.
*/
/*
* If the domain part of the string does not
* match the NFS domain, try to map it using
* idmap service.
*/
if (rc != IDMAP_SUCCESS) {
goto done;
}
goto done;
}
else {
/*
* Not a valid user
*/
}
goto done;
}
/*
* Valid user entry
*/
done:
}
/* ARGSUSED1 */
void
{
char *pw_str;
char *at_str;
/*
* Sentinel uid is not a valid id
*/
goto done;
}
/*
* Make local copy of domain for further manipuation
* NOTE: mapid_get_domain() returns a ptr to TSD.
*/
if (cur_domain_null()) {
dom_str_len = 0;
dom_str[0] = '\0';
} else {
}
/*
* If uid is ephemeral then resolve it using idmap service
*/
if (rc != IDMAP_SUCCESS) {
/*
* We don't put stringified ephemeral uids on
* the wire.
*/
goto done;
}
/*
* idmap_buf is already in the desired form i.e. name@domain
*/
at_str_len = dom_str_len = 0;
at_str = "";
dom_str[0] = '\0';
goto gen_result;
}
/*
* Handling non-ephemeral uids
*
* We want to encode the uid into a literal string... :
*
* - upon failure to allocate space from the heap
* - if there is no current domain configured
* - if there is no such uid in the passwd DB's
*/
/*
* If we could not allocate from the heap, try
* allocating from the stack as a last resort.
*/
goto done;
}
/*
* Constructing literal string without '@' so that
* we'll know that it's not a user, but rather a
* uid encoded string.
*/
at_str_len = dom_str_len = 0;
at_str = "";
dom_str[0] = '\0';
} else {
/*
* Otherwise, we construct the "user@domain" string if
* it's not already in that form.
*/
at_str = "@";
at_str_len = 1;
} else {
at_str_len = dom_str_len = 0;
at_str = "";
dom_str[0] = '\0';
}
}
goto done;
}
/* LINTED format argument to sprintf */
if (pwd_buf)
if (idmap_buf)
done:
/*
* There is a chance that the door_return will fail because the
* resulting string is too large, try to indicate that if possible
*/
if (door_return((char *)resp,
NULL, 0);
}
}
void
{
int grp_rc;
char *grp_buf;
char *group;
char *domain;
goto done;
}
unsigned long id;
/*
* Invalid "group@domain" string. Still, the
* group part might be an encoded gid, so do a
* final check. Remember, domain part of string
* was not set since not a valid string.
*/
if (!validate_id_str(group)) {
goto done;
}
errno = 0;
/*
* We don't accept ephemeral ids from the wire.
*/
goto done;
}
goto done;
}
/*
* String properly constructed. Now we check for domain and
* group validity.
*/
/*
* If the domain part of the string does not
* match the NFS domain, try to map it using
* idmap service.
*/
if (rc != IDMAP_SUCCESS) {
goto done;
}
goto done;
}
else {
/*
* Not a valid group
*/
}
goto done;
}
/*
* Valid group entry
*/
done:
}
/* ARGSUSED1 */
void
{
char *gr_str;
char *at_str;
/*
* Sentinel gid is not a valid id
*/
goto done;
}
/*
* Make local copy of domain for further manipuation
* NOTE: mapid_get_domain() returns a ptr to TSD.
*/
if (cur_domain_null()) {
dom_str_len = 0;
dom_str[0] = '\0';
} else {
}
/*
* If gid is ephemeral then resolve it using idmap service
*/
if (rc != IDMAP_SUCCESS) {
/*
* We don't put stringified ephemeral gids on
* the wire.
*/
goto done;
}
/*
* idmap_buf is already in the desired form i.e. name@domain
*/
at_str_len = dom_str_len = 0;
at_str = "";
dom_str[0] = '\0';
goto gen_result;
}
/*
* Handling non-ephemeral gids
*
* We want to encode the gid into a literal string... :
*
* - upon failure to allocate space from the heap
* - if there is no current domain configured
* - if there is no such gid in the group DB's
*/
/*
* If we could not allocate from the heap, try
* allocating from the stack as a last resort.
*/
goto done;
}
/*
* Constructing literal string without '@' so that
* we'll know that it's not a group, but rather a
* gid encoded string.
*/
at_str_len = dom_str_len = 0;
at_str = "";
dom_str[0] = '\0';
} else {
/*
* Otherwise, we construct the "group@domain" string if
* it's not already in that form.
*/
at_str = "@";
at_str_len = 1;
} else {
at_str_len = dom_str_len = 0;
at_str = "";
dom_str[0] = '\0';
}
}
goto done;
}
/* LINTED format argument to sprintf */
if (grp_buf)
if (idmap_buf)
done:
/*
* There is a chance that the door_return will fail because the
* resulting string is too large, try to indicate that if possible
*/
if (door_return((char *)resp,
NULL, 0);
}
}
/* ARGSUSED */
void
{
/*
* Make sure we have a valid argument
*/
NULL, 0);
return;
}
/* LINTED pointer cast */
case NFSMAPID_STR_UID:
return;
case NFSMAPID_UID_STR:
return;
case NFSMAPID_STR_GID:
return;
case NFSMAPID_GID_STR:
return;
default:
break;
}
}
/*
* mapid_get_domain() always returns a ptr to TSD, so the
* check for a NULL domain is not a simple comparison with
* NULL but we need to check the contents of the TSD data.
*/
int
cur_domain_null(void)
{
char *p;
if ((p = mapid_get_domain()) == NULL)
return (1);
return (p[0] == '\0');
}
int
{
/*
* Caller must insure that the string is valid
*/
return (0);
*(*dpp)++ = '\0';
return (1);
}
int
valid_domain(const char *dom)
{
const char *whoami = "valid_domain";
if (!mapid_stdchk_domain(dom)) {
return (0);
}
/*
* NOTE: mapid_get_domain() returns a ptr to TSD.
*/
}
int
validate_id_str(const char *id)
{
while (*id) {
return (0);
}
return (1);
}
void
idmap_kcall(int door_id)
{
struct nfsidmap_args args;
if (door_id >= 0) {
} else {
}
}
/*
* Get the current NFS domain.
*
* otherwise, the DNS domain is used.
*/
void
check_domain(int sighup)
{
const char *whoami = "check_domain";
static int setup_done = 0;
/*
* Construct the arguments to be passed to libmapid interface
* If called in response to a SIGHUP, reset any cached DNS TXT
* RR state.
*/
/*
* Restart the signal handler thread if we're still setting up
*/
if (!setup_done) {
setup_done = 1;
if (thr_continue(sig_thread)) {
"handler thread could not be restarted."), whoami);
exit(6);
}
}
}
/*
* Need to be able to open the DIAG_FILE before nfsmapid(1m)
* releases it's root priviledges. The DIAG_FILE then remains
* open for the duration of this nfsmapid instance via n4_fd.
*/
void
{
static int msg_done = 0;
return;
}
if (msg_done)
return;
"daemon.debug for more info", DIAG_FILE);
msg_done = 1;
}
/*
* When a new domain name is configured, save to DIAG_FILE
* and log to syslog, with LOG_DEBUG level (if configured).
*/
void
update_diag_file(char *new)
{
ssize_t n;
if (n < 0 || n < len)
}
/*
* Callback function for libmapid. This will be called
* by the lib, everytime the nfsmapid(1m) domain changes.
*/
void *
cb_update_domain(void *arg)
{
return (NULL);
}