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