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 /*
23 * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
25 */
26
27 /* Copyright (c) 1984, 1986, 1987, 1988, 1989 AT&T */
28 /* All Rights Reserved */
29
30 /*
31 * Portions of this source code were derived from Berkeley 4.3 BSD
32 * under license from the Regents of the University of California.
33 */
34
35 #pragma ident "%Z%%M% %I% %E% SMI"
36
37 /*
38 * auth_loopb.c, implements UNIX style authentication parameters in the
39 * kernel. Interfaces with svc_auth_loopback on the server. See
40 * auth_loopb.c for the user level implementation of the loopback auth.
41 *
42 */
43
44 #include <sys/param.h>
45 #include <sys/time.h>
46 #include <sys/types.h>
47 #include <sys/systm.h>
48 #include <sys/user.h>
49 #include <sys/proc.h>
50 #include <sys/utsname.h>
51 #include <sys/cred.h>
52 #include <sys/kmem.h>
53 #include <sys/sysmacros.h>
54 #include <sys/cmn_err.h>
55
56 #include <rpc/types.h>
57 #include <rpc/xdr.h>
58 #include <rpc/auth.h>
59 #include <rpc/auth_unix.h>
60 #include <rpc/clnt.h>
61 #include <rpc/rpc_msg.h>
62
63 /*
64 * Unix authenticator operations vector
65 */
66 static void authloopback_nextverf(AUTH *);
67 static bool_t authloopback_marshal(AUTH *, XDR *, struct cred *);
68 static bool_t authloopback_validate(AUTH *, struct opaque_auth *);
69 static bool_t authloopback_refresh(AUTH *, struct rpc_msg *, cred_t *);
70 static void authloopback_destroy(AUTH *);
71
72 static struct auth_ops authloopback_ops = {
73 authloopback_nextverf,
74 authloopback_marshal,
75 authloopback_validate,
76 authloopback_refresh,
77 authloopback_destroy,
78 authany_wrap,
79 authany_unwrap
80 };
81
82 /*
83 * Create a kernel unix style authenticator.
84 * Returns an auth handle.
85 */
86 AUTH *
authloopback_create(void)87 authloopback_create(void)
88 {
89 /*
90 * Allocate and set up auth handle
91 */
92 return (kmem_cache_alloc(authloopback_cache, KM_SLEEP));
93 }
94
95 /*
96 * The constructor of the authloopback_cache.
97 */
98 /* ARGSUSED */
99 int
authloopback_init(void * buf,void * cdrarg,int kmflags)100 authloopback_init(void *buf, void *cdrarg, int kmflags)
101 {
102 AUTH *auth = (AUTH *)buf;
103
104 auth->ah_ops = &authloopback_ops;
105 auth->ah_cred.oa_flavor = AUTH_LOOPBACK;
106 auth->ah_verf = _null_auth;
107
108 return (0);
109 }
110
111 /*
112 * authloopback operations
113 */
114 /* ARGSUSED */
115 static void
authloopback_nextverf(AUTH * auth)116 authloopback_nextverf(AUTH *auth)
117 {
118
119 /* no action necessary */
120 }
121
122 static bool_t
authloopback_marshal(AUTH * auth,XDR * xdrs,struct cred * cr)123 authloopback_marshal(AUTH *auth, XDR *xdrs, struct cred *cr)
124 {
125 char *sercred;
126 XDR xdrm;
127 struct opaque_auth *cred;
128 bool_t ret = FALSE;
129 const gid_t *gp, *gpend;
130 int gidlen, credsize, namelen, rounded_namelen;
131 int32_t *ptr;
132
133 /*
134 * First we try a fast path to get through
135 * this very common operation.
136 */
137 gp = crgetgroups(cr);
138 gidlen = crgetngroups(cr);
139 if (gidlen > NGRPS_LOOPBACK)
140 return (FALSE);
141 gpend = &gp[gidlen-1];
142
143 namelen = (int)strlen(uts_nodename());
144 rounded_namelen = RNDUP(namelen);
145 credsize = 4 + 4 + rounded_namelen + 4 + 4 + 4 + gidlen * 4;
146 ptr = XDR_INLINE(xdrs, 4 + 4 + credsize + 4 + 4);
147 if (ptr) {
148 /*
149 * We can do the fast path.
150 */
151 IXDR_PUT_INT32(ptr, AUTH_LOOPBACK); /* cred flavor */
152 IXDR_PUT_INT32(ptr, credsize); /* cred len */
153 IXDR_PUT_INT32(ptr, gethrestime_sec());
154 IXDR_PUT_INT32(ptr, namelen);
155 bcopy(uts_nodename(), ptr, namelen);
156 if (rounded_namelen - namelen)
157 bzero(((caddr_t)ptr) + namelen,
158 rounded_namelen - namelen);
159 ptr += rounded_namelen / BYTES_PER_XDR_UNIT;
160 IXDR_PUT_INT32(ptr, crgetuid(cr));
161 IXDR_PUT_INT32(ptr, crgetgid(cr));
162 IXDR_PUT_INT32(ptr, gidlen);
163 while (gp <= gpend) {
164 IXDR_PUT_INT32(ptr, *gp++);
165 }
166 IXDR_PUT_INT32(ptr, AUTH_NULL); /* verf flavor */
167 IXDR_PUT_INT32(ptr, 0); /* verf len */
168 return (TRUE);
169 }
170 sercred = kmem_alloc(MAX_AUTH_BYTES, KM_SLEEP);
171 /*
172 * serialize u struct stuff into sercred
173 */
174 xdrmem_create(&xdrm, sercred, MAX_AUTH_BYTES, XDR_ENCODE);
175 if (!xdr_authloopback(&xdrm)) {
176 printf("authloopback_marshal: xdr_authloopback failed\n");
177 ret = FALSE;
178 goto done;
179 }
180
181 /*
182 * Make opaque auth credentials that point at serialized u struct
183 */
184 cred = &(auth->ah_cred);
185 cred->oa_length = XDR_GETPOS(&xdrm);
186 cred->oa_base = sercred;
187
188 /*
189 * serialize credentials and verifiers (null)
190 */
191 if ((xdr_opaque_auth(xdrs, &(auth->ah_cred))) &&
192 (xdr_opaque_auth(xdrs, &(auth->ah_verf))))
193 ret = TRUE;
194 else
195 ret = FALSE;
196 done:
197 kmem_free(sercred, MAX_AUTH_BYTES);
198 return (ret);
199 }
200
201 /* ARGSUSED */
202 static bool_t
authloopback_validate(AUTH * auth,struct opaque_auth * verf)203 authloopback_validate(AUTH *auth, struct opaque_auth *verf)
204 {
205 return (TRUE);
206 }
207
208 /* ARGSUSED */
209 static bool_t
authloopback_refresh(AUTH * auth,struct rpc_msg * msg,cred_t * cr)210 authloopback_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr)
211 {
212 return (FALSE);
213 }
214
215 static void
authloopback_destroy(register AUTH * auth)216 authloopback_destroy(register AUTH *auth)
217 {
218 kmem_cache_free(authloopback_cache, auth);
219 }
220