16134Scasper /*
26134Scasper * CDDL HEADER START
36134Scasper *
46134Scasper * The contents of this file are subject to the terms of the
56134Scasper * Common Development and Distribution License (the "License").
66134Scasper * You may not use this file except in compliance with the License.
76134Scasper *
86134Scasper * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
96134Scasper * or http://www.opensolaris.org/os/licensing.
106134Scasper * See the License for the specific language governing permissions
116134Scasper * and limitations under the License.
126134Scasper *
136134Scasper * When distributing Covered Code, include this CDDL HEADER in each
146134Scasper * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
156134Scasper * If applicable, add the following below this CDDL HEADER, with the
166134Scasper * fields enclosed by brackets "[]" replaced with your own identifying
176134Scasper * information: Portions Copyright [yyyy] [name of copyright owner]
186134Scasper *
196134Scasper * CDDL HEADER END
206134Scasper */
216134Scasper
226134Scasper /*
236134Scasper * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
246134Scasper * Use is subject to license terms.
256134Scasper */
266134Scasper
276134Scasper #pragma ident "%Z%%M% %I% %E% SMI"
286134Scasper
29*6812Sraf #include "lint.h"
306134Scasper #include "priv_private.h"
316134Scasper #include "mtlib.h"
326134Scasper #include "libc.h"
336134Scasper #include <door.h>
346134Scasper #include <errno.h>
356134Scasper #include <priv.h>
366134Scasper #include <klpd.h>
376134Scasper #include <stdio.h>
386134Scasper #include <stdlib.h>
396134Scasper #include <string.h>
406134Scasper #include <sys/klpd.h>
416134Scasper #include <sys/param.h>
426134Scasper #include <sys/syscall.h>
436134Scasper #include <unistd.h>
446134Scasper #include <netinet/in.h>
456134Scasper
466134Scasper typedef struct klpd_data {
476134Scasper boolean_t (*kd_callback)(void *, const priv_set_t *, void *);
486134Scasper void *kd_user_cookie;
496134Scasper int kd_doorfd;
506134Scasper } klpd_data_t;
516134Scasper
526134Scasper typedef struct klpd_ctxt {
536134Scasper klpd_data_t *kc_data;
546134Scasper char *kc_path;
556134Scasper int kc_int;
566134Scasper int kc_type;
576134Scasper } klpd_ctxt_t;
586134Scasper
596134Scasper /* ARGSUSED */
606134Scasper static void
klpd_door_callback(void * kd_cookie,char * argp,size_t arg_size,door_desc_t * dp,uint_t ndesc)616134Scasper klpd_door_callback(void *kd_cookie, char *argp, size_t arg_size,
626134Scasper door_desc_t *dp, uint_t ndesc)
636134Scasper {
646134Scasper klpd_data_t *p = kd_cookie;
656134Scasper int res;
666134Scasper klpd_ctxt_t ctx;
676134Scasper klpd_head_t *klh;
686134Scasper klpd_arg_t *ka;
696134Scasper priv_set_t *pset;
706134Scasper
716134Scasper if (argp == DOOR_UNREF_DATA) {
726134Scasper (void) p->kd_callback(p->kd_user_cookie, NULL, NULL);
736134Scasper (void) door_return(NULL, 0, NULL, 0);
746134Scasper }
756134Scasper
766134Scasper klh = (void *)argp;
776134Scasper ka = KLH_ARG(klh);
786134Scasper pset = KLH_PRIVSET(klh);
796134Scasper
806134Scasper ctx.kc_type = ka == NULL ? KLPDARG_NONE : ka->kla_type;
816134Scasper
826134Scasper switch (ctx.kc_type) {
836134Scasper case KLPDARG_NONE:
846134Scasper ctx.kc_path = NULL;
856134Scasper ctx.kc_int = -1;
866134Scasper break;
876134Scasper case KLPDARG_VNODE:
886134Scasper ctx.kc_path = ka->kla_str;
896134Scasper ctx.kc_int = -1;
906134Scasper break;
916134Scasper default:
926134Scasper ctx.kc_int = ka->kla_int;
936134Scasper ctx.kc_path = NULL;
946134Scasper break;
956134Scasper }
966134Scasper
976134Scasper ctx.kc_data = p;
986134Scasper
996134Scasper if (p->kd_callback(p->kd_user_cookie, pset, &ctx))
1006134Scasper res = 0;
1016134Scasper else
1026134Scasper res = 1;
1036134Scasper
1046134Scasper (void) door_return((char *)&res, sizeof (res), NULL, 0);
1056134Scasper }
1066134Scasper
1076134Scasper void *
klpd_create(boolean_t (* callback)(void *,const priv_set_t *,void *),void * cookie)1086134Scasper klpd_create(boolean_t (*callback)(void *, const priv_set_t *, void *),
1096134Scasper void *cookie)
1106134Scasper {
1116134Scasper klpd_data_t *p = malloc(sizeof (klpd_data_t));
1126134Scasper
1136134Scasper if (p == NULL)
1146134Scasper return (NULL);
1156134Scasper
1166134Scasper p->kd_doorfd = door_create(klpd_door_callback, p,
1176134Scasper DOOR_REFUSE_DESC | DOOR_UNREF);
1186134Scasper if (p->kd_doorfd == -1)
1196134Scasper goto out;
1206134Scasper
1216134Scasper p->kd_user_cookie = cookie;
1226134Scasper p->kd_callback = callback;
1236134Scasper
1246134Scasper return (p);
1256134Scasper
1266134Scasper out:
1276134Scasper free(p);
1286134Scasper return (NULL);
1296134Scasper }
1306134Scasper
1316134Scasper int
klpd_register_id(const priv_set_t * set,void * handle,idtype_t type,id_t id)1326134Scasper klpd_register_id(const priv_set_t *set, void *handle, idtype_t type, id_t id)
1336134Scasper {
1346134Scasper klpd_data_t *p = handle;
1356134Scasper priv_data_t *d;
1366134Scasper
1376134Scasper LOADPRIVDATA(d);
1386134Scasper
1396134Scasper /* We really need to have the privilege set as argument here */
1406134Scasper if (syscall(SYS_privsys, PRIVSYS_KLPD_REG, p->kd_doorfd, id,
1416134Scasper set, d->pd_setsize, type) == -1)
1426134Scasper return (-1);
1436134Scasper
1446134Scasper /* Registration for the current process? Then do the thing. */
1456134Scasper if (type == P_PID && (id == 0 || (pid_t)id == getpid())) {
1466134Scasper (void) setppriv(PRIV_OFF, PRIV_INHERITABLE, set);
1476134Scasper (void) setpflags(PRIV_XPOLICY, 1);
1486134Scasper }
1496134Scasper return (0);
1506134Scasper }
1516134Scasper
1526134Scasper int
klpd_register(const priv_set_t * set,void * handle)1536134Scasper klpd_register(const priv_set_t *set, void *handle)
1546134Scasper {
1556134Scasper return (klpd_register_id(set, handle, P_PID, -1));
1566134Scasper }
1576134Scasper
1586134Scasper int
klpd_unregister_id(void * handle,idtype_t type,id_t id)1596134Scasper klpd_unregister_id(void *handle, idtype_t type, id_t id)
1606134Scasper {
1616134Scasper klpd_data_t *p = handle;
1626134Scasper int err;
1636134Scasper
1646134Scasper err = syscall(SYS_privsys, PRIVSYS_KLPD_UNREG, p->kd_doorfd, id,
1656134Scasper (void *)NULL, 0L, type);
1666134Scasper if (close(p->kd_doorfd) != 0)
1676134Scasper err = -1;
1686134Scasper free(p);
1696134Scasper return (err);
1706134Scasper }
1716134Scasper
1726134Scasper int
klpd_unregister(void * handle)1736134Scasper klpd_unregister(void *handle)
1746134Scasper {
1756134Scasper return (klpd_unregister_id(handle, P_PID, -1));
1766134Scasper }
1776134Scasper
1786134Scasper const char *
klpd_getpath(void * context)1796134Scasper klpd_getpath(void *context)
1806134Scasper {
1816134Scasper klpd_ctxt_t *p = context;
1826134Scasper
1836134Scasper if (p->kc_type != KLPDARG_VNODE)
1846134Scasper errno = EINVAL;
1856134Scasper return (p->kc_path);
1866134Scasper }
1876134Scasper
1886134Scasper int
klpd_getport(void * context,int * proto)1896134Scasper klpd_getport(void *context, int *proto)
1906134Scasper {
1916134Scasper klpd_ctxt_t *p = context;
1926134Scasper
1936134Scasper switch (p->kc_type) {
1946134Scasper case KLPDARG_TCPPORT:
1956134Scasper *proto = IPPROTO_TCP;
1966134Scasper break;
1976134Scasper case KLPDARG_UDPPORT:
1986134Scasper *proto = IPPROTO_UDP;
1996134Scasper break;
2006134Scasper case KLPDARG_SCTPPORT:
2016134Scasper *proto = IPPROTO_SCTP;
2026134Scasper break;
2036134Scasper case KLPDARG_SDPPORT:
2046134Scasper *proto = PROTO_SDP;
2056134Scasper break;
2066134Scasper default:
2076134Scasper errno = EINVAL;
2086134Scasper return (-1);
2096134Scasper }
2106134Scasper return (p->kc_int);
2116134Scasper }
2126134Scasper
2136134Scasper /*ARGSUSED*/
2146134Scasper int
klpd_getucred(ucred_t ** uc,void * context)2156134Scasper klpd_getucred(ucred_t **uc, void *context)
2166134Scasper {
2176134Scasper return (door_ucred(uc));
2186134Scasper }
219