2 * Sun RPC is a product of Sun Microsystems, Inc. and is provided for
3 * unrestricted use provided that this legend is included on all tape
4 * media and as a part of the software program in whole or part. Users
5 * may copy or modify Sun RPC without charge, but are not authorized
6 * to license or distribute it to anyone else except as part of a product or
7 * program developed by the user.
9 * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE
10 * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR
11 * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE.
13 * Sun RPC is provided with no support and without any obligation on the
14 * part of Sun Microsystems, Inc. to assist in its use, correction,
15 * modification or enhancement.
17 * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE
18 * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC
19 * OR ANY PART THEREOF.
21 * In no event will Sun Microsystems, Inc. be liable for any lost revenue
22 * or profits or other special, indirect and consequential damages, even if
23 * Sun has been advised of the possibility of such damages.
25 * Sun Microsystems, Inc.
27 * Mountain View, California 94043
30 * Copyright (C) 1984, Sun Microsystems, Inc.
33 * auth_unix.c, Implements UNIX style authentication parameters.
35 * The system is very weak. The client uses no encryption for it's
36 * credentials and only sends null verifiers. The server sends backs
37 * null verifiers or optionally a verifier that suggests a new short hand
38 * for the credentials.
48 #include <sys/param.h>
50 #include <rpc/types.h>
53 #include <rpc/auth_unix.h>
60 * Unix authenticator operations vector
62 static void authunix_nextverf (AUTH
*);
63 static bool_t
authunix_marshal (AUTH
*, XDR
*);
64 static bool_t
authunix_validate (AUTH
*, struct opaque_auth
*);
65 static bool_t
authunix_refresh (AUTH
*);
66 static void authunix_destroy (AUTH
*);
68 static struct auth_ops auth_unix_ops
= {
77 * This struct is pointed to by the ah_private field of an auth_handle.
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 */
86 #define AUTH_PRIVATE(auth) ((struct audata *)auth->ah_private)
88 static bool_t
marshal_new_auth (AUTH
*) internal_function
;
92 * Create a unix style authenticator.
93 * Returns an auth handle with the given stuff in it.
96 authunix_create (char *machname
, uid_t uid
, gid_t gid
, int len
,
99 struct authunix_parms aup
;
100 char mymem
[MAX_AUTH_BYTES
];
107 * Allocate and set up auth handle
109 auth
= (AUTH
*) mem_alloc (sizeof (*auth
));
110 au
= (struct audata
*) mem_alloc (sizeof (*au
));
111 if (auth
== NULL
|| au
== NULL
)
115 if (_IO_fwide (stderr
, 0) > 0)
116 (void) __fwprintf (stderr
, L
"%s",
117 _("authunix_create: out of memory\n"));
120 (void) fputs (_("authunix_create: out of memory\n"), stderr
);
121 mem_free (auth
, sizeof (*auth
));
122 mem_free (au
, sizeof (*au
));
125 auth
->ah_ops
= &auth_unix_ops
;
126 auth
->ah_private
= (caddr_t
) au
;
127 auth
->ah_verf
= au
->au_shcred
= _null_auth
;
131 * fill in param struct from the given params
133 (void) __gettimeofday (&now
, (struct timezone
*) 0);
134 aup
.aup_time
= now
.tv_sec
;
135 aup
.aup_machname
= machname
;
138 aup
.aup_len
= (u_int
) len
;
139 aup
.aup_gids
= aup_gids
;
142 * Serialize the parameters into origcred
144 INTUSE(xdrmem_create
) (&xdrs
, mymem
, MAX_AUTH_BYTES
, XDR_ENCODE
);
145 if (!INTUSE(xdr_authunix_parms
) (&xdrs
, &aup
))
147 au
->au_origcred
.oa_length
= len
= XDR_GETPOS (&xdrs
);
148 au
->au_origcred
.oa_flavor
= AUTH_UNIX
;
149 au
->au_origcred
.oa_base
= mem_alloc ((u_int
) len
);
150 if (au
->au_origcred
.oa_base
== NULL
)
152 memcpy(au
->au_origcred
.oa_base
, mymem
, (u_int
) len
);
155 * set auth handle to reflect new cred.
157 auth
->ah_cred
= au
->au_origcred
;
158 marshal_new_auth (auth
);
161 INTDEF (authunix_create
)
164 * Returns an auth handle with parameters determined by doing lots of
168 authunix_create_default (void)
170 char machname
[MAX_MACHINE_NAME
+ 1];
172 if (__gethostname (machname
, MAX_MACHINE_NAME
) == -1)
174 machname
[MAX_MACHINE_NAME
] = 0;
175 uid_t uid
= __geteuid ();
176 gid_t gid
= __getegid ();
179 /* When we have to try a second time, do not use alloca() again. We
180 might have reached the stack limit already. */
183 /* Ask the kernel how many groups there are exactly. Note that we
184 might have to redo all this if the number of groups has changed
185 between the two calls. */
186 max_nr_groups
= __getgroups (0, NULL
);
188 /* Just some random reasonable stack limit. */
189 #define ALLOCA_LIMIT (1024 / sizeof (gid_t))
191 if (max_nr_groups
< ALLOCA_LIMIT
&& ! retry
)
192 gids
= (gid_t
*) alloca (max_nr_groups
* sizeof (gid_t
));
195 gids
= (gid_t
*) malloc (max_nr_groups
* sizeof (gid_t
));
200 int len
= __getgroups (max_nr_groups
, gids
);
205 /* New groups added in the meantime. Try again. */
206 if (max_nr_groups
>= ALLOCA_LIMIT
|| retry
)
211 /* No other error can happen. */
215 /* This braindamaged Sun code forces us here to truncate the
216 list of groups to NGRPS members since the code in
217 authuxprot.c transforms a fixed array. Grrr. */
218 AUTH
*result
= INTUSE(authunix_create
) (machname
, uid
, gid
, MIN (NGRPS
, len
),
221 if (max_nr_groups
>= ALLOCA_LIMIT
|| retry
)
226 INTDEF (authunix_create_default
)
229 * authunix operations
233 authunix_nextverf (AUTH
*auth
)
235 /* no action necessary */
239 authunix_marshal (AUTH
*auth
, XDR
*xdrs
)
241 struct audata
*au
= AUTH_PRIVATE (auth
);
243 return XDR_PUTBYTES (xdrs
, au
->au_marshed
, au
->au_mpos
);
247 authunix_validate (AUTH
*auth
, struct opaque_auth
*verf
)
252 if (verf
->oa_flavor
== AUTH_SHORT
)
254 au
= AUTH_PRIVATE (auth
);
255 INTUSE(xdrmem_create
) (&xdrs
, verf
->oa_base
, verf
->oa_length
,
258 if (au
->au_shcred
.oa_base
!= NULL
)
260 mem_free (au
->au_shcred
.oa_base
,
261 au
->au_shcred
.oa_length
);
262 au
->au_shcred
.oa_base
= NULL
;
264 if (INTUSE(xdr_opaque_auth
) (&xdrs
, &au
->au_shcred
))
266 auth
->ah_cred
= au
->au_shcred
;
270 xdrs
.x_op
= XDR_FREE
;
271 (void) INTUSE(xdr_opaque_auth
) (&xdrs
, &au
->au_shcred
);
272 au
->au_shcred
.oa_base
= NULL
;
273 auth
->ah_cred
= au
->au_origcred
;
275 marshal_new_auth (auth
);
281 authunix_refresh (AUTH
*auth
)
283 struct audata
*au
= AUTH_PRIVATE (auth
);
284 struct authunix_parms aup
;
289 if (auth
->ah_cred
.oa_base
== au
->au_origcred
.oa_base
)
291 /* there is no hope. Punt */
296 /* first deserialize the creds back into a struct authunix_parms */
297 aup
.aup_machname
= NULL
;
298 aup
.aup_gids
= (gid_t
*) NULL
;
299 INTUSE(xdrmem_create
) (&xdrs
, au
->au_origcred
.oa_base
,
300 au
->au_origcred
.oa_length
, XDR_DECODE
);
301 stat
= INTUSE(xdr_authunix_parms
) (&xdrs
, &aup
);
305 /* update the time and serialize in place */
306 (void) __gettimeofday (&now
, (struct timezone
*) 0);
307 aup
.aup_time
= now
.tv_sec
;
308 xdrs
.x_op
= XDR_ENCODE
;
309 XDR_SETPOS (&xdrs
, 0);
310 stat
= INTUSE(xdr_authunix_parms
) (&xdrs
, &aup
);
313 auth
->ah_cred
= au
->au_origcred
;
314 marshal_new_auth (auth
);
316 /* free the struct authunix_parms created by deserializing */
317 xdrs
.x_op
= XDR_FREE
;
318 (void) INTUSE(xdr_authunix_parms
) (&xdrs
, &aup
);
324 authunix_destroy (AUTH
*auth
)
326 struct audata
*au
= AUTH_PRIVATE (auth
);
328 mem_free (au
->au_origcred
.oa_base
, au
->au_origcred
.oa_length
);
330 if (au
->au_shcred
.oa_base
!= NULL
)
331 mem_free (au
->au_shcred
.oa_base
, au
->au_shcred
.oa_length
);
333 mem_free (auth
->ah_private
, sizeof (struct audata
));
335 if (auth
->ah_verf
.oa_base
!= NULL
)
336 mem_free (auth
->ah_verf
.oa_base
, auth
->ah_verf
.oa_length
);
338 mem_free ((caddr_t
) auth
, sizeof (*auth
));
342 * Marshals (pre-serializes) an auth struct.
343 * sets private data, au_marshed and au_mpos
347 marshal_new_auth (AUTH
*auth
)
350 XDR
*xdrs
= &xdr_stream
;
351 struct audata
*au
= AUTH_PRIVATE (auth
);
353 INTUSE(xdrmem_create
) (xdrs
, au
->au_marshed
, MAX_AUTH_BYTES
, XDR_ENCODE
);
354 if ((!INTUSE(xdr_opaque_auth
) (xdrs
, &(auth
->ah_cred
))) ||
355 (!INTUSE(xdr_opaque_auth
) (xdrs
, &(auth
->ah_verf
))))
356 perror (_("auth_none.c - Fatal marshalling problem"));
358 au
->au_mpos
= XDR_GETPOS (xdrs
);