1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License (the "License"). 6 * You may not use this file except in compliance with the License. 7 * 8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 9 * or http://www.opensolaris.org/os/licensing. 10 * See the License for the specific language governing permissions 11 * and limitations under the License. 12 * 13 * When distributing Covered Code, include this CDDL HEADER in each 14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 15 * If applicable, add the following below this CDDL HEADER, with the 16 * fields enclosed by brackets "[]" replaced with your own identifying 17 * information: Portions Copyright [yyyy] [name of copyright owner] 18 * 19 * CDDL HEADER END 20 */ 21 22 /* 23 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #include "lint.h" 28 #include "priv_private.h" 29 #include "mtlib.h" 30 #include "libc.h" 31 #include <door.h> 32 #include <errno.h> 33 #include <priv.h> 34 #include <klpd.h> 35 #include <stdio.h> 36 #include <stdlib.h> 37 #include <string.h> 38 #include <sys/klpd.h> 39 #include <sys/param.h> 40 #include <sys/syscall.h> 41 #include <unistd.h> 42 #include <netinet/in.h> 43 44 typedef struct klpd_data { 45 boolean_t (*kd_callback)(void *, const priv_set_t *, void *); 46 void *kd_user_cookie; 47 int kd_doorfd; 48 } klpd_data_t; 49 50 typedef struct klpd_ctxt { 51 klpd_data_t *kc_data; 52 char *kc_path; 53 int kc_int; 54 int kc_type; 55 } klpd_ctxt_t; 56 57 static void 58 klpd_door_callback(void *kd_cookie, char *argp, size_t arg_size __unused, 59 door_desc_t *dp __unused, uint_t ndesc __unused) 60 { 61 klpd_data_t *p = kd_cookie; 62 int res; 63 klpd_ctxt_t ctx; 64 klpd_head_t *klh; 65 klpd_arg_t *ka; 66 priv_set_t *pset; 67 68 if (argp == DOOR_UNREF_DATA) { 69 (void) p->kd_callback(p->kd_user_cookie, NULL, NULL); 70 (void) door_return(NULL, 0, NULL, 0); 71 } 72 73 klh = (void *)argp; 74 ka = KLH_ARG(klh); 75 pset = KLH_PRIVSET(klh); 76 77 ctx.kc_type = ka == NULL ? KLPDARG_NONE : ka->kla_type; 78 79 switch (ctx.kc_type) { 80 case KLPDARG_NONE: 81 ctx.kc_path = NULL; 82 ctx.kc_int = -1; 83 break; 84 case KLPDARG_VNODE: 85 ctx.kc_path = ka->kla_str; 86 ctx.kc_int = -1; 87 break; 88 default: 89 ctx.kc_int = ka->kla_int; 90 ctx.kc_path = NULL; 91 break; 92 } 93 94 ctx.kc_data = p; 95 96 if (p->kd_callback(p->kd_user_cookie, pset, &ctx)) 97 res = 0; 98 else 99 res = 1; 100 101 (void) door_return((char *)&res, sizeof (res), NULL, 0); 102 } 103 104 void * 105 klpd_create(boolean_t (*callback)(void *, const priv_set_t *, void *), 106 void *cookie) 107 { 108 klpd_data_t *p = malloc(sizeof (klpd_data_t)); 109 110 if (p == NULL) 111 return (NULL); 112 113 p->kd_doorfd = door_create(klpd_door_callback, p, 114 DOOR_REFUSE_DESC | DOOR_UNREF); 115 if (p->kd_doorfd == -1) 116 goto out; 117 118 p->kd_user_cookie = cookie; 119 p->kd_callback = callback; 120 121 return (p); 122 123 out: 124 free(p); 125 return (NULL); 126 } 127 128 int 129 klpd_register_id(const priv_set_t *set, void *handle, idtype_t type, id_t id) 130 { 131 klpd_data_t *p = handle; 132 priv_data_t *d; 133 134 LOADPRIVDATA(d); 135 136 /* We really need to have the privilege set as argument here */ 137 if (syscall(SYS_privsys, PRIVSYS_KLPD_REG, p->kd_doorfd, id, 138 set, d->pd_setsize, type) == -1) 139 return (-1); 140 141 /* Registration for the current process? Then do the thing. */ 142 if (type == P_PID && (id == 0 || (pid_t)id == getpid())) { 143 (void) setppriv(PRIV_OFF, PRIV_INHERITABLE, set); 144 (void) setpflags(PRIV_XPOLICY, 1); 145 } 146 return (0); 147 } 148 149 int 150 klpd_register(const priv_set_t *set, void *handle) 151 { 152 return (klpd_register_id(set, handle, P_PID, -1)); 153 } 154 155 int 156 klpd_unregister_id(void *handle, idtype_t type, id_t id) 157 { 158 klpd_data_t *p = handle; 159 int err; 160 161 err = syscall(SYS_privsys, PRIVSYS_KLPD_UNREG, p->kd_doorfd, id, 162 (void *)NULL, 0L, type); 163 if (close(p->kd_doorfd) != 0) 164 err = -1; 165 free(p); 166 return (err); 167 } 168 169 int 170 klpd_unregister(void *handle) 171 { 172 return (klpd_unregister_id(handle, P_PID, -1)); 173 } 174 175 const char * 176 klpd_getpath(void *context) 177 { 178 klpd_ctxt_t *p = context; 179 180 if (p->kc_type != KLPDARG_VNODE) 181 errno = EINVAL; 182 return (p->kc_path); 183 } 184 185 int 186 klpd_getport(void *context, int *proto) 187 { 188 klpd_ctxt_t *p = context; 189 190 switch (p->kc_type) { 191 case KLPDARG_TCPPORT: 192 *proto = IPPROTO_TCP; 193 break; 194 case KLPDARG_UDPPORT: 195 *proto = IPPROTO_UDP; 196 break; 197 case KLPDARG_SCTPPORT: 198 *proto = IPPROTO_SCTP; 199 break; 200 case KLPDARG_SDPPORT: 201 *proto = PROTO_SDP; 202 break; 203 default: 204 errno = EINVAL; 205 return (-1); 206 } 207 return (p->kc_int); 208 } 209 210 int 211 klpd_getucred(ucred_t **uc, void *context __unused) 212 { 213 return (door_ucred(uc)); 214 } 215