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 * Copyright 2008 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 #pragma ident "%Z%%M% %I% %E% SMI" 27 28 /* 29 * sec_svc.c, Server-side rpc security interface. 30 */ 31 #ifdef _KERNEL 32 #include <sys/param.h> 33 #include <sys/types.h> 34 #include <sys/debug.h> 35 #include <sys/systm.h> 36 #include <rpc/types.h> 37 #include <netinet/in.h> 38 #include <rpc/xdr.h> 39 #include <rpc/auth.h> 40 #include <rpc/clnt.h> 41 #include <rpc/rpc_msg.h> 42 #include <sys/tiuser.h> 43 #include <sys/tihdr.h> 44 #include <sys/t_kuser.h> 45 #include <sys/cmn_err.h> 46 #include <rpc/auth_des.h> 47 #include <rpc/auth_sys.h> 48 #include <rpc/rpcsec_gss.h> 49 #include <rpc/svc_auth.h> 50 #include <rpc/svc.h> 51 #else 52 #include <rpc/rpc.h> 53 #endif 54 55 56 enum auth_stat _svcauth_null(struct svc_req *, struct rpc_msg *); 57 58 /* 59 * NO-OP server wrap/unwrap svc_authany_ops using no-op svc_authany_wrap(). 60 */ 61 /* ARGSUSED */ 62 static int 63 svc_authany_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xfunc, caddr_t xwhere) 64 { 65 return (*xfunc)(xdrs, xwhere); 66 } 67 68 struct svc_auth_ops svc_authany_ops = { 69 svc_authany_wrap, 70 svc_authany_wrap 71 }; 72 73 74 /* 75 * The call rpc message, msg has been obtained from the wire. The msg contains 76 * the raw form of credentials and verifiers. authenticate returns AUTH_OK 77 * if the msg is successfully authenticated. If AUTH_OK then the routine also 78 * does the following things: 79 * set rqst->rq_xprt->verf to the appropriate response verifier; 80 * sets rqst->rq_client_cred to the "cooked" form of the credentials. 81 * 82 * NB: rqst->rq_cxprt->verf must be pre-alloctaed; 83 * its length is set appropriately. 84 * 85 * The caller still owns and is responsible for msg->u.cmb.cred and 86 * msg->u.cmb.verf. The authentication system retains ownership of 87 * rqst->rq_client_cred, the cooked credentials. 88 * 89 * There is an assumption that any flavor less than AUTH_NULL is 90 * invalid. 91 */ 92 enum auth_stat 93 sec_svc_msg(struct svc_req *rqst, struct rpc_msg *msg, bool_t *no_dispatch) 94 { 95 int cred_flavor; 96 97 rqst->rq_cred = msg->rm_call.cb_cred; 98 rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; 99 rqst->rq_xprt->xp_verf.oa_length = 0; 100 /* 101 * Init the xp_auth to be no-op for all the flavors. 102 * Flavor specific routines will revise this when appropriate. 103 */ 104 rqst->rq_xprt->xp_auth.svc_ah_ops = svc_authany_ops; 105 rqst->rq_xprt->xp_auth.svc_ah_private = NULL; 106 *no_dispatch = FALSE; 107 108 cred_flavor = rqst->rq_cred.oa_flavor; 109 110 switch (cred_flavor) { 111 case AUTH_NULL: 112 rqst->rq_xprt->xp_cookie = (void *) AUTH_NULL; 113 return (_svcauth_null(rqst, msg)); 114 115 case AUTH_UNIX: 116 rqst->rq_xprt->xp_cookie = (void *) AUTH_UNIX; 117 return (_svcauth_unix(rqst, msg)); 118 119 case AUTH_SHORT: 120 rqst->rq_xprt->xp_cookie = (void *) AUTH_SHORT; 121 return (_svcauth_short(rqst, msg)); 122 123 case AUTH_DES: 124 rqst->rq_xprt->xp_cookie = (void *) AUTH_DES; 125 return (_svcauth_des(rqst, msg)); 126 127 case RPCSEC_GSS: 128 /* 129 * RPCSEC_GSS flavor routine takes an additional 130 * boolean parameter that gets set to TRUE when 131 * the call is not to be dispatched to the server. 132 */ 133 return (__svcrpcsec_gss(rqst, msg, no_dispatch)); 134 } 135 return (AUTH_REJECTEDCRED); 136 } 137 138 /* 139 * sec_svc_getcred() gets unix cred of incoming security rpc requests. 140 * It also returns the prinicipal name and a cookie which is application 141 * dependent e.g. for nfs, it is the pseudo flavor. 142 * 143 * return 0 on failure 144 */ 145 int 146 sec_svc_getcred(struct svc_req *req, cred_t *cr, caddr_t *principal, 147 int *secmod) 148 { 149 struct authunix_parms *aup; 150 struct authdes_cred *adc; 151 int flavor, stat; 152 rpc_gss_rawcred_t *rcred; 153 rpc_gss_ucred_t *ucred; 154 void *cookie; 155 156 stat = 1; 157 flavor = req->rq_cred.oa_flavor; 158 159 *principal = NULL; 160 switch (flavor) { 161 case AUTH_UNIX: 162 *secmod = AUTH_UNIX; 163 aup = (struct authunix_parms *)req->rq_clntcred; 164 if (crsetugid(cr, aup->aup_uid, aup->aup_gid) != 0) 165 (void) crsetugid(cr, UID_NOBODY, GID_NOBODY); 166 if (crsetgroups(cr, aup->aup_len, aup->aup_gids) != 0) 167 (void) crsetgroups(cr, 0, NULL); 168 break; 169 170 case AUTH_NONE: 171 *secmod = AUTH_NONE; 172 break; 173 174 case AUTH_DES: 175 *secmod = AUTH_DES; 176 adc = (struct authdes_cred *)req->rq_clntcred; 177 stat = kauthdes_getucred(adc, cr); 178 *principal = adc->adc_fullname.name; 179 break; 180 181 case RPCSEC_GSS: 182 stat = rpc_gss_getcred(req, &rcred, &ucred, &cookie); 183 *secmod = (int)(uintptr_t)cookie; /* XX64 */ 184 if (ucred != NULL) { 185 if (crsetugid(cr, ucred->uid, ucred->gid) != 0 || 186 crsetgroups(cr, ucred->gidlen, ucred->gidlist) != 0) 187 stat = 0; 188 } else { 189 (void) crsetugid(cr, UID_NOBODY, GID_NOBODY); 190 (void) crsetgroups(cr, 0, NULL); 191 } 192 *principal = (caddr_t)rcred->client_principal; 193 break; 194 195 default: 196 stat = 0; 197 break; 198 } 199 200 return (stat); 201 } 202 203 204 /* ARGSUSED */ 205 enum auth_stat 206 _svcauth_null(struct svc_req *rqst, struct rpc_msg *msg) 207 { 208 return (AUTH_OK); 209 } 210 211 212 /* 213 * Load root principal names from user space to kernel space. 214 * 215 * flavor - security flavor 216 * count - number of principal names to be loaded 217 * proots - address of the array of root names. 218 * input is the array address in the user space, 219 * output is the kernel address. 220 * 221 * return 0 on failure. 222 */ 223 int 224 sec_svc_loadrootnames(int flavor, int count, caddr_t **proots, model_t model) 225 { 226 caddr_t *roots, *oroots, root; 227 char netname[MAXNETNAMELEN+1]; 228 struct rpc_gss_principal gsstmp, *gssname; 229 uint_t i, j; 230 size_t len, allocsz, oallocsz; 231 232 #ifdef lint 233 model = model; 234 #endif 235 236 /* 237 * Get list of names from user space 238 */ 239 allocsz = count * sizeof (caddr_t); 240 oallocsz = count * SIZEOF_PTR(model); 241 242 /* 243 * And now copy each individual principal name 244 */ 245 switch (flavor) { 246 case AUTH_DES: 247 roots = kmem_zalloc(allocsz, KM_SLEEP); 248 oroots = kmem_alloc(oallocsz, KM_SLEEP); 249 250 if (copyin(*proots, oroots, oallocsz)) 251 goto done; 252 253 for (i = 0; i < count; i++) { 254 /* 255 * copyinstr copies the complete string (including the 256 * NULL) and returns the len with the NULL byte 257 * included in the calculation as long as the max 258 * length is not exceeded. 259 */ 260 #ifdef _SYSCALL32_IMPL 261 if (model != DATAMODEL_NATIVE) { 262 caddr32_t *tmp; 263 264 tmp = (caddr32_t *)oroots; 265 root = (caddr_t)(uintptr_t)tmp[i]; 266 } else 267 #endif 268 root = oroots[i]; 269 if (copyinstr(root, netname, sizeof (netname), &len)) { 270 for (j = 0; j < i; j++) { 271 if (roots[j] != NULL) 272 kmem_free(roots[j], 273 strlen(roots[j]) + 1); 274 } 275 goto done; 276 } 277 roots[i] = kmem_alloc(len, KM_SLEEP); 278 bcopy(netname, roots[i], len); 279 } 280 kmem_free(oroots, oallocsz); 281 *proots = roots; 282 return (1); 283 284 case RPCSEC_GSS: 285 roots = kmem_alloc(allocsz, KM_SLEEP); 286 oroots = kmem_alloc(oallocsz, KM_SLEEP); 287 288 if (copyin(*proots, oroots, oallocsz)) 289 goto done; 290 291 for (i = 0; i < count; i++) { 292 #ifdef _SYSCALL32_IMPL 293 if (model != DATAMODEL_NATIVE) { 294 caddr32_t *tmp; 295 296 tmp = (caddr32_t *)oroots; 297 root = (caddr_t)(uintptr_t)tmp[i]; 298 } else 299 #endif 300 root = oroots[i]; 301 302 if (copyin(root, &gsstmp, sizeof (gsstmp))) { 303 kmem_free(oroots, oallocsz); 304 goto gssfreeup; 305 } 306 len = sizeof (gsstmp.len) + gsstmp.len; 307 gssname = kmem_alloc(len, KM_SLEEP); 308 if (copyin(root, gssname, len)) { 309 kmem_free(gssname, len); 310 kmem_free(oroots, oallocsz); 311 goto gssfreeup; 312 } 313 roots[i] = (caddr_t)gssname; 314 } 315 kmem_free(oroots, oallocsz); 316 *proots = roots; 317 return (1); 318 319 default: 320 return (0); 321 } 322 323 gssfreeup: 324 for (j = 0; j < i; j++) { 325 if (roots[j] != NULL) { 326 gssname = (rpc_gss_principal_t)roots[j]; 327 kmem_free(roots[j], gssname->len + 328 sizeof (gssname->len)); 329 } 330 } 331 done: 332 kmem_free(roots, allocsz); 333 return (0); 334 } 335 336 337 /* 338 * Figure out everything we allocated in a root principal name list in 339 * order to free it up. 340 */ 341 void 342 sec_svc_freerootnames(int flavor, int count, caddr_t *proots) 343 { 344 int i; 345 rpc_gss_principal_t gssname; 346 347 switch (flavor) { 348 case AUTH_DES: 349 for (i = 0; i < count; i++) 350 if (proots[i] != NULL) 351 kmem_free(proots[i], strlen(proots[i]) + 1); 352 break; 353 354 case RPCSEC_GSS: 355 for (i = 0; i < count; i++) { 356 if (proots[i] == NULL) 357 continue; 358 gssname = (rpc_gss_principal_t)proots[i]; 359 kmem_free(proots[i], gssname->len + sizeof (int)); 360 } 361 break; 362 363 } 364 kmem_free(proots, count * sizeof (caddr_t)); 365 } 366 367 /* 368 * Check if the given principal name is in the root principal list 369 */ 370 bool_t 371 sec_svc_inrootlist(int flavor, caddr_t rootname, int count, caddr_t *roots) 372 { 373 int i, tmp_len; 374 rpc_gss_principal_t gssp, tmp_gssp; 375 size_t namelen; 376 377 switch (flavor) { 378 case AUTH_DES: 379 namelen = strlen(rootname) + 1; 380 for (i = 0; i < count; i++) 381 if (bcmp(rootname, roots[i], namelen) == 0) 382 return (TRUE); 383 break; 384 385 case RPCSEC_GSS: 386 gssp = (rpc_gss_principal_t)rootname; 387 namelen = gssp->len; 388 for (i = 0; i < count; i++) { 389 tmp_gssp = (rpc_gss_principal_t)roots[i]; 390 tmp_len = tmp_gssp->len; 391 if ((namelen == tmp_len) && 392 (bcmp(&gssp->name[0], 393 &tmp_gssp->name[0], namelen) == 0)) 394 return (TRUE); 395 } 396 break; 397 } 398 return (FALSE); 399 } 400 401 /* 402 * Miscellaneout "control" functions manipulating global RPC security 403 * attributes for server applications. 404 */ 405 bool_t 406 sec_svc_control(uint_t cmd, void *argp) 407 { 408 bool_t result = FALSE; /* be paranoid */ 409 410 switch (cmd) { 411 case RPC_SVC_SET_GSS_CALLBACK: 412 result = rpc_gss_set_callback((rpc_gss_callback_t *)argp); 413 break; 414 default: 415 cmn_err(CE_WARN, "sec_svc_control: bad command (%d)", cmd); 416 result = FALSE; 417 break; 418 } 419 420 return (result); 421 } 422