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