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