xref: /titanic_50/usr/src/lib/libnsl/rpc/svc_auth.c (revision 8eea8e29cc4374d1ee24c25a07f45af132db3499)
1 /*
2  * CDDL HEADER START
3  *
4  * The contents of this file are subject to the terms of the
5  * Common Development and Distribution License, Version 1.0 only
6  * (the "License").  You may not use this file except in compliance
7  * with the License.
8  *
9  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10  * or http://www.opensolaris.org/os/licensing.
11  * See the License for the specific language governing permissions
12  * and limitations under the License.
13  *
14  * When distributing Covered Code, include this CDDL HEADER in each
15  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16  * If applicable, add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your own identifying
18  * information: Portions Copyright [yyyy] [name of copyright owner]
19  *
20  * CDDL HEADER END
21  *
22  * Copyright 2003 Sun Microsystems, Inc.  All rights reserved.
23  * Use is subject to license terms.
24  */
25 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */
26 /* All Rights Reserved */
27 /*
28  * Portions of this source code were derived from Berkeley
29  * 4.3 BSD under license from the Regents of the University of
30  * California.
31  */
32 
33 #pragma ident	"%Z%%M%	%I%	%E% SMI"
34 
35 /*
36  * svc_auth.c, Server-side rpc authenticator interface.
37  *
38  */
39 
40 #include "mt.h"
41 #include "rpc_mt.h"
42 #include <rpc/rpc.h>
43 #include <sys/types.h>
44 #include <rpc/trace.h>
45 #include <stdlib.h>
46 
47 /*
48  * svcauthsw is the bdevsw of server side authentication.
49  *
50  * Server side authenticators are called from authenticate by
51  * using the client auth struct flavor field to index into svcauthsw.
52  * The server auth flavors must implement a routine that looks
53  * like:
54  *
55  *	enum auth_stat
56  *	flavorx_auth(rqst, msg)
57  *		struct svc_req *rqst;
58  *		struct rpc_msg *msg;
59  *
60  * The RPCSEC_GSS flavor is an exception.  Its routine takes an
61  * additional boolean parameter that gets set to TRUE when the call
62  * is not to be dispatched to the server.
63  */
64 
65 enum auth_stat __svcauth_null();	/* no authentication */
66 enum auth_stat __svcauth_sys();		/* (system) unix style (uid, gids) */
67 enum auth_stat __svcauth_short();	/* short hand unix style */
68 enum auth_stat __svcauth_des();		/* des style */
69 enum auth_stat __svcauth_loopback();	/* (loopback) unix style (uid, gids) */
70 extern enum auth_stat __svcrpcsec_gss();	/* GSS style */
71 
72 /* declarations to allow servers to specify new authentication flavors */
73 struct authsvc {
74 	int	flavor;
75 	enum	auth_stat (*handler)();
76 	struct	authsvc	  *next;
77 };
78 static struct authsvc *Auths = NULL;
79 
80 /*
81  * The call rpc message, msg has been obtained from the wire.  The msg contains
82  * the raw form of credentials and verifiers.  no_dispatch is used and
83  * dereferenced in subsequent gss function calls.  authenticate returns AUTH_OK
84  * if the msg is successfully authenticated.  If AUTH_OK then the routine also
85  * does the following things:
86  * set rqst->rq_xprt->verf to the appropriate response verifier;
87  * sets rqst->rq_client_cred to the "cooked" form of the credentials.
88  *
89  * NB: rqst->rq_cxprt->verf must be pre-alloctaed;
90  * its length is set appropriately.
91  *
92  * The caller still owns and is responsible for msg->u.cmb.cred and
93  * msg->u.cmb.verf.  The authentication system retains ownership of
94  * rqst->rq_client_cred, the cooked credentials.
95  *
96  * There is an assumption that any flavour less than AUTH_NULL is
97  * invalid.
98  */
99 enum auth_stat
100 __gss_authenticate(rqst, msg, no_dispatch)
101 	struct svc_req *rqst;
102 	struct rpc_msg *msg;
103 	bool_t *no_dispatch;
104 {
105 	int cred_flavor;
106 	struct authsvc *asp;
107 	enum auth_stat dummy;
108 	extern mutex_t authsvc_lock;
109 
110 /* VARIABLES PROTECTED BY authsvc_lock: asp, Auths */
111 
112 	trace1(TR___gss_authenticate, 0);
113 	rqst->rq_cred = msg->rm_call.cb_cred;
114 	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;
115 	rqst->rq_xprt->xp_verf.oa_length = 0;
116 	cred_flavor = rqst->rq_cred.oa_flavor;
117 	*no_dispatch = FALSE;
118 	switch (cred_flavor) {
119 	case AUTH_NULL:
120 		dummy = __svcauth_null(rqst, msg);
121 		trace1(TR___gss_authenticate, 1);
122 		return (dummy);
123 	case AUTH_SYS:
124 		dummy = __svcauth_sys(rqst, msg);
125 		trace1(TR___gss_authenticate, 1);
126 		return (dummy);
127 	case AUTH_SHORT:
128 		dummy = __svcauth_short(rqst, msg);
129 		trace1(TR___gss_authenticate, 1);
130 		return (dummy);
131 	case AUTH_DES:
132 		dummy = __svcauth_des(rqst, msg);
133 		trace1(TR___gss_authenticate, 1);
134 		return (dummy);
135 	case AUTH_LOOPBACK:
136 		dummy = __svcauth_loopback(rqst, msg);
137 		trace1(TR___gss_authenticate, 1);
138 		return (dummy);
139 	case RPCSEC_GSS:
140 		dummy = __svcrpcsec_gss(rqst, msg, no_dispatch);
141 		trace1(TR___gss_authenticate, 1);
142 		return (dummy);
143 	}
144 
145 	/* flavor doesn't match any of the builtin types, so try new ones */
146 	mutex_lock(&authsvc_lock);
147 	for (asp = Auths; asp; asp = asp->next) {
148 		if (asp->flavor == cred_flavor) {
149 			enum auth_stat as;
150 
151 			as = (*asp->handler)(rqst, msg);
152 			mutex_unlock(&authsvc_lock);
153 			trace1(TR___gss_authenticate, 1);
154 			return (as);
155 		}
156 	}
157 	mutex_unlock(&authsvc_lock);
158 
159 	trace1(TR___gss_authenticate, 1);
160 	return (AUTH_REJECTEDCRED);
161 }
162 
163 /*
164  * The following function __authenticate(rqst, msg) is preserved for
165  * backward compatibility.
166  */
167 enum auth_stat
168 __authenticate(rqst, msg)
169 	struct svc_req *rqst;
170 	struct rpc_msg *msg;
171 {
172 	bool_t no_dispatch;
173 	enum auth_stat st;
174 
175 	trace1(TR___authenticate, 0);
176 
177 	st = __gss_authenticate(rqst, msg, &no_dispatch);
178 
179 	trace1(TR___authenticate, 1);
180 	return (st);
181 }
182 
183 /*ARGSUSED*/
184 enum auth_stat
185 __svcauth_null(rqst, msg)
186 	struct svc_req *rqst;
187 	struct rpc_msg *msg;
188 {
189 	trace1(TR___svcauth_null, 0);
190 	trace1(TR___svcauth_null, 1);
191 	return (AUTH_OK);
192 }
193 
194 /*
195  *  Allow the rpc service to register new authentication types that it is
196  *  prepared to handle.  When an authentication flavor is registered,
197  *  the flavor is checked against already registered values.  If not
198  *  registered, then a new Auths entry is added on the list.
199  *
200  *  There is no provision to delete a registration once registered.
201  *
202  *  This routine returns:
203  *	 0 if registration successful
204  *	 1 if flavor already registered
205  *	-1 if can't register (errno set)
206  */
207 
208 int
209 svc_auth_reg(cred_flavor, handler)
210 	int cred_flavor;
211 	enum auth_stat (*handler)();
212 {
213 	struct authsvc *asp;
214 	extern mutex_t authsvc_lock;
215 
216 	trace2(TR_svc_auth_reg, 0, cred_flavor);
217 	switch (cred_flavor) {
218 	    case AUTH_NULL:
219 	    case AUTH_SYS:
220 	    case AUTH_SHORT:
221 	    case AUTH_DES:
222 	    case AUTH_LOOPBACK:
223 	    case RPCSEC_GSS:
224 		/* already registered */
225 		trace1(TR_svc_auth_reg, 1);
226 		return (1);
227 
228 	    default:
229 		mutex_lock(&authsvc_lock);
230 		for (asp = Auths; asp; asp = asp->next) {
231 			if (asp->flavor == cred_flavor) {
232 				/* already registered */
233 				mutex_unlock(&authsvc_lock);
234 				trace1(TR_svc_auth_reg, 1);
235 				return (1);
236 			}
237 		}
238 
239 		/* this is a new one, so go ahead and register it */
240 		asp = (struct authsvc *)mem_alloc(sizeof (*asp));
241 		if (asp == NULL) {
242 			mutex_unlock(&authsvc_lock);
243 			trace1(TR_svc_auth_reg, 1);
244 			return (-1);
245 		}
246 		asp->flavor = cred_flavor;
247 		asp->handler = handler;
248 		asp->next = Auths;
249 		Auths = asp;
250 		mutex_unlock(&authsvc_lock);
251 		break;
252 	}
253 	trace1(TR_svc_auth_reg, 1);
254 	return (0);
255 }
256