1 /* $NetBSD: auth_unix.c,v 1.18 2000/07/06 03:03:30 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2009, Sun Microsystems, Inc. 5 * All rights reserved. 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions are met: 9 * - Redistributions of source code must retain the above copyright notice, 10 * this list of conditions and the following disclaimer. 11 * - Redistributions in binary form must reproduce the above copyright notice, 12 * this list of conditions and the following disclaimer in the documentation 13 * and/or other materials provided with the distribution. 14 * - Neither the name of Sun Microsystems, Inc. nor the names of its 15 * contributors may be used to endorse or promote products derived 16 * from this software without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE 22 * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28 * POSSIBILITY OF SUCH DAMAGE. 29 */ 30 31 #if defined(LIBC_SCCS) && !defined(lint) 32 static char *sccsid2 = "@(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro"; 33 static char *sccsid = "@(#)auth_unix.c 2.2 88/08/01 4.0 RPCSRC"; 34 #endif 35 #include <sys/cdefs.h> 36 __FBSDID("$FreeBSD$"); 37 38 /* 39 * auth_unix.c, Implements UNIX style authentication parameters. 40 * 41 * Copyright (C) 1984, Sun Microsystems, Inc. 42 * 43 * The system is very weak. The client uses no encryption for it's 44 * credentials and only sends null verifiers. The server sends backs 45 * null verifiers or optionally a verifier that suggests a new short hand 46 * for the credentials. 47 * 48 */ 49 50 #include "namespace.h" 51 #include "reentrant.h" 52 #include <sys/param.h> 53 54 #include <assert.h> 55 #include <err.h> 56 #include <stdio.h> 57 #include <stdlib.h> 58 #include <unistd.h> 59 #include <string.h> 60 61 #include <rpc/types.h> 62 #include <rpc/xdr.h> 63 #include <rpc/auth.h> 64 #include <rpc/auth_unix.h> 65 #include "un-namespace.h" 66 #include "mt_misc.h" 67 68 /* auth_unix.c */ 69 static void authunix_nextverf (AUTH *); 70 static bool_t authunix_marshal (AUTH *, XDR *); 71 static bool_t authunix_validate (AUTH *, struct opaque_auth *); 72 static bool_t authunix_refresh (AUTH *, void *); 73 static void authunix_destroy (AUTH *); 74 static void marshal_new_auth (AUTH *); 75 static struct auth_ops *authunix_ops (void); 76 77 /* 78 * This struct is pointed to by the ah_private field of an auth_handle. 79 */ 80 struct audata { 81 struct opaque_auth au_origcred; /* original credentials */ 82 struct opaque_auth au_shcred; /* short hand cred */ 83 u_long au_shfaults; /* short hand cache faults */ 84 char au_marshed[MAX_AUTH_BYTES]; 85 u_int au_mpos; /* xdr pos at end of marshed */ 86 }; 87 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 88 89 /* 90 * Create a unix style authenticator. 91 * Returns an auth handle with the given stuff in it. 92 */ 93 AUTH * 94 authunix_create(char *machname, u_int uid, u_int gid, int len, u_int *aup_gids) 95 { 96 struct authunix_parms aup; 97 char mymem[MAX_AUTH_BYTES]; 98 struct timeval now; 99 XDR xdrs; 100 AUTH *auth; 101 struct audata *au; 102 103 /* 104 * Allocate and set up auth handle 105 */ 106 au = NULL; 107 auth = mem_alloc(sizeof(*auth)); 108 #ifndef _KERNEL 109 if (auth == NULL) { 110 warnx("authunix_create: out of memory"); 111 goto cleanup_authunix_create; 112 } 113 #endif 114 au = mem_alloc(sizeof(*au)); 115 #ifndef _KERNEL 116 if (au == NULL) { 117 warnx("authunix_create: out of memory"); 118 goto cleanup_authunix_create; 119 } 120 #endif 121 auth->ah_ops = authunix_ops(); 122 auth->ah_private = (caddr_t)au; 123 auth->ah_verf = au->au_shcred = _null_auth; 124 au->au_shfaults = 0; 125 au->au_origcred.oa_base = NULL; 126 127 /* 128 * fill in param struct from the given params 129 */ 130 (void)gettimeofday(&now, NULL); 131 aup.aup_time = now.tv_sec; 132 aup.aup_machname = machname; 133 aup.aup_uid = uid; 134 aup.aup_gid = gid; 135 aup.aup_len = (u_int)len; 136 aup.aup_gids = aup_gids; 137 138 /* 139 * Serialize the parameters into origcred 140 */ 141 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 142 if (! xdr_authunix_parms(&xdrs, &aup)) 143 abort(); 144 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 145 au->au_origcred.oa_flavor = AUTH_UNIX; 146 #ifdef _KERNEL 147 au->au_origcred.oa_base = mem_alloc((u_int) len); 148 #else 149 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 150 warnx("authunix_create: out of memory"); 151 goto cleanup_authunix_create; 152 } 153 #endif 154 memmove(au->au_origcred.oa_base, mymem, (size_t)len); 155 156 /* 157 * set auth handle to reflect new cred. 158 */ 159 auth->ah_cred = au->au_origcred; 160 marshal_new_auth(auth); 161 return (auth); 162 #ifndef _KERNEL 163 cleanup_authunix_create: 164 if (auth) 165 mem_free(auth, sizeof(*auth)); 166 if (au) { 167 if (au->au_origcred.oa_base) 168 mem_free(au->au_origcred.oa_base, (u_int)len); 169 mem_free(au, sizeof(*au)); 170 } 171 return (NULL); 172 #endif 173 } 174 175 /* 176 * Returns an auth handle with parameters determined by doing lots of 177 * syscalls. 178 */ 179 AUTH * 180 authunix_create_default(void) 181 { 182 AUTH *auth; 183 int ngids; 184 long ngids_max; 185 char machname[MAXHOSTNAMELEN + 1]; 186 uid_t uid; 187 gid_t gid; 188 gid_t *gids; 189 190 ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 191 gids = malloc(sizeof(gid_t) * ngids_max); 192 if (gids == NULL) 193 return (NULL); 194 195 if (gethostname(machname, sizeof machname) == -1) 196 abort(); 197 machname[sizeof(machname) - 1] = 0; 198 uid = geteuid(); 199 gid = getegid(); 200 if ((ngids = getgroups(ngids_max, gids)) < 0) 201 abort(); 202 if (ngids > NGRPS) 203 ngids = NGRPS; 204 /* XXX: interface problem; we should translate from uid_t and gid_t */ 205 auth = authunix_create(machname, uid, gid, ngids, gids); 206 free(gids); 207 return (auth); 208 } 209 210 /* 211 * authunix operations 212 */ 213 214 /* ARGSUSED */ 215 static void 216 authunix_nextverf(AUTH *auth) 217 { 218 /* no action necessary */ 219 } 220 221 static bool_t 222 authunix_marshal(AUTH *auth, XDR *xdrs) 223 { 224 struct audata *au; 225 226 assert(auth != NULL); 227 assert(xdrs != NULL); 228 229 au = AUTH_PRIVATE(auth); 230 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 231 } 232 233 static bool_t 234 authunix_validate(AUTH *auth, struct opaque_auth *verf) 235 { 236 struct audata *au; 237 XDR xdrs; 238 239 assert(auth != NULL); 240 assert(verf != NULL); 241 242 if (verf->oa_flavor == AUTH_SHORT) { 243 au = AUTH_PRIVATE(auth); 244 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 245 XDR_DECODE); 246 247 if (au->au_shcred.oa_base != NULL) { 248 mem_free(au->au_shcred.oa_base, 249 au->au_shcred.oa_length); 250 au->au_shcred.oa_base = NULL; 251 } 252 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 253 auth->ah_cred = au->au_shcred; 254 } else { 255 xdrs.x_op = XDR_FREE; 256 (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 257 au->au_shcred.oa_base = NULL; 258 auth->ah_cred = au->au_origcred; 259 } 260 marshal_new_auth(auth); 261 } 262 return (TRUE); 263 } 264 265 static bool_t 266 authunix_refresh(AUTH *auth, void *dummy) 267 { 268 struct audata *au = AUTH_PRIVATE(auth); 269 struct authunix_parms aup; 270 struct timeval now; 271 XDR xdrs; 272 int stat; 273 274 assert(auth != NULL); 275 276 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 277 /* there is no hope. Punt */ 278 return (FALSE); 279 } 280 au->au_shfaults ++; 281 282 /* first deserialize the creds back into a struct authunix_parms */ 283 aup.aup_machname = NULL; 284 aup.aup_gids = NULL; 285 xdrmem_create(&xdrs, au->au_origcred.oa_base, 286 au->au_origcred.oa_length, XDR_DECODE); 287 stat = xdr_authunix_parms(&xdrs, &aup); 288 if (! stat) 289 goto done; 290 291 /* update the time and serialize in place */ 292 (void)gettimeofday(&now, NULL); 293 aup.aup_time = now.tv_sec; 294 xdrs.x_op = XDR_ENCODE; 295 XDR_SETPOS(&xdrs, 0); 296 stat = xdr_authunix_parms(&xdrs, &aup); 297 if (! stat) 298 goto done; 299 auth->ah_cred = au->au_origcred; 300 marshal_new_auth(auth); 301 done: 302 /* free the struct authunix_parms created by deserializing */ 303 xdrs.x_op = XDR_FREE; 304 (void)xdr_authunix_parms(&xdrs, &aup); 305 XDR_DESTROY(&xdrs); 306 return (stat); 307 } 308 309 static void 310 authunix_destroy(AUTH *auth) 311 { 312 struct audata *au; 313 314 assert(auth != NULL); 315 316 au = AUTH_PRIVATE(auth); 317 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 318 319 if (au->au_shcred.oa_base != NULL) 320 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 321 322 mem_free(auth->ah_private, sizeof(struct audata)); 323 324 if (auth->ah_verf.oa_base != NULL) 325 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 326 327 mem_free(auth, sizeof(*auth)); 328 } 329 330 /* 331 * Marshals (pre-serializes) an auth struct. 332 * sets private data, au_marshed and au_mpos 333 */ 334 static void 335 marshal_new_auth(AUTH *auth) 336 { 337 XDR xdr_stream; 338 XDR *xdrs = &xdr_stream; 339 struct audata *au; 340 341 assert(auth != NULL); 342 343 au = AUTH_PRIVATE(auth); 344 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 345 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 346 (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 347 warnx("auth_none.c - Fatal marshalling problem"); 348 else 349 au->au_mpos = XDR_GETPOS(xdrs); 350 XDR_DESTROY(xdrs); 351 } 352 353 static struct auth_ops * 354 authunix_ops(void) 355 { 356 static struct auth_ops ops; 357 358 /* VARIABLES PROTECTED BY ops_lock: ops */ 359 360 mutex_lock(&ops_lock); 361 if (ops.ah_nextverf == NULL) { 362 ops.ah_nextverf = authunix_nextverf; 363 ops.ah_marshal = authunix_marshal; 364 ops.ah_validate = authunix_validate; 365 ops.ah_refresh = authunix_refresh; 366 ops.ah_destroy = authunix_destroy; 367 } 368 mutex_unlock(&ops_lock); 369 return (&ops); 370 } 371