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(machname, uid, gid, len, aup_gids) 95 char *machname; 96 u_int uid; 97 u_int gid; 98 int len; 99 u_int *aup_gids; 100 { 101 struct authunix_parms aup; 102 char mymem[MAX_AUTH_BYTES]; 103 struct timeval now; 104 XDR xdrs; 105 AUTH *auth; 106 struct audata *au; 107 108 /* 109 * Allocate and set up auth handle 110 */ 111 au = NULL; 112 auth = mem_alloc(sizeof(*auth)); 113 #ifndef _KERNEL 114 if (auth == NULL) { 115 warnx("authunix_create: out of memory"); 116 goto cleanup_authunix_create; 117 } 118 #endif 119 au = mem_alloc(sizeof(*au)); 120 #ifndef _KERNEL 121 if (au == NULL) { 122 warnx("authunix_create: out of memory"); 123 goto cleanup_authunix_create; 124 } 125 #endif 126 auth->ah_ops = authunix_ops(); 127 auth->ah_private = (caddr_t)au; 128 auth->ah_verf = au->au_shcred = _null_auth; 129 au->au_shfaults = 0; 130 au->au_origcred.oa_base = NULL; 131 132 /* 133 * fill in param struct from the given params 134 */ 135 (void)gettimeofday(&now, NULL); 136 aup.aup_time = now.tv_sec; 137 aup.aup_machname = machname; 138 aup.aup_uid = uid; 139 aup.aup_gid = gid; 140 aup.aup_len = (u_int)len; 141 aup.aup_gids = aup_gids; 142 143 /* 144 * Serialize the parameters into origcred 145 */ 146 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 147 if (! xdr_authunix_parms(&xdrs, &aup)) 148 abort(); 149 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 150 au->au_origcred.oa_flavor = AUTH_UNIX; 151 #ifdef _KERNEL 152 au->au_origcred.oa_base = mem_alloc((u_int) len); 153 #else 154 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 155 warnx("authunix_create: out of memory"); 156 goto cleanup_authunix_create; 157 } 158 #endif 159 memmove(au->au_origcred.oa_base, mymem, (size_t)len); 160 161 /* 162 * set auth handle to reflect new cred. 163 */ 164 auth->ah_cred = au->au_origcred; 165 marshal_new_auth(auth); 166 return (auth); 167 #ifndef _KERNEL 168 cleanup_authunix_create: 169 if (auth) 170 mem_free(auth, sizeof(*auth)); 171 if (au) { 172 if (au->au_origcred.oa_base) 173 mem_free(au->au_origcred.oa_base, (u_int)len); 174 mem_free(au, sizeof(*au)); 175 } 176 return (NULL); 177 #endif 178 } 179 180 /* 181 * Returns an auth handle with parameters determined by doing lots of 182 * syscalls. 183 */ 184 AUTH * 185 authunix_create_default() 186 { 187 AUTH *auth; 188 int ngids; 189 long ngids_max; 190 char machname[MAXHOSTNAMELEN + 1]; 191 uid_t uid; 192 gid_t gid; 193 gid_t *gids; 194 195 ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 196 gids = malloc(sizeof(gid_t) * ngids_max); 197 if (gids == NULL) 198 return (NULL); 199 200 if (gethostname(machname, sizeof machname) == -1) 201 abort(); 202 machname[sizeof(machname) - 1] = 0; 203 uid = geteuid(); 204 gid = getegid(); 205 if ((ngids = getgroups(ngids_max, gids)) < 0) 206 abort(); 207 if (ngids > NGRPS) 208 ngids = NGRPS; 209 /* XXX: interface problem; we should translate from uid_t and gid_t */ 210 auth = authunix_create(machname, uid, gid, ngids, gids); 211 free(gids); 212 return (auth); 213 } 214 215 /* 216 * authunix operations 217 */ 218 219 /* ARGSUSED */ 220 static void 221 authunix_nextverf(auth) 222 AUTH *auth; 223 { 224 /* no action necessary */ 225 } 226 227 static bool_t 228 authunix_marshal(auth, xdrs) 229 AUTH *auth; 230 XDR *xdrs; 231 { 232 struct audata *au; 233 234 assert(auth != NULL); 235 assert(xdrs != NULL); 236 237 au = AUTH_PRIVATE(auth); 238 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 239 } 240 241 static bool_t 242 authunix_validate(auth, verf) 243 AUTH *auth; 244 struct opaque_auth *verf; 245 { 246 struct audata *au; 247 XDR xdrs; 248 249 assert(auth != NULL); 250 assert(verf != NULL); 251 252 if (verf->oa_flavor == AUTH_SHORT) { 253 au = AUTH_PRIVATE(auth); 254 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 255 XDR_DECODE); 256 257 if (au->au_shcred.oa_base != NULL) { 258 mem_free(au->au_shcred.oa_base, 259 au->au_shcred.oa_length); 260 au->au_shcred.oa_base = NULL; 261 } 262 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 263 auth->ah_cred = au->au_shcred; 264 } else { 265 xdrs.x_op = XDR_FREE; 266 (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 267 au->au_shcred.oa_base = NULL; 268 auth->ah_cred = au->au_origcred; 269 } 270 marshal_new_auth(auth); 271 } 272 return (TRUE); 273 } 274 275 static bool_t 276 authunix_refresh(AUTH *auth, void *dummy) 277 { 278 struct audata *au = AUTH_PRIVATE(auth); 279 struct authunix_parms aup; 280 struct timeval now; 281 XDR xdrs; 282 int stat; 283 284 assert(auth != NULL); 285 286 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 287 /* there is no hope. Punt */ 288 return (FALSE); 289 } 290 au->au_shfaults ++; 291 292 /* first deserialize the creds back into a struct authunix_parms */ 293 aup.aup_machname = NULL; 294 aup.aup_gids = NULL; 295 xdrmem_create(&xdrs, au->au_origcred.oa_base, 296 au->au_origcred.oa_length, XDR_DECODE); 297 stat = xdr_authunix_parms(&xdrs, &aup); 298 if (! stat) 299 goto done; 300 301 /* update the time and serialize in place */ 302 (void)gettimeofday(&now, NULL); 303 aup.aup_time = now.tv_sec; 304 xdrs.x_op = XDR_ENCODE; 305 XDR_SETPOS(&xdrs, 0); 306 stat = xdr_authunix_parms(&xdrs, &aup); 307 if (! stat) 308 goto done; 309 auth->ah_cred = au->au_origcred; 310 marshal_new_auth(auth); 311 done: 312 /* free the struct authunix_parms created by deserializing */ 313 xdrs.x_op = XDR_FREE; 314 (void)xdr_authunix_parms(&xdrs, &aup); 315 XDR_DESTROY(&xdrs); 316 return (stat); 317 } 318 319 static void 320 authunix_destroy(auth) 321 AUTH *auth; 322 { 323 struct audata *au; 324 325 assert(auth != NULL); 326 327 au = AUTH_PRIVATE(auth); 328 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 329 330 if (au->au_shcred.oa_base != NULL) 331 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 332 333 mem_free(auth->ah_private, sizeof(struct audata)); 334 335 if (auth->ah_verf.oa_base != NULL) 336 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 337 338 mem_free(auth, sizeof(*auth)); 339 } 340 341 /* 342 * Marshals (pre-serializes) an auth struct. 343 * sets private data, au_marshed and au_mpos 344 */ 345 static void 346 marshal_new_auth(auth) 347 AUTH *auth; 348 { 349 XDR xdr_stream; 350 XDR *xdrs = &xdr_stream; 351 struct audata *au; 352 353 assert(auth != NULL); 354 355 au = AUTH_PRIVATE(auth); 356 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 357 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 358 (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 359 warnx("auth_none.c - Fatal marshalling problem"); 360 else 361 au->au_mpos = XDR_GETPOS(xdrs); 362 XDR_DESTROY(xdrs); 363 } 364 365 static struct auth_ops * 366 authunix_ops() 367 { 368 static struct auth_ops ops; 369 370 /* VARIABLES PROTECTED BY ops_lock: ops */ 371 372 mutex_lock(&ops_lock); 373 if (ops.ah_nextverf == NULL) { 374 ops.ah_nextverf = authunix_nextverf; 375 ops.ah_marshal = authunix_marshal; 376 ops.ah_validate = authunix_validate; 377 ops.ah_refresh = authunix_refresh; 378 ops.ah_destroy = authunix_destroy; 379 } 380 mutex_unlock(&ops_lock); 381 return (&ops); 382 } 383