#include <sys/param.h>
#include <sys/time.h>
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/user.h>
#include <sys/proc.h>
#include <sys/utsname.h>
#include <sys/cred.h>
#include <sys/kmem.h>
#include <sys/sysmacros.h>
#include <sys/cmn_err.h>
#include <rpc/types.h>
#include <rpc/xdr.h>
#include <rpc/auth.h>
#include <rpc/auth_unix.h>
#include <rpc/clnt.h>
#include <rpc/rpc_msg.h>
static void authloopback_nextverf(AUTH *);
static bool_t authloopback_marshal(AUTH *, XDR *, struct cred *);
static bool_t authloopback_validate(AUTH *, struct opaque_auth *);
static bool_t authloopback_refresh(AUTH *, struct rpc_msg *, cred_t *);
static void authloopback_destroy(AUTH *);
static struct auth_ops authloopback_ops = {
authloopback_nextverf,
authloopback_marshal,
authloopback_validate,
authloopback_refresh,
authloopback_destroy,
authany_wrap,
authany_unwrap
};
AUTH *
authloopback_create(void)
{
return (kmem_cache_alloc(authloopback_cache, KM_SLEEP));
}
int
authloopback_init(void *buf, void *cdrarg, int kmflags)
{
AUTH *auth = (AUTH *)buf;
auth->ah_ops = &authloopback_ops;
auth->ah_cred.oa_flavor = AUTH_LOOPBACK;
auth->ah_verf = _null_auth;
return (0);
}
static void
authloopback_nextverf(AUTH *auth)
{
}
static bool_t
authloopback_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
{
char *sercred;
XDR xdrm;
bool_t ret;
uint32_t gidlen, credsize, namelen, rounded_namelen;
int32_t *ptr;
char *nodename = uts_nodename();
uint32_t maxgidlen;
uint_t startpos;
ASSERT(xdrs->x_op == XDR_ENCODE);
ASSERT(auth->ah_cred.oa_flavor == AUTH_LOOPBACK);
ASSERT(auth->ah_verf.oa_flavor == AUTH_NONE);
ASSERT(auth->ah_verf.oa_length == 0);
namelen = (uint32_t)strlen(nodename);
if (namelen > MAX_MACHINE_NAME)
return (FALSE);
rounded_namelen = RNDUP(namelen);
#define NFIELDS 5
CTASSERT(NFIELDS * BYTES_PER_XDR_UNIT + RNDUP(MAX_MACHINE_NAME) <=
MAX_AUTH_BYTES);
maxgidlen = (MAX_AUTH_BYTES - NFIELDS * BYTES_PER_XDR_UNIT -
rounded_namelen) / BYTES_PER_XDR_UNIT;
gidlen = crgetngroups(cr);
if (gidlen > maxgidlen)
return (FALSE);
credsize = NFIELDS * BYTES_PER_XDR_UNIT + rounded_namelen +
gidlen * BYTES_PER_XDR_UNIT;
ASSERT(credsize <= MAX_AUTH_BYTES);
#undef NFIELDS
ptr = XDR_INLINE(xdrs, 2 * BYTES_PER_XDR_UNIT + credsize +
2 * BYTES_PER_XDR_UNIT);
if (ptr != NULL) {
const gid_t *gp = crgetgroups(cr);
IXDR_PUT_U_INT32(ptr, AUTH_LOOPBACK);
IXDR_PUT_U_INT32(ptr, credsize);
IXDR_PUT_INT32(ptr, gethrestime_sec());
IXDR_PUT_U_INT32(ptr, namelen);
bcopy(nodename, ptr, namelen);
if ((rounded_namelen - namelen) > 0)
bzero((char *)ptr + namelen, rounded_namelen - namelen);
ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
IXDR_PUT_U_INT32(ptr, crgetuid(cr));
IXDR_PUT_U_INT32(ptr, crgetgid(cr));
IXDR_PUT_U_INT32(ptr, gidlen);
while (gidlen-- > 0)
IXDR_PUT_U_INT32(ptr, *gp++);
IXDR_PUT_U_INT32(ptr, AUTH_NONE);
IXDR_PUT_U_INT32(ptr, 0);
return (TRUE);
}
sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
startpos = XDR_GETPOS(&xdrm);
if (!xdr_authloopback(&xdrm, cr)) {
printf("authloopback_marshal: xdr_authloopback failed\n");
ret = FALSE;
goto done;
}
auth->ah_cred.oa_base = sercred;
auth->ah_cred.oa_length = XDR_GETPOS(&xdrm) - startpos;
ASSERT(auth->ah_cred.oa_length <= MAX_AUTH_BYTES);
if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
(xdr_opaque_auth(xdrs, &(auth->ah_verf))))
ret = TRUE;
else
ret = FALSE;
done:
XDR_DESTROY(&xdrm);
kmem_free(sercred, MAX_AUTH_BYTES);
return (ret);
}
static bool_t
authloopback_validate(AUTH *auth, struct opaque_auth *verf)
{
return (TRUE);
}
static bool_t
authloopback_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr)
{
return (FALSE);
}
static void
authloopback_destroy(register AUTH *auth)
{
kmem_cache_free(authloopback_cache, auth);
}