sec_clnt.c revision 52056d7b0df4718b60b8de756bee184ba1831169
/*
* 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
*/
/*
*/
#include <rpc/rpcsec_gss.h>
#define MAXCLIENTS 16
/*
* Currently there is no maximum length defined withing the gss
* specification. Because of security issues the maximum gss
* authentication length is checked to be under the MAXAUTHLEN
* defined below. The value was chosen because it will be a safe
* maximum value for some time. Currently lengths are generally
* under the 16 byte length
*/
static int clnt_authdes_cachesz = 64;
struct kmem_cache *authkern_cache;
struct kmem_cache *authnone_cache;
struct kmem_cache *authloopback_cache;
static struct desauthent {
short da_inuse;
} *desauthtab;
static int nextdesvictim;
/* RPC stuff */
static void purge_authtab(struct sec_data *);
/* Zone stuff */
/*
* Load RPCSEC_GSS specific data from user space to kernel space.
*/
/*ARGSUSED*/
static int
{
struct gss_clnt_data *data;
int error = 0;
/* map opaque data to gss specific structure */
#ifdef _SYSCALL32_IMPL
if (model != DATAMODEL_NATIVE) {
struct gss_clnt_data32 gd32;
} else {
}
} else
#endif /* _SYSCALL32_IMPL */
if (error == 0) {
return (0);
}
}
}
return (EFAULT);
}
/*
* Load AUTH_DES specific data from user space to kernel space.
*/
/*ARGSUSED2*/
int
{
int error = 0;
char *userbufptr;
struct knetconfig *knconf;
/* map opaque data to des specific strucutre */
#ifdef _SYSCALL32_IMPL
if (model != DATAMODEL_NATIVE) {
struct des_clnt_data32 data32;
} else {
}
} else
#endif /* _SYSCALL32_IMPL */
if (error == 0) {
else {
} else {
if (nlen != 0) {
}
}
}
}
if (!error) {
/*
* Allocate space for a knetconfig structure and
* its strings and copy in from user-land.
*/
#ifdef _SYSCALL32_IMPL
if (model != DATAMODEL_NATIVE) {
struct knetconfig32 knconf32;
sizeof (knconf32)) == -1) {
} else {
}
} else
#endif /* _SYSCALL32_IMPL */
}
}
if (!error) {
char *p, *pf;
if (error) {
kmem_free(p, KNC_STRSIZE);
}
if (!error) {
p, KNC_STRSIZE, &nmoved_tmp);
if (error) {
kmem_free(p, KNC_STRSIZE);
}
}
if (!error) {
}
}
if (error) {
return (error);
}
return (0);
}
/*
* Free up AUTH_DES specific data.
*/
void
{
if (data->netnamelen > 0) {
}
}
}
}
/*
* Load application auth related data from user land to kernel.
* Map opaque data field to dh_k4_clntdata_t for AUTH_DES
*
*/
int
{
int error = 0;
#ifdef _SYSCALL32_IMPL
if (model != DATAMODEL_NATIVE) {
struct sec_data32 sd32;
} else {
}
} else
#endif /* _SYSCALL32_IMPL */
}
/*
* Copy in opaque data field per flavor.
*/
if (!error) {
case AUTH_NONE:
case AUTH_UNIX:
case AUTH_LOOPBACK:
break;
case AUTH_DES:
break;
case RPCSEC_GSS:
break;
default:
break;
}
}
if (!error) {
} else {
}
return (error);
}
/*
* Null the sec_data index in the cache table, and
* free the memory allocated by sec_clnt_loadinfo.
*/
void
{
case AUTH_DES:
break;
case RPCSEC_GSS:
rpc_gss_secpurge((void *)secdata);
}
}
break;
case AUTH_NONE:
case AUTH_UNIX:
case AUTH_LOOPBACK:
default:
break;
}
}
/*
* Get an AUTH handle for a RPC client based on the given sec_data.
* If an AUTH handle exists for the same sec_data, use that AUTH handle,
* otherwise create a new one.
*/
int
{
int i;
struct desauthent *da;
int authflavor;
int stat; /* return (errno) status */
char gss_svc_name[MAX_GSS_NAME];
return (EINVAL);
for (;;) {
int nlen;
char *netname;
switch (authflavor) {
case AUTH_NONE:
case AUTH_UNIX:
case AUTH_LOOPBACK:
case AUTH_DES:
if (desauthtab == NULL) {
sizeof (struct desauthent), KM_SLEEP);
}
for (da = desauthtab;
da++) {
return (0);
}
}
/*
* A better way would be to have a cred paramater to
* authdes_create.
*/
/*
* Note that authdes_create() expects a
* NUL-terminated string for netname, but
* dh_k4_clntdata_t gives us netname & netnamelen.
*
* We must create a string for authdes_create();
* the latter takes a copy of it, so we may
* immediately free it.
*/
/* must be NUL-terminated */
&auth);
if (stat != 0) {
/*
* If AUTH_F_TRYNONE is on, try again
* with AUTH_NONE. See bug 1180236.
*/
continue;
} else
return (stat);
}
i = clnt_authdes_cachesz;
do {
/* overflow of des auths */
return (stat);
}
return (stat);
case RPCSEC_GSS:
/*
* For RPCSEC_GSS, cache is done in rpc_gss_secget().
* For every rpc_gss_secget(), it should have
* a corresponding rpc_gss_secfree() call.
*/
/* success */
if (stat == 0)
return (stat);
/*
* let the caller retry if connection timedout
* or reset.
*/
return (stat);
/*
* If AUTH_F_TRYNONE is on, try again
* with AUTH_NONE. See bug 1180236.
*/
continue;
}
" failed with %d", stat);
return (stat);
default:
/*
* auth create must have failed, try AUTH_NONE
* (this relies on AUTH_NONE never failing)
*/
"authflavor %d, trying AUTH_NONE", authflavor);
}
}
}
void
{
struct desauthent *da;
case AUTH_NONE: /* XXX: do real AUTH_NONE */
case AUTH_UNIX:
case AUTH_LOOPBACK:
break;
case AUTH_DES:
if (desauthtab != NULL) {
for (da = desauthtab;
return;
}
}
}
break;
case RPCSEC_GSS:
(void) rpc_gss_secfree(auth);
break;
default:
break;
}
}
/*
* Revoke the authentication key in the given AUTH handle by setting
* it to NULL. If newkey is true, then generate a new key instead of
* nulling out the old one. This is necessary for AUTH_DES because
* the new key will be used next time the user does a keylogin. If
* the zero'd key is used as actual key, then it cannot be revoked
* again!
*/
void
{
return;
if (newkey) {
/* failed to get new key, munge the old one */
}
} else {
/* null out old key */
}
}
/*
* Revoke all rpc credentials (of the selected auth type) for the given uid
* from the auth cache. Must be root to do this if the requested uid is not
* the effective uid of the requestor.
*
* Called from nfssys() for backward compatibility, and also
* called from krpc_sys().
*
* AUTH_DES does not refer to the "mechanism" information.
* RPCSEC_GSS requires the "mechanism" input.
* The input argument, mechanism, is a user-space address and needs
* to be copied into the kernel address space.
*
* Returns error number.
*/
/*ARGSUSED*/
int
{
struct desauthent *da;
int error = 0;
return (EPERM);
switch (rpcflavor) {
case AUTH_DES:
if (desauthtab != NULL) {
for (da = desauthtab;
}
}
return (0);
case RPCSEC_GSS: {
if (!mechanism)
return (EINVAL);
/* copyin the gss mechanism type */
#ifdef _SYSCALL32_IMPL
if (model != DATAMODEL_NATIVE) {
sizeof (gss_OID_desc32))) {
return (EFAULT);
}
} else
#endif /* _SYSCALL32_IMPL */
return (EFAULT);
}
return (EINVAL);
}
return (EFAULT);
}
return (error);
}
default:
/* not an auth type with cached creds */
return (EINVAL);
}
}
/*
* Since sec_data is the index for the client auth handles
* cache table, whenever the sec_data is freed, the index needs
* to be nulled.
*/
void
{
struct desauthent *da;
case AUTH_DES:
if (desauthtab != NULL) {
for (da = desauthtab;
}
}
}
return;
case RPCSEC_GSS:
rpc_gss_secpurge((void *)secdata);
return;
default:
return;
}
}
void
sec_subrinit(void)
{
/* RPC stuff */
}
/*
* Destroys the caches and mutexes previously allocated and initialized
* in sec_subrinit().
* This routine is called by _init() if mod_install() failed.
*/
void
sec_subrfini(void)
{
/* RPC stuff */
(void) zone_key_delete(auth_zone_key);
}