netname.c revision 7c478bd95313f5f23a4c958a745db2134aa03244
/*
* CDDL HEADER START
*
* The contents of this file are subject to the terms of the
* Common Development and Distribution License, Version 1.0 only
* (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 2004 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
/* All Rights Reserved */
/*
* Portions of this source code were derived from Berkeley
* 4.3 BSD under license from the Regents of the University of
* California.
*/
/*
* ==== hack-attack: possibly MT-safe but definitely not MT-hot.
* ==== turn this into a real switch frontend and backends
*
* Well, at least the API doesn't involve pointers-to-static.
*/
#pragma ident "%Z%%M% %I% %E% SMI"
/*
* netname utility routines (getnetname, user2netname, host2netname).
*
* Convert from unix names (uid, gid) to network wide names.
* This module is operating system dependent!
* What we define here will work with any unix system that has adopted
* the Sun NIS domain architecture.
*/
#include "mt.h"
#include "rpc_mt.h"
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <syslog.h>
#include <rpcsvc/nis_dhext.h>
#include <nsswitch.h>
#include <syslog.h>
#ifndef MAXHOSTNAMELEN
#define MAXHOSTNAMELEN 256
#endif
#ifndef NGROUPS
#define NGROUPS 16
#endif
/*
* the value for NOBODY_UID is set by the SVID. The following define also
* appears in netnamer.c
*/
#define NOBODY_UID 60001
extern int __nis_principal();
extern int getdomainname();
extern char *strncpy();
extern int key_call();
#define OPSYS_LEN 4
#define PKTABLE_LEN 12
static const char *OPSYS = "unix";
static const char *PKTABLE = "cred.org_dir";
/*
* default publickey policy:
* publickey: nis [NOTFOUND = return] files
*/
/* NSW_NOTSUCCESS NSW_NOTFOUND NSW_UNAVAIL NSW_TRYAGAIN */
static struct __nsw_switchconfig publickey_default =
/*
* Convert unix cred to network-name using nisplus
* nisplus cred table has the following format:
*
* cname auth_type auth_name public private
* ----------------------------------------------------------
* nisname DES netname pubkey private_key
* nisname LOCAL uid gidlist
*
* Obtain netname given <uid,domain>.
* 0. If domain is NULL (indicating local domain), first try to get
* netname from keyserv (keylogin sets this).
* 1. Get the nisplus principal name from the LOCAL entry of the cred
* table in the specified domain (the local domain if domain is NULL).
* 2. Using the principal name, lookup the DES entry and extract netname.
*/
static int
int *err;
char *domain;
{
int len;
int status;
mechanism_t **mechs;
/*
* Look up the keyserv interface routines to see if
* netname is stored there.
*/
xdr_key_netstres, (char *)&kres) &&
len +1);
*err = __NSW_SUCCESS;
return (1);
}
}
/*
* 1. Determine user's nis+ principal name.
*
* If domain is specified, we want to look up the uid in the
* specified domain to determine the user's principal name.
* Otherwise, get principal name from local directory.
*/
/*
* Don't use nis_local_principal here because we want to
* catch the TRYAGAIN case so that we handle it properly.
*/
switch (status) {
case NIS_NOTFOUND:
case NIS_PARTIAL:
case NIS_NOSUCHNAME:
case NIS_NOSUCHTABLE:
*err = __NSW_NOTFOUND;
break;
case NIS_S_NOTFOUND:
case NIS_TRYAGAIN:
*err = __NSW_TRYAGAIN;
"user2netname: (nis+ lookup): %s\n",
break;
default:
*err = __NSW_UNAVAIL;
"user2netname: (nis+ lookup): %s\n",
}
return (0);
}
/*
* 2. use nis+ principal name to get netname by getting a PK entry.
*
* (Use NOAUTH to prevent recursion.)
*/
(size_t)NIS_MAXNAMELEN) {
*err = __NSW_UNAVAIL;
return (0);
}
mechanism_t **mpp;
/*
* Loop thru mechanism types till we find one in the
* cred table for this user.
*/
if (AUTH_DES_COMPAT_CHK(mp)) {
goto try_auth_des;
}
if (! VALID_MECH_ENTRY(mp))
continue;
sizeof (auth_type)))
continue;
"[cname=\"%s\",auth_type=\"%s\"],%s.%s",
/*
* If the entry is not found, let's try the next one,
* else it's success or a serious enough NIS+ err
* to bail on.
*/
break;
}
} else {
/*
* No valid mechs exist or the AUTH_DES compat entry was
* found in the security cf.
*/
}
case NIS_SUCCESS:
case NIS_S_SUCCESS:
break; /* go and do something useful */
case NIS_NOTFOUND:
case NIS_PARTIAL:
case NIS_NOSUCHNAME:
case NIS_NOSUCHTABLE:
*err = __NSW_NOTFOUND;
return (0);
case NIS_S_NOTFOUND:
case NIS_TRYAGAIN:
*err = __NSW_TRYAGAIN;
"user2netname: (nis+ lookup): %s\n",
return (0);
default:
*err = __NSW_UNAVAIL;
return (0);
}
/*
* Principal with more than one entry for this mech type?
* Something wrong with cred table. Should be unique.
* Warn user and continue.
*/
"user2netname: %s entry for %s not unique",
}
if (len > MAXNETNAMELEN) {
*err = __NSW_UNAVAIL;
return (0);
}
*err = __NSW_SUCCESS;
return (1);
}
/*
* Convert unix cred to network-name by concatenating the
* 3 pieces of information <opsys type> <uid> <domain>.
*/
static int
int *err;
char *domain;
{
int i;
char *dfltdom;
if (__rpc_get_default_domain(&dfltdom) != 0) {
*err = __NSW_UNAVAIL;
return (0);
}
}
(size_t)MAXNETNAMELEN) {
*err = __NSW_UNAVAIL;
return (0);
}
*err = __NSW_SUCCESS;
return (1);
}
/*
* Figure out my fully qualified network name
*/
int
{
int dummy;
trace1(TR_getnetname, 0);
if (uid == 0)
else
return (dummy);
}
/*
* Figure out the fully qualified network name for the given uid.
* This is a private interface.
*/
int
{
int dummy;
if (uid == 0)
else
return (dummy);
}
/*
* Convert unix cred to network-name
*
* It uses the publickey policy in the /etc/nsswitch.conf file
* (Unless the netname is "nobody", which is special cased).
* If there is no publickey policy in /etc/nsswitch.conf,
* the default publickey policy is used, which is
* publickey: nis [NOTFOUND=return] files
* Note that for the non-nisplus case, there is no failover
* so only the first entry would be relevant for those cases.
*/
int
const char *domain;
{
struct __nsw_switchconfig *conf;
struct __nsw_lookup *look;
enum __nsw_parse_err perr;
int err;
trace1(TR_user2netname, 0);
/*
* Take care of the special case of "nobody". If the uid is
* the value assigned by the SVID for nobody, return the string
* "nobody".
*/
if (uid == NOBODY_UID) {
return (1);
}
if (! conf) {
needfree = 0;
}
/* ldap, nis, and files all do the same thing. */
else {
"user2netname: unknown nameservice \
for publickey info '%s'\n",
look->service_name);
err = __NSW_UNAVAIL;
}
case __NSW_CONTINUE :
break;
case __NSW_RETURN :
if (needfree)
return (res);
default :
"user2netname: Unknown action for nameservice '%s'",
look->service_name);
}
}
if (needfree)
return (0);
}
/*
* Convert host to network-name
* This routine returns following netnames given the host and domain
* arguments defined below: (domainname=y.z)
* Arguments
* host domain netname
* ---- ------ -------
* - - unix.m@y.z (hostname=m)
* - a.b unix.m@a.b (hostname=m)
* - - unix.m@y.z (hostname=m.w.x)
* - a.b unix.m@a.b (hostname=m.w.x)
* h - unix.h@y.z
* h a.b unix.h@a.b
* h.w.x - unix.h@w.x
* h.w.x a.b unix.h@a.b
*/
int
const char *host;
const char *domain;
{
char *p;
char *dot_in_host;
int i;
trace1(TR_host2netname, 0);
if (p) {
*p++ = '\0';
/* if no domain passed, use tail of nis_local_host() */
domain = p;
}
}
} else {
return (0);
}
}
p = dot_in_host;
if (p) {
p = (char *)nis_domain_of(hostname);
if (len >= sizeof (domainname)) {
return (0);
}
(void) strcpy(domainname, p);
} else {
domainname[0] = NULL;
return (0);
}
} else {
if (len >= sizeof (domainname)) {
return (0);
}
}
i = strlen(domainname);
if (i == 0)
/* No domainname */
return (0);
domainname[i - 1] = 0;
if (dot_in_host) { /* strip off rest of name */
*dot_in_host = '\0';
}
> (size_t)MAXNETNAMELEN) {
return (0);
}
return (1);
}