xref: /freebsd/lib/libc/rpc/svc_auth.c (revision e0c4386e7e71d93b0edc0c8fa156263fc4a8b0b6)
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 /*
37  * svc_auth.c, Server-side rpc authenticator interface.
38  *
39  */
40 
41 #include "namespace.h"
42 #include "reentrant.h"
43 #include <sys/types.h>
44 #include <rpc/rpc.h>
45 #include <stdlib.h>
46 #include "un-namespace.h"
47 #include "mt_misc.h"
48 
49 /*
50  * svcauthsw is the bdevsw of server side authentication.
51  *
52  * Server side authenticators are called from authenticate by
53  * using the client auth struct flavor field to index into svcauthsw.
54  * The server auth flavors must implement a routine that looks
55  * like:
56  *
57  *	enum auth_stat
58  *	flavorx_auth(rqst, msg)
59  *		struct svc_req *rqst;
60  *		struct rpc_msg *msg;
61  *
62  */
63 
64 /* declarations to allow servers to specify new authentication flavors */
65 struct authsvc {
66 	int	flavor;
67 	enum	auth_stat (*handler)(struct svc_req *, struct rpc_msg *);
68 	struct	authsvc	  *next;
69 };
70 static struct authsvc *Auths = NULL;
71 
72 struct svc_auth_ops svc_auth_null_ops;
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-allocated;
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 flavour less than AUTH_NULL is
90  * invalid.
91  */
92 enum auth_stat
93 _authenticate(struct svc_req *rqst, struct rpc_msg *msg)
94 {
95 	int cred_flavor;
96 	struct authsvc *asp;
97 	enum auth_stat dummy;
98 
99 /* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */
100 
101 	rqst->rq_cred = msg->rm_call.cb_cred;
102 	SVC_AUTH(rqst->rq_xprt).svc_ah_ops = &svc_auth_null_ops;
103 	SVC_AUTH(rqst->rq_xprt).svc_ah_private = NULL;
104 	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
105 	rqst->rq_xprt->xp_verf.oa_length = 0;
106 	cred_flavor = rqst->rq_cred.oa_flavor;
107 	switch (cred_flavor) {
108 	case AUTH_NULL:
109 		dummy = _svcauth_null(rqst, msg);
110 		return (dummy);
111 	case AUTH_SYS:
112 		dummy = _svcauth_unix(rqst, msg);
113 		return (dummy);
114 	case AUTH_SHORT:
115 		dummy = _svcauth_short(rqst, msg);
116 		return (dummy);
117 #ifdef DES_BUILTIN
118 	case AUTH_DES:
119 		dummy = _svcauth_des(rqst, msg);
120 		return (dummy);
121 #endif
122 	default:
123 		break;
124 	}
125 
126 	/* flavor doesn't match any of the builtin types, so try new ones */
127 	mutex_lock(&authsvc_lock);
128 	for (asp = Auths; asp; asp = asp->next) {
129 		if (asp->flavor == cred_flavor) {
130 			enum auth_stat as;
131 
132 			as = (*asp->handler)(rqst, msg);
133 			mutex_unlock(&authsvc_lock);
134 			return (as);
135 		}
136 	}
137 	mutex_unlock(&authsvc_lock);
138 
139 	return (AUTH_REJECTEDCRED);
140 }
141 
142 /*
143  * A set of null auth methods used by any authentication protocols
144  * that don't need to inspect or modify the message body.
145  */
146 static bool_t
147 svcauth_null_wrap(SVCAUTH *auth, XDR *xdrs, xdrproc_t xdr_func, caddr_t xdr_ptr)
148 {
149 
150 	return (xdr_func(xdrs, xdr_ptr));
151 }
152 
153 struct svc_auth_ops svc_auth_null_ops = {
154 	svcauth_null_wrap,
155 	svcauth_null_wrap,
156 };
157 
158 /*ARGSUSED*/
159 enum auth_stat
160 _svcauth_null(struct svc_req *rqst, struct rpc_msg *msg)
161 {
162 	return (AUTH_OK);
163 }
164 
165 /*
166  *  Allow the rpc service to register new authentication types that it is
167  *  prepared to handle.  When an authentication flavor is registered,
168  *  the flavor is checked against already registered values.  If not
169  *  registered, then a new Auths entry is added on the list.
170  *
171  *  There is no provision to delete a registration once registered.
172  *
173  *  This routine returns:
174  *	 0 if registration successful
175  *	 1 if flavor already registered
176  *	-1 if can't register (errno set)
177  */
178 
179 int
180 svc_auth_reg(int cred_flavor,
181     enum auth_stat (*handler)(struct svc_req *, struct rpc_msg *))
182 {
183 	struct authsvc *asp;
184 
185 	switch (cred_flavor) {
186 	    case AUTH_NULL:
187 	    case AUTH_SYS:
188 	    case AUTH_SHORT:
189 #ifdef DES_BUILTIN
190 	    case AUTH_DES:
191 #endif
192 		/* already registered */
193 		return (1);
194 
195 	    default:
196 		mutex_lock(&authsvc_lock);
197 		for (asp = Auths; asp; asp = asp->next) {
198 			if (asp->flavor == cred_flavor) {
199 				/* already registered */
200 				mutex_unlock(&authsvc_lock);
201 				return (1);
202 			}
203 		}
204 
205 		/* this is a new one, so go ahead and register it */
206 		asp = mem_alloc(sizeof (*asp));
207 		if (asp == NULL) {
208 			mutex_unlock(&authsvc_lock);
209 			return (-1);
210 		}
211 		asp->flavor = cred_flavor;
212 		asp->handler = handler;
213 		asp->next = Auths;
214 		Auths = asp;
215 		mutex_unlock(&authsvc_lock);
216 		break;
217 	}
218 	return (0);
219 }
220