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 /* 34 * auth_unix.c, Implements UNIX style authentication parameters. 35 * 36 * Copyright (C) 1984, Sun Microsystems, Inc. 37 * 38 * The system is very weak. The client uses no encryption for it's 39 * credentials and only sends null verifiers. The server sends backs 40 * null verifiers or optionally a verifier that suggests a new short hand 41 * for the credentials. 42 * 43 */ 44 45 #include "namespace.h" 46 #include "reentrant.h" 47 #include <sys/param.h> 48 49 #include <assert.h> 50 #include <err.h> 51 #include <stdio.h> 52 #include <stdlib.h> 53 #include <unistd.h> 54 #include <string.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 "un-namespace.h" 61 #include "mt_misc.h" 62 63 /* auth_unix.c */ 64 static void authunix_nextverf (AUTH *); 65 static bool_t authunix_marshal (AUTH *, XDR *); 66 static bool_t authunix_validate (AUTH *, struct opaque_auth *); 67 static bool_t authunix_refresh (AUTH *, void *); 68 static void authunix_destroy (AUTH *); 69 static void marshal_new_auth (AUTH *); 70 static struct auth_ops *authunix_ops (void); 71 72 /* 73 * This struct is pointed to by the ah_private field of an auth_handle. 74 */ 75 struct audata { 76 struct opaque_auth au_origcred; /* original credentials */ 77 struct opaque_auth au_shcred; /* short hand cred */ 78 u_long au_shfaults; /* short hand cache faults */ 79 char au_marshed[MAX_AUTH_BYTES]; 80 u_int au_mpos; /* xdr pos at end of marshed */ 81 }; 82 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 83 84 /* 85 * Create a unix style authenticator. 86 * Returns an auth handle with the given stuff in it. 87 */ 88 AUTH * 89 authunix_create(char *machname, u_int uid, u_int gid, int len, u_int *aup_gids) 90 { 91 struct authunix_parms aup; 92 char mymem[MAX_AUTH_BYTES]; 93 struct timeval now; 94 XDR xdrs; 95 AUTH *auth; 96 struct audata *au; 97 98 /* 99 * Allocate and set up auth handle 100 */ 101 au = NULL; 102 auth = mem_alloc(sizeof(*auth)); 103 #ifndef _KERNEL 104 if (auth == NULL) { 105 warnx("authunix_create: out of memory"); 106 goto cleanup_authunix_create; 107 } 108 #endif 109 au = mem_alloc(sizeof(*au)); 110 #ifndef _KERNEL 111 if (au == NULL) { 112 warnx("authunix_create: out of memory"); 113 goto cleanup_authunix_create; 114 } 115 #endif 116 auth->ah_ops = authunix_ops(); 117 auth->ah_private = (caddr_t)au; 118 auth->ah_verf = au->au_shcred = _null_auth; 119 au->au_shfaults = 0; 120 au->au_origcred.oa_base = NULL; 121 122 /* 123 * fill in param struct from the given params 124 */ 125 (void)gettimeofday(&now, NULL); 126 aup.aup_time = now.tv_sec; 127 aup.aup_machname = machname; 128 aup.aup_uid = uid; 129 aup.aup_gid = gid; 130 aup.aup_len = (u_int)len; 131 aup.aup_gids = aup_gids; 132 133 /* 134 * Serialize the parameters into origcred 135 */ 136 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 137 if (! xdr_authunix_parms(&xdrs, &aup)) 138 abort(); 139 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 140 au->au_origcred.oa_flavor = AUTH_UNIX; 141 #ifdef _KERNEL 142 au->au_origcred.oa_base = mem_alloc((u_int) len); 143 #else 144 if ((au->au_origcred.oa_base = mem_alloc((u_int) len)) == NULL) { 145 warnx("authunix_create: out of memory"); 146 goto cleanup_authunix_create; 147 } 148 #endif 149 memmove(au->au_origcred.oa_base, mymem, (size_t)len); 150 151 /* 152 * set auth handle to reflect new cred. 153 */ 154 auth->ah_cred = au->au_origcred; 155 marshal_new_auth(auth); 156 return (auth); 157 #ifndef _KERNEL 158 cleanup_authunix_create: 159 if (auth) 160 mem_free(auth, sizeof(*auth)); 161 if (au) { 162 if (au->au_origcred.oa_base) 163 mem_free(au->au_origcred.oa_base, (u_int)len); 164 mem_free(au, sizeof(*au)); 165 } 166 return (NULL); 167 #endif 168 } 169 170 /* 171 * Returns an auth handle with parameters determined by doing lots of 172 * syscalls. 173 */ 174 AUTH * 175 authunix_create_default(void) 176 { 177 AUTH *auth; 178 int ngids; 179 long ngids_max; 180 char machname[MAXHOSTNAMELEN + 1]; 181 uid_t uid; 182 gid_t gid; 183 gid_t *gids; 184 185 ngids_max = sysconf(_SC_NGROUPS_MAX) + 1; 186 gids = malloc(sizeof(gid_t) * ngids_max); 187 if (gids == NULL) 188 return (NULL); 189 190 if (gethostname(machname, sizeof machname) == -1) 191 abort(); 192 machname[sizeof(machname) - 1] = 0; 193 uid = geteuid(); 194 gid = getegid(); 195 if ((ngids = getgroups(ngids_max, gids)) < 0) 196 abort(); 197 if (ngids > NGRPS) 198 ngids = NGRPS; 199 /* XXX: interface problem; we should translate from uid_t and gid_t */ 200 auth = authunix_create(machname, uid, gid, ngids, gids); 201 free(gids); 202 return (auth); 203 } 204 205 /* 206 * authunix operations 207 */ 208 209 /* ARGSUSED */ 210 static void 211 authunix_nextverf(AUTH *auth) 212 { 213 /* no action necessary */ 214 } 215 216 static bool_t 217 authunix_marshal(AUTH *auth, XDR *xdrs) 218 { 219 struct audata *au; 220 221 assert(auth != NULL); 222 assert(xdrs != NULL); 223 224 au = AUTH_PRIVATE(auth); 225 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 226 } 227 228 static bool_t 229 authunix_validate(AUTH *auth, struct opaque_auth *verf) 230 { 231 struct audata *au; 232 XDR xdrs; 233 234 assert(auth != NULL); 235 assert(verf != NULL); 236 237 if (verf->oa_flavor == AUTH_SHORT) { 238 au = AUTH_PRIVATE(auth); 239 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 240 XDR_DECODE); 241 242 if (au->au_shcred.oa_base != NULL) { 243 mem_free(au->au_shcred.oa_base, 244 au->au_shcred.oa_length); 245 au->au_shcred.oa_base = NULL; 246 } 247 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 248 auth->ah_cred = au->au_shcred; 249 } else { 250 xdrs.x_op = XDR_FREE; 251 (void)xdr_opaque_auth(&xdrs, &au->au_shcred); 252 au->au_shcred.oa_base = NULL; 253 auth->ah_cred = au->au_origcred; 254 } 255 marshal_new_auth(auth); 256 } 257 return (TRUE); 258 } 259 260 static bool_t 261 authunix_refresh(AUTH *auth, void *dummy) 262 { 263 struct audata *au = AUTH_PRIVATE(auth); 264 struct authunix_parms aup; 265 struct timeval now; 266 XDR xdrs; 267 int stat; 268 269 assert(auth != NULL); 270 271 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 272 /* there is no hope. Punt */ 273 return (FALSE); 274 } 275 au->au_shfaults ++; 276 277 /* first deserialize the creds back into a struct authunix_parms */ 278 aup.aup_machname = NULL; 279 aup.aup_gids = NULL; 280 xdrmem_create(&xdrs, au->au_origcred.oa_base, 281 au->au_origcred.oa_length, XDR_DECODE); 282 stat = xdr_authunix_parms(&xdrs, &aup); 283 if (! stat) 284 goto done; 285 286 /* update the time and serialize in place */ 287 (void)gettimeofday(&now, NULL); 288 aup.aup_time = now.tv_sec; 289 xdrs.x_op = XDR_ENCODE; 290 XDR_SETPOS(&xdrs, 0); 291 stat = xdr_authunix_parms(&xdrs, &aup); 292 if (! stat) 293 goto done; 294 auth->ah_cred = au->au_origcred; 295 marshal_new_auth(auth); 296 done: 297 /* free the struct authunix_parms created by deserializing */ 298 xdrs.x_op = XDR_FREE; 299 (void)xdr_authunix_parms(&xdrs, &aup); 300 XDR_DESTROY(&xdrs); 301 return (stat); 302 } 303 304 static void 305 authunix_destroy(AUTH *auth) 306 { 307 struct audata *au; 308 309 assert(auth != NULL); 310 311 au = AUTH_PRIVATE(auth); 312 mem_free(au->au_origcred.oa_base, au->au_origcred.oa_length); 313 314 if (au->au_shcred.oa_base != NULL) 315 mem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 316 317 mem_free(auth->ah_private, sizeof(struct audata)); 318 319 if (auth->ah_verf.oa_base != NULL) 320 mem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 321 322 mem_free(auth, sizeof(*auth)); 323 } 324 325 /* 326 * Marshals (pre-serializes) an auth struct. 327 * sets private data, au_marshed and au_mpos 328 */ 329 static void 330 marshal_new_auth(AUTH *auth) 331 { 332 XDR xdr_stream; 333 XDR *xdrs = &xdr_stream; 334 struct audata *au; 335 336 assert(auth != NULL); 337 338 au = AUTH_PRIVATE(auth); 339 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 340 if ((! xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 341 (! xdr_opaque_auth(xdrs, &(auth->ah_verf)))) 342 warnx("auth_none.c - Fatal marshalling problem"); 343 else 344 au->au_mpos = XDR_GETPOS(xdrs); 345 XDR_DESTROY(xdrs); 346 } 347 348 static struct auth_ops * 349 authunix_ops(void) 350 { 351 static struct auth_ops ops; 352 353 /* VARIABLES PROTECTED BY ops_lock: ops */ 354 355 mutex_lock(&ops_lock); 356 if (ops.ah_nextverf == NULL) { 357 ops.ah_nextverf = authunix_nextverf; 358 ops.ah_marshal = authunix_marshal; 359 ops.ah_validate = authunix_validate; 360 ops.ah_refresh = authunix_refresh; 361 ops.ah_destroy = authunix_destroy; 362 } 363 mutex_unlock(&ops_lock); 364 return (&ops); 365 } 366