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