174462Salfred/* $NetBSD: svc_auth.c,v 1.12 2000/07/06 03:10:35 christos Exp $ */ 274462Salfred 3258578Shrs/*- 4258578Shrs * Copyright (c) 2009, Sun Microsystems, Inc. 5258578Shrs * All rights reserved. 6258578Shrs * 7258578Shrs * Redistribution and use in source and binary forms, with or without 8258578Shrs * modification, are permitted provided that the following conditions are met: 9258578Shrs * - Redistributions of source code must retain the above copyright notice, 10258578Shrs * this list of conditions and the following disclaimer. 11258578Shrs * - Redistributions in binary form must reproduce the above copyright notice, 12258578Shrs * this list of conditions and the following disclaimer in the documentation 13258578Shrs * and/or other materials provided with the distribution. 14258578Shrs * - Neither the name of Sun Microsystems, Inc. nor the names of its 15258578Shrs * contributors may be used to endorse or promote products derived 16258578Shrs * from this software without specific prior written permission. 1726221Swpaul * 18258578Shrs * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19258578Shrs * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20258578Shrs * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21258578Shrs * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22258578Shrs * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23258578Shrs * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24258578Shrs * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25258578Shrs * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26258578Shrs * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27258578Shrs * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28258578Shrs * POSSIBILITY OF SUCH DAMAGE. 291901Swollman */ 3026221Swpaul/* 3126221Swpaul * Copyright (c) 1986-1991 by Sun Microsystems Inc. 3226221Swpaul */ 331901Swollman 34136581Sobrien#if defined(LIBC_SCCS) && !defined(lint) 35136581Sobrien#ident "@(#)svc_auth.c 1.16 94/04/24 SMI" 3626221Swpaulstatic char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro"; 371901Swollman#endif 3892990Sobrien#include <sys/cdefs.h> 3992990Sobrien__FBSDID("$FreeBSD$"); 401901Swollman 411901Swollman/* 4226221Swpaul * svc_auth.c, Server-side rpc authenticator interface. 431901Swollman * 441901Swollman */ 451901Swollman 4675094Siedowse#include "namespace.h" 4774462Salfred#include "reentrant.h" 4874462Salfred#include <sys/types.h> 4974462Salfred#include <rpc/rpc.h> 5026221Swpaul#include <stdlib.h> 5174462Salfred#include "un-namespace.h" 52156090Sdeischen#include "mt_misc.h" 531901Swollman 541901Swollman/* 558870Srgrimes * svcauthsw is the bdevsw of server side authentication. 568870Srgrimes * 571901Swollman * Server side authenticators are called from authenticate by 581901Swollman * using the client auth struct flavor field to index into svcauthsw. 598870Srgrimes * The server auth flavors must implement a routine that looks 608870Srgrimes * like: 618870Srgrimes * 621901Swollman * enum auth_stat 631901Swollman * flavorx_auth(rqst, msg) 6474462Salfred * struct svc_req *rqst; 6574462Salfred * struct rpc_msg *msg; 661901Swollman * 671901Swollman */ 681901Swollman 6926221Swpaul/* declarations to allow servers to specify new authentication flavors */ 7026221Swpaulstruct authsvc { 7126221Swpaul int flavor; 7292905Sobrien enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *); 7326221Swpaul struct authsvc *next; 741901Swollman}; 7526221Swpaulstatic struct authsvc *Auths = NULL; 761901Swollman 77182891Sdfrstruct svc_auth_ops svc_auth_null_ops; 78181344Sdfr 791901Swollman/* 801901Swollman * The call rpc message, msg has been obtained from the wire. The msg contains 811901Swollman * the raw form of credentials and verifiers. authenticate returns AUTH_OK 821901Swollman * if the msg is successfully authenticated. If AUTH_OK then the routine also 831901Swollman * does the following things: 841901Swollman * set rqst->rq_xprt->verf to the appropriate response verifier; 851901Swollman * sets rqst->rq_client_cred to the "cooked" form of the credentials. 861901Swollman * 871901Swollman * NB: rqst->rq_cxprt->verf must be pre-alloctaed; 881901Swollman * its length is set appropriately. 891901Swollman * 901901Swollman * The caller still owns and is responsible for msg->u.cmb.cred and 911901Swollman * msg->u.cmb.verf. The authentication system retains ownership of 921901Swollman * rqst->rq_client_cred, the cooked credentials. 931901Swollman * 941901Swollman * There is an assumption that any flavour less than AUTH_NULL is 951901Swollman * invalid. 961901Swollman */ 971901Swollmanenum auth_stat 98288113Srodrigc_authenticate(struct svc_req *rqst, struct rpc_msg *msg) 991901Swollman{ 10074462Salfred int cred_flavor; 10174462Salfred struct authsvc *asp; 10274462Salfred enum auth_stat dummy; 1031901Swollman 10474462Salfred/* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */ 10574462Salfred 1061901Swollman rqst->rq_cred = msg->rm_call.cb_cred; 107181344Sdfr SVC_AUTH(rqst->rq_xprt).svc_ah_ops = &svc_auth_null_ops; 108181344Sdfr SVC_AUTH(rqst->rq_xprt).svc_ah_private = NULL; 1091901Swollman rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; 1101901Swollman rqst->rq_xprt->xp_verf.oa_length = 0; 1111901Swollman cred_flavor = rqst->rq_cred.oa_flavor; 11226221Swpaul switch (cred_flavor) { 11326221Swpaul case AUTH_NULL: 11474462Salfred dummy = _svcauth_null(rqst, msg); 11574462Salfred return (dummy); 11674462Salfred case AUTH_SYS: 11774462Salfred dummy = _svcauth_unix(rqst, msg); 11874462Salfred return (dummy); 11926221Swpaul case AUTH_SHORT: 12074462Salfred dummy = _svcauth_short(rqst, msg); 12174462Salfred return (dummy); 12226221Swpaul#ifdef DES_BUILTIN 12326221Swpaul case AUTH_DES: 12474462Salfred dummy = _svcauth_des(rqst, msg); 12574462Salfred return (dummy); 12626221Swpaul#endif 12774462Salfred default: 12874462Salfred break; 1291901Swollman } 1301901Swollman 13126221Swpaul /* flavor doesn't match any of the builtin types, so try new ones */ 13274462Salfred mutex_lock(&authsvc_lock); 13326221Swpaul for (asp = Auths; asp; asp = asp->next) { 13426221Swpaul if (asp->flavor == cred_flavor) { 13526221Swpaul enum auth_stat as; 13626221Swpaul 13726221Swpaul as = (*asp->handler)(rqst, msg); 13874462Salfred mutex_unlock(&authsvc_lock); 13926221Swpaul return (as); 14026221Swpaul } 14126221Swpaul } 14274462Salfred mutex_unlock(&authsvc_lock); 14326221Swpaul 1441901Swollman return (AUTH_REJECTEDCRED); 1451901Swollman} 1461901Swollman 147181344Sdfr/* 148181344Sdfr * A set of null auth methods used by any authentication protocols 149181344Sdfr * that don't need to inspect or modify the message body. 150181344Sdfr */ 151181344Sdfrstatic bool_t 152287341Srodrigcsvcauth_null_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr) 153181344Sdfr{ 154181344Sdfr 155181344Sdfr return (xdr_func(xdrs, xdr_ptr)); 156181344Sdfr} 157181344Sdfr 158182891Sdfrstruct svc_auth_ops svc_auth_null_ops = { 159181344Sdfr svcauth_null_wrap, 160181344Sdfr svcauth_null_wrap, 161181344Sdfr}; 162181344Sdfr 16326221Swpaul/*ARGSUSED*/ 1641901Swollmanenum auth_stat 165287341Srodrigc_svcauth_null(struct svc_req *rqst, struct rpc_msg *msg) 1661901Swollman{ 1671901Swollman return (AUTH_OK); 1681901Swollman} 16926221Swpaul 17026221Swpaul/* 17126221Swpaul * Allow the rpc service to register new authentication types that it is 17226221Swpaul * prepared to handle. When an authentication flavor is registered, 17326221Swpaul * the flavor is checked against already registered values. If not 17426221Swpaul * registered, then a new Auths entry is added on the list. 17526221Swpaul * 17626221Swpaul * There is no provision to delete a registration once registered. 17726221Swpaul * 17826221Swpaul * This routine returns: 17926221Swpaul * 0 if registration successful 18026221Swpaul * 1 if flavor already registered 18126221Swpaul * -1 if can't register (errno set) 18226221Swpaul */ 18326221Swpaul 18426221Swpaulint 185287341Srodrigcsvc_auth_reg(int cred_flavor, 186287341Srodrigc enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)) 18726221Swpaul{ 18874462Salfred struct authsvc *asp; 18926221Swpaul 19026221Swpaul switch (cred_flavor) { 19126221Swpaul case AUTH_NULL: 19274462Salfred case AUTH_SYS: 19326221Swpaul case AUTH_SHORT: 19426221Swpaul#ifdef DES_BUILTIN 19526221Swpaul case AUTH_DES: 19626221Swpaul#endif 19726221Swpaul /* already registered */ 19826221Swpaul return (1); 19926221Swpaul 20026221Swpaul default: 20174462Salfred mutex_lock(&authsvc_lock); 20226221Swpaul for (asp = Auths; asp; asp = asp->next) { 20326221Swpaul if (asp->flavor == cred_flavor) { 20426221Swpaul /* already registered */ 20574462Salfred mutex_unlock(&authsvc_lock); 20626221Swpaul return (1); 20726221Swpaul } 20826221Swpaul } 20926221Swpaul 21026221Swpaul /* this is a new one, so go ahead and register it */ 21174462Salfred asp = mem_alloc(sizeof (*asp)); 21226221Swpaul if (asp == NULL) { 21374462Salfred mutex_unlock(&authsvc_lock); 21426221Swpaul return (-1); 21526221Swpaul } 21626221Swpaul asp->flavor = cred_flavor; 21726221Swpaul asp->handler = handler; 21826221Swpaul asp->next = Auths; 21926221Swpaul Auths = asp; 22074462Salfred mutex_unlock(&authsvc_lock); 22126221Swpaul break; 22226221Swpaul } 22326221Swpaul return (0); 22426221Swpaul} 225