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 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 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 /* 36 * Adapted for use by the boot program. 37 * 38 * auth_unix.c, Implements UNIX style authentication parameters. 39 * 40 * The system is very weak. The client uses no encryption for its 41 * credentials and only sends null verifiers. The server sends backs 42 * null verifiers or optionally a verifier that suggests a new short hand 43 * for the credentials. 44 */ 45 46 #include <stdlib.h> 47 #include <sys/sysmacros.h> 48 #include <rpc/types.h> 49 #include <rpc/xdr.h> 50 #include <rpc/auth.h> 51 #include "clnt.h" 52 #include <rpc/auth_unix.h> 53 #include <sys/promif.h> 54 #include <sys/salib.h> 55 #include <sys/bootdebug.h> 56 #include "nfs_inet.h" 57 58 static struct auth_ops *authunix_ops(); 59 /* 60 * This struct is pointed to by the ah_private field of an auth_handle. 61 */ 62 struct audata { 63 struct opaque_auth au_origcred; /* original credentials */ 64 struct opaque_auth au_shcred; /* short hand cred */ 65 uint_t au_shfaults; /* short hand cache faults */ 66 char au_marshed[MAX_AUTH_BYTES]; 67 uint_t au_mpos; /* xdr pos at end of marshed */ 68 }; 69 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private) 70 71 static void marshal_new_auth(AUTH *); 72 73 #define dprintf if (boothowto & RB_DEBUG) printf 74 75 /* 76 * Create a unix style authenticator. 77 * Returns an auth handle with the given stuff in it. 78 */ 79 AUTH * 80 authunix_create(char *machname, uid_t uid, gid_t gid, int len, gid_t *aup_gids) 81 { 82 struct authunix_parms aup; 83 char mymem[MAX_AUTH_BYTES]; 84 XDR xdrs; 85 AUTH *auth; 86 struct audata *au; 87 88 /* 89 * Allocate and set up auth handle 90 */ 91 auth = (AUTH *) bkmem_alloc(sizeof (*auth)); 92 if (auth == NULL) { 93 prom_panic("authunix_create: Cannot allocate memory."); 94 } 95 96 au = (struct audata *)bkmem_alloc(sizeof (*au)); 97 if (au == NULL) { 98 prom_panic("authunix_create: Cannot allocate memory."); 99 } 100 101 /* setup authenticator. */ 102 auth->ah_ops = authunix_ops(); 103 auth->ah_private = (caddr_t)au; 104 105 /* structure copies */ 106 auth->ah_verf = au->au_shcred = _null_auth; 107 108 au->au_shfaults = 0; 109 110 /* 111 * fill in param struct from the given params 112 */ 113 aup.aup_time = prom_gettime() / 1000; 114 aup.aup_machname = machname; 115 aup.aup_uid = uid; 116 aup.aup_gid = gid; 117 aup.aup_len = (uint_t)len; 118 aup.aup_gids = (gid_t *)aup_gids; 119 120 /* 121 * Serialize the parameters into origcred 122 */ 123 xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); 124 if (!xdr_authunix_parms(&xdrs, &aup)) { 125 prom_panic("authunix_create: xdr_authunix_parms failed"); 126 } 127 au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs); 128 au->au_origcred.oa_flavor = (uint_t)AUTH_UNIX; 129 if ((au->au_origcred.oa_base = bkmem_alloc((uint_t)len)) == NULL) { 130 prom_panic("authunix_create: memory alloc failed"); 131 } 132 (void) bcopy(mymem, au->au_origcred.oa_base, (uint_t)len); 133 134 /* 135 * set auth handle to reflect new cred. 136 */ 137 auth->ah_cred = au->au_origcred; 138 marshal_new_auth(auth); 139 return (auth); 140 } 141 142 /* 143 * authunix operations 144 */ 145 146 /* ARGSUSED */ 147 static void 148 authunix_nextverf(AUTH *auth) 149 { 150 } 151 152 /* ARGSUSED */ 153 static bool_t 154 authunix_marshal(AUTH *auth, XDR *xdrs, cred_t *cr) 155 { 156 struct audata *au = AUTH_PRIVATE(auth); 157 158 return (XDR_PUTBYTES(xdrs, au->au_marshed, au->au_mpos)); 159 } 160 161 static bool_t 162 authunix_validate(AUTH *auth, struct opaque_auth *verf) 163 { 164 struct audata *au; 165 XDR xdrs; 166 167 if (verf->oa_flavor == AUTH_SHORT) { 168 au = AUTH_PRIVATE(auth); 169 170 171 xdrmem_create(&xdrs, verf->oa_base, verf->oa_length, 172 XDR_DECODE); 173 174 if (xdr_opaque_auth(&xdrs, &au->au_shcred)) { 175 auth->ah_cred = au->au_shcred; 176 } else { 177 xdrs.x_op = XDR_FREE; 178 (void) xdr_opaque_auth(&xdrs, &au->au_shcred); 179 au->au_shcred.oa_base = 0; 180 auth->ah_cred = au->au_origcred; 181 } 182 marshal_new_auth(auth); 183 } 184 185 return (TRUE); 186 } 187 188 /*ARGSUSED*/ 189 static bool_t 190 authunix_refresh(AUTH *auth, struct rpc_msg *msg, cred_t *cr) 191 { 192 struct audata *au = AUTH_PRIVATE(auth); 193 struct authunix_parms aup; 194 XDR xdrs; 195 int stat; 196 197 if (auth->ah_cred.oa_base == au->au_origcred.oa_base) { 198 /* there is no hope. Punt */ 199 return (FALSE); 200 } 201 au->au_shfaults ++; 202 203 /* first deserialize the creds back into a struct authunix_parms */ 204 aup.aup_machname = (char *)0; 205 aup.aup_gids = (gid_t *)0; 206 xdrmem_create(&xdrs, au->au_origcred.oa_base, 207 au->au_origcred.oa_length, XDR_DECODE); 208 stat = xdr_authunix_parms(&xdrs, &aup); 209 if (!stat) 210 goto done; 211 212 /* update the time and serialize in place */ 213 aup.aup_time = (prom_gettime() / 1000); 214 xdrs.x_op = XDR_ENCODE; 215 (void) XDR_SETPOS(&xdrs, 0); 216 stat = xdr_authunix_parms(&xdrs, &aup); 217 if (!stat) 218 goto done; 219 auth->ah_cred = au->au_origcred; 220 marshal_new_auth(auth); 221 done: 222 /* free the struct authunix_parms created by deserializing */ 223 xdrs.x_op = XDR_FREE; 224 (void) xdr_authunix_parms(&xdrs, &aup); 225 XDR_DESTROY(&xdrs); 226 return (stat); 227 } 228 229 static void 230 authunix_destroy(AUTH *auth) 231 { 232 struct audata *au = AUTH_PRIVATE(auth); 233 234 if (au->au_shcred.oa_base != NULL) 235 bkmem_free(au->au_shcred.oa_base, au->au_shcred.oa_length); 236 bkmem_free(auth->ah_private, sizeof (struct audata)); 237 if (auth->ah_verf.oa_base != NULL) 238 bkmem_free(auth->ah_verf.oa_base, auth->ah_verf.oa_length); 239 bkmem_free((caddr_t)auth, sizeof (*auth)); 240 } 241 242 /* 243 * Marshals (pre-serializes) an auth struct. 244 * sets private data, au_marshed and au_mpos 245 */ 246 static void 247 marshal_new_auth(AUTH *auth) 248 { 249 XDR xdr_stream; 250 XDR *xdrs = &xdr_stream; 251 struct audata *au = AUTH_PRIVATE(auth); 252 253 xdrmem_create(xdrs, au->au_marshed, MAX_AUTH_BYTES, XDR_ENCODE); 254 if ((!xdr_opaque_auth(xdrs, &(auth->ah_cred))) || 255 (!xdr_opaque_auth(xdrs, &(auth->ah_verf)))) { 256 dprintf("marshal_new_auth - Fatal marshalling problem"); 257 } else { 258 au->au_mpos = XDR_GETPOS(xdrs); 259 } 260 XDR_DESTROY(xdrs); 261 } 262 263 264 static struct auth_ops * 265 authunix_ops(void) 266 { 267 static struct auth_ops ops; 268 269 if (ops.ah_nextverf == 0) { 270 ops.ah_nextverf = authunix_nextverf; 271 ops.ah_marshal = authunix_marshal; 272 ops.ah_validate = authunix_validate; 273 ops.ah_refresh = authunix_refresh; 274 ops.ah_destroy = authunix_destroy; 275 } 276 return (&ops); 277 } 278 279 /* 280 * XDR for unix authentication parameters. 281 */ 282 bool_t 283 xdr_authunix_parms(XDR *xdrs, struct authunix_parms *p) 284 { 285 if (xdr_u_int(xdrs, &(p->aup_time)) && 286 xdr_string(xdrs, &(p->aup_machname), MAX_MACHINE_NAME) && 287 xdr_int(xdrs, (int *)&(p->aup_uid)) && 288 xdr_int(xdrs, (int *)&(p->aup_gid)) && 289 xdr_array(xdrs, (caddr_t *)&(p->aup_gids), 290 &(p->aup_len), NGRPS, sizeof (int), xdr_int)) { 291 return (TRUE); 292 } 293 return (FALSE); 294 } 295