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