1 /* $NetBSD: svc_auth.c,v 1.17 2013/03/11 20:19:29 tron Exp $ */ 2 3 /* 4 * Copyright (c) 2010, Oracle America, Inc. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions are 8 * met: 9 * 10 * * Redistributions of source code must retain the above copyright 11 * notice, this list of conditions and the following disclaimer. 12 * * Redistributions in binary form must reproduce the above 13 * copyright notice, this list of conditions and the following 14 * disclaimer in the documentation and/or other materials 15 * provided with the distribution. 16 * * Neither the name of the "Oracle America, Inc." nor the names of its 17 * contributors may be used to endorse or promote products derived 18 * from this software without specific prior written permission. 19 * 20 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 21 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 22 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 23 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 24 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 25 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE 27 * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, 29 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 30 * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE 31 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32 */ 33 /* 34 * Copyright (c) 1986-1991 by Sun Microsystems Inc. 35 */ 36 37 /* #ident "@(#)svc_auth.c 1.16 94/04/24 SMI" */ 38 39 #include <sys/cdefs.h> 40 #if defined(LIBC_SCCS) && !defined(lint) 41 #if 0 42 static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro"; 43 #else 44 __RCSID("$NetBSD: svc_auth.c,v 1.17 2013/03/11 20:19:29 tron Exp $"); 45 #endif 46 #endif 47 48 /* 49 * svc_auth.c, Server-side rpc authenticator interface. 50 * 51 */ 52 53 #include "namespace.h" 54 #include "reentrant.h" 55 #include <sys/types.h> 56 #include <rpc/rpc.h> 57 #include <assert.h> 58 #include <stdlib.h> 59 60 #ifdef __weak_alias 61 __weak_alias(svc_auth_reg,_svc_auth_reg) 62 #endif 63 64 /* 65 * svcauthsw is the bdevsw of server side authentication. 66 * 67 * Server side authenticators are called from authenticate by 68 * using the client auth struct flavor field to index into svcauthsw. 69 * The server auth flavors must implement a routine that looks 70 * like: 71 * 72 * enum auth_stat 73 * flavorx_auth(rqst, msg) 74 * struct svc_req *rqst; 75 * struct rpc_msg *msg; 76 * 77 */ 78 79 /* declarations to allow servers to specify new authentication flavors */ 80 struct authsvc { 81 int flavor; 82 enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *); 83 struct authsvc *next; 84 }; 85 static struct authsvc *Auths = NULL; 86 87 /* 88 * The call rpc message, msg has been obtained from the wire. The msg contains 89 * the raw form of credentials and verifiers. authenticate returns AUTH_OK 90 * if the msg is successfully authenticated. If AUTH_OK then the routine also 91 * does the following things: 92 * set rqst->rq_xprt->verf to the appropriate response verifier; 93 * sets rqst->rq_client_cred to the "cooked" form of the credentials. 94 * 95 * NB: rqst->rq_cxprt->verf must be pre-alloctaed; 96 * its length is set appropriately. 97 * 98 * The caller still owns and is responsible for msg->u.cmb.cred and 99 * msg->u.cmb.verf. The authentication system retains ownership of 100 * rqst->rq_client_cred, the cooked credentials. 101 * 102 * There is an assumption that any flavour less than AUTH_NULL is 103 * invalid. 104 */ 105 enum auth_stat 106 _authenticate(struct svc_req *rqst, struct rpc_msg *msg) 107 { 108 int cred_flavor; 109 struct authsvc *asp; 110 enum auth_stat dummy; 111 #ifdef _REENTRANT 112 extern mutex_t authsvc_lock; 113 #endif 114 115 _DIAGASSERT(rqst != NULL); 116 _DIAGASSERT(msg != NULL); 117 118 /* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */ 119 120 rqst->rq_cred = msg->rm_call.cb_cred; 121 rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor; 122 rqst->rq_xprt->xp_verf.oa_length = 0; 123 cred_flavor = rqst->rq_cred.oa_flavor; 124 switch (cred_flavor) { 125 case AUTH_NULL: 126 dummy = _svcauth_null(rqst, msg); 127 return (dummy); 128 case AUTH_SYS: 129 dummy = _svcauth_unix(rqst, msg); 130 return (dummy); 131 case AUTH_SHORT: 132 dummy = _svcauth_short(rqst, msg); 133 return (dummy); 134 #if 0 135 case AUTH_DES: 136 dummy = __svcauth_des(rqst, msg); 137 return (dummy); 138 #endif 139 default: 140 break; 141 } 142 143 /* flavor doesn't match any of the builtin types, so try new ones */ 144 mutex_lock(&authsvc_lock); 145 for (asp = Auths; asp; asp = asp->next) { 146 if (asp->flavor == cred_flavor) { 147 enum auth_stat as; 148 149 as = (*asp->handler)(rqst, msg); 150 mutex_unlock(&authsvc_lock); 151 return (as); 152 } 153 } 154 mutex_unlock(&authsvc_lock); 155 156 return (AUTH_REJECTEDCRED); 157 } 158 159 /*ARGSUSED*/ 160 enum auth_stat 161 _svcauth_null(struct svc_req *rqst, struct rpc_msg *msg) 162 { 163 return (AUTH_OK); 164 } 165 166 /* 167 * Allow the rpc service to register new authentication types that it is 168 * prepared to handle. When an authentication flavor is registered, 169 * the flavor is checked against already registered values. If not 170 * registered, then a new Auths entry is added on the list. 171 * 172 * There is no provision to delete a registration once registered. 173 * 174 * This routine returns: 175 * 0 if registration successful 176 * 1 if flavor already registered 177 * -1 if can't register (errno set) 178 */ 179 180 int 181 svc_auth_reg( 182 int cred_flavor, 183 enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *)) 184 { 185 struct authsvc *asp; 186 #ifdef _REENTRANT 187 extern mutex_t authsvc_lock; 188 #endif 189 190 switch (cred_flavor) { 191 case AUTH_NULL: 192 case AUTH_SYS: 193 case AUTH_SHORT: 194 #if 0 195 case AUTH_DES: 196 #endif 197 /* already registered */ 198 return (1); 199 200 default: 201 mutex_lock(&authsvc_lock); 202 for (asp = Auths; asp; asp = asp->next) { 203 if (asp->flavor == cred_flavor) { 204 /* already registered */ 205 mutex_unlock(&authsvc_lock); 206 return (1); 207 } 208 } 209 210 /* this is a new one, so go ahead and register it */ 211 asp = mem_alloc(sizeof (*asp)); 212 if (asp == NULL) { 213 mutex_unlock(&authsvc_lock); 214 return (-1); 215 } 216 asp->flavor = cred_flavor; 217 asp->handler = handler; 218 asp->next = Auths; 219 Auths = asp; 220 mutex_unlock(&authsvc_lock); 221 break; 222 } 223 return (0); 224 } 225