diff options
| author | Bill Paul <wpaul@FreeBSD.org> | 1997-05-28 05:00:11 +0000 | 
|---|---|---|
| committer | Bill Paul <wpaul@FreeBSD.org> | 1997-05-28 05:00:11 +0000 | 
| commit | e8636dfd57b1bc6a19328606214e847c0d9eb1aa (patch) | |
| tree | e948513145e50b36622f94430ef224e97a752e8a /lib/libc | |
| parent | 7d0a5a391923395c0b5cd9ae9b5b7fcaac4c4979 (diff) | |
Notes
Diffstat (limited to 'lib/libc')
59 files changed, 6508 insertions, 968 deletions
| diff --git a/lib/libc/rpc/Makefile.inc b/lib/libc/rpc/Makefile.inc index 8776d9d8eee9..5c96968fa5a5 100644 --- a/lib/libc/rpc/Makefile.inc +++ b/lib/libc/rpc/Makefile.inc @@ -1,16 +1,38 @@  #	@(#)Makefile	5.11 (Berkeley) 9/6/90 -.PATH: ${.CURDIR}/rpc ${.CURDIR}/. -CFLAGS+=-I${.CURDIR} -I${.CURDIR}/rpc +.PATH: ${.CURDIR}/../libc/rpc ${.CURDIR}/.  SRCS+=	auth_none.c auth_unix.c  authunix_prot.c bindresvport.c \  	clnt_generic.c clnt_perror.c clnt_raw.c clnt_simple.c clnt_tcp.c \  	clnt_udp.c rpc_dtablesize.c get_myaddress.c getrpcent.c getrpcport.c \  	pmap_clnt.c pmap_getmaps.c pmap_getport.c pmap_prot.c \  	pmap_prot2.c pmap_rmt.c rpc_prot.c rpc_commondata.c rpc_callmsg.c \  	svc.c svc_auth.c svc_auth_unix.c svc_raw.c svc_run.c svc_simple.c \ -	svc_tcp.c svc_udp.c xdr.c xdr_array.c xdr_mem.c \ -	xdr_rec.c xdr_reference.c xdr_stdio.c +	svc_tcp.c svc_udp.c +SRCS+=	clnt_unix.c svc_unix.c + +SRCS+=	auth_des.c authdes_prot.c auth_time.c des_soft.c des_crypt.c \ +	key_call.c key_prot_xdr.c netname.c netnamer.c rpcdname.c rtime.c \ +	svc_auth_des.c crypt_clnt.c crypt_xdr.c crypt_client.c + +CFLAGS+= -DBROKEN_DES + +CLEANFILES= crypt_clnt.c crypt_xdr.c crypt.h + +RPCDIR= ${DESTDIR}/usr/include/rpcsvc +RPCGEN= rpcgen -C + +crypt_clnt.c: ${RPCDIR}/crypt.x crypt.h +	${RPCGEN} -l -o ${.TARGET} ${RPCDIR}/crypt.x + +crypt_xdr.c: ${RPCDIR}/crypt.x crypt.h +	${RPCGEN} -c -o ${.TARGET} ${RPCDIR}/crypt.x + +crypt.h: ${RPCDIR}/crypt.x +	${RPCGEN} -h -o ${.TARGET} ${RPCDIR}/crypt.x + +# Only build man pages with libc. +.if ${LIB} == "c"  #  # XXX -- rstat.1 and rstat_svc.8 shouldn't really be here  #        but there's no rstat command, don't know why, so I'm @@ -18,22 +40,81 @@ SRCS+=	auth_none.c auth_unix.c  authunix_prot.c bindresvport.c \  # Paul.  # -MAN1+= rpc/rstat.1   -MAN3+= rpc/bindresvport.3 rpc/getrpcent.3 rpc/getrpcport.3 rpc/rpc.3 rpc/xdr.3 +# MAN1+= rpc/rstat.1 +MAN3+= rpc/bindresvport.3 rpc/getrpcent.3 rpc/getrpcport.3 rpc/rpc.3  MAN5+= rpc/rpc.5  MAN8+= rpc/rstat_svc.8 +MAN3+= rpc/rpc_secure.3 rpc/publickey.3 rpc/rtime.3 rpc/des_crypt.3 +MAN5+= rpc/publickey.5 -UNSUPPORTED+=	xdr_float.c  - -HDRS+=	auth.h auth_unix.h clnt.h pmap_clnt.h \ -	pmap_prot.h pmap_rmt.h rpc.h rpc_msg.h svc.h svc_auth.h types.h xdr.h +MLINKS+=	getrpcent.3 getrpcbyname.3 \ +		getrpcent.3 getrpcbynumber.3 \ +		getrpcent.3 endrpcent.3 \ +		getrpcent.3 setrpcent.3 \ +		rpc.3 auth_destroy.3 \ +		rpc.3 authnone_create.3 \ +		rpc.3 authunix_create.3 \ +		rpc.3 authunix_create_default.3 \ +		rpc.3 callrpc.3 \ +		rpc.3 clnt_broadcast.3 \ +		rpc.3 clnt_call.3 \ +		rpc.3 clnt_control.3 \ +		rpc.3 clnt_create.3 \ +		rpc.3 clnt_destroy.3 \ +		rpc.3 clnt_freeres.3 \ +		rpc.3 clnt_geterr.3 \ +		rpc.3 clnt_pcreateerror.3 \ +		rpc.3 clnt_perrno.3 \ +		rpc.3 clnt_perror.3 \ +		rpc.3 clnt_spcreateerror.3 \ +		rpc.3 clnt_sperrno.3 \ +		rpc.3 clnt_sperror.3 \ +		rpc.3 clntraw_create.3 \ +		rpc.3 clnttcp_create.3 \ +		rpc.3 clntudp_bufcreate.3 \ +		rpc.3 clntudp_create.3 \ +		rpc.3 get_myaddress.3 \ +		rpc.3 pmap_getmaps.3 \ +		rpc.3 pmap_getport.3 \ +		rpc.3 pmap_rmtcall.3 \ +		rpc.3 pmap_set.3 \ +		rpc.3 pmap_unset.3 \ +		rpc.3 regsterrpc.3 \ +		rpc.3 rpc_createerr.3 \ +		rpc.3 svc_destroy.3 \ +		rpc.3 svc_fds.3 \ +		rpc.3 svc_fdset.3 \ +		rpc.3 svc_getargs.3 \ +		rpc.3 svc_getcaller.3 \ +		rpc.3 svc_getreg.3 \ +		rpc.3 svc_getregset.3 \ +		rpc.3 svc_register.3 \ +		rpc.3 svc_run.3 \ +		rpc.3 svc_sendreply.3 \ +		rpc.3 svc_unregister.3 \ +		rpc.3 svcerr_auth.3 \ +		rpc.3 svcerr_decode.3 \ +		rpc.3 svcerr_noproc.3 \ +		rpc.3 svcerr_noprog.3 \ +		rpc.3 svcerr_progvers.3 \ +		rpc.3 svcerr_systemerr.3 \ +		rpc.3 svcerr_weakauth.3 \ +		rpc.3 svcfd_create.3 \ +		rpc.3 svcraw_create.3 \ +		rpc.3 svctcp_create.3 \ +		rpc.3 svcudp_bufcreate.3 \ +		rpc.3 xdr_accepted_reply.3 \ +		rpc.3 xdr_authunix_parms.3 \ +		rpc.3 xdr_callhdr.3 \ +		rpc.3 xdr_callmsg.3 \ +		rpc.3 xdr_opaque_auth.3 \ +		rpc.3 xdr_pmap.3 \ +		rpc.3 xdr_pmaplist.3 \ +		rpc.3 xdr_rejected_reply.3 \ +		rpc.3 xdr_replymsg.3 \ +		rpc.3 xprt_register.3 \ +		rpc.3 xprt_unregister.3 \ -beforeinstall: ${HDRS} -	@-if [ ! -d ${DESTDIR}/usr/include/rpc ]; then \ -		mkdir ${DESTDIR}/usr/include/rpc; \ -		chown ${BINOWN}.${BINGRP} ${DESTDIR}/usr/include/rpc; \ -		chmod 755 ${DESTDIR}/usr/include/rpc; \ -	fi -	cd ${.CURDIR}/rpc; install -c -o ${BINOWN} -g ${BINGRP} -m 444 ${HDRS} \ -	    ${DESTDIR}/usr/include/rpc +MLINKS+=getrpcent.3 getrpcbyname.3 getrpcent.3 getrpcbynumber.3 +.endif diff --git a/lib/libc/rpc/auth_des.c b/lib/libc/rpc/auth_des.c new file mode 100644 index 000000000000..3fd2bfe8f4a0 --- /dev/null +++ b/lib/libc/rpc/auth_des.c @@ -0,0 +1,554 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + *  + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + *  + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + *  + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ +/* + * auth_des.c, client-side implementation of DES authentication + */ +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <sys/cdefs.h> +#include <rpc/des_crypt.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <netinet/in.h>	/* XXX: just to get htonl() and ntohl() */ +#include <sys/socket.h> +#undef NIS +#include <rpcsvc/nis.h> + +#if defined(LIBC_SCCS) && !defined(lint) +/* from: static char sccsid[] = 	"@(#)auth_des.c	2.2 88/07/29 4.0 RPCSRC; from 1.9 88/02/08 SMI"; */ +static const char rcsid[] = "$Id$"; +#endif + +extern bool_t __rpc_get_time_offset __P(( struct timeval *, nis_server *, +						char *, char **, struct sockaddr_in * )); +extern int rtime __P(( struct sockaddr_in *, struct timeval *, struct timeval *)); +extern bool_t xdr_authdes_cred __P(( XDR *, struct authdes_cred * )); +extern bool_t xdr_authdes_verf __P(( XDR *, struct authdes_verf * )); + +#define MILLION		1000000L +#define RTIME_TIMEOUT 5		/* seconds to wait for sync */ + +#define AUTH_PRIVATE(auth)	(struct ad_private *) auth->ah_private +#define ALLOC(object_type)	(object_type *) mem_alloc(sizeof(object_type)) +#define FREE(ptr, size)		mem_free((char *)(ptr), (int) size) +#define ATTEMPT(xdr_op)		if (!(xdr_op)) return (FALSE) + +#define debug(msg)		 /*printf("%s\n", msg) */ + +/*  + * DES authenticator operations vector + */ +static void	authdes_nextverf(); +static bool_t	authdes_marshal(); +static bool_t	authdes_validate(); +static bool_t	authdes_refresh(); +static void	authdes_destroy(); +static struct auth_ops authdes_ops = { +	authdes_nextverf, +	authdes_marshal, +	authdes_validate, +	authdes_refresh, +	authdes_destroy +}; +#ifdef foo +static bool_t	synchronize __P(( struct sockaddr *, struct timeval *)); +#endif +/* + * This struct is pointed to by the ah_private field of an "AUTH *" + */ +struct ad_private { +	char *ad_fullname; 		/* client's full name */ +	u_int ad_fullnamelen;		/* length of name, rounded up */ +	char *ad_servername; 		/* server's full name */ +	u_int ad_servernamelen;		/* length of name, rounded up */ +	u_int ad_window;	  	/* client specified window */ +	bool_t ad_dosync;		/* synchronize? */		 +	struct sockaddr ad_syncaddr;	/* remote host to synch with */ +	char *ad_timehost;		/* remote host to synch with */ +	struct timeval ad_timediff;	/* server's time - client's time */ +	u_long ad_nickname;		/* server's nickname for client */ +	struct authdes_cred ad_cred;	/* storage for credential */ +	struct authdes_verf ad_verf;	/* storage for verifier */ +	struct timeval ad_timestamp;	/* timestamp sent */ +	des_block ad_xkey;		/* encrypted conversation key */ +	u_char ad_pkey[1024];		/* Server's actual public key */ +	char *ad_netid;			/* Timehost netid */ +	char *ad_uaddr;			/* Timehost uaddr */ +	nis_server *ad_nis_srvr;	/* NIS+ server struct */ +}; +	 + +/* + * Create the client des authentication object + */	 +AUTH * +authdes_create(servername, window, syncaddr, ckey) +	char *servername;		/* network name of server */ +	u_int window;			/* time to live */ +	struct sockaddr *syncaddr;	/* optional addr of host to sync with */ +	des_block *ckey;		/* optional conversation key to use*/ +{ + +	AUTH *auth; +	struct ad_private *ad; +	char namebuf[MAXNETNAMELEN+1]; +	u_char	pkey_data[1024]; + +	if (!getpublickey(servername, pkey_data)) +		return(NULL); + +	/* + 	 * Allocate everything now +	 */ +	auth = ALLOC(AUTH); +	ad = ALLOC(struct ad_private); +	(void) getnetname(namebuf); + +	ad->ad_fullnamelen = RNDUP(strlen(namebuf)); +	ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); + +	ad->ad_servernamelen = strlen(servername); +	ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); + +	if (auth == NULL || ad == NULL || ad->ad_fullname == NULL || +	    ad->ad_servername == NULL) { +		debug("authdes_create: out of memory"); +		goto failed; +	} + +	/*  +	 * Set up private data +	 */ +	bcopy(namebuf, ad->ad_fullname, ad->ad_fullnamelen + 1); +	bcopy(servername, ad->ad_servername, ad->ad_servernamelen + 1); +	bcopy(pkey_data, ad->ad_pkey, strlen(pkey_data) + 1); +	if (syncaddr != NULL) { +		ad->ad_syncaddr = *syncaddr; +		ad->ad_dosync = TRUE; +	} else { +		ad->ad_dosync = FALSE; +	} +	ad->ad_window = window; +	if (ckey == NULL) { +		if (key_gendes(&auth->ah_key) < 0) { +			debug("authdes_create: unable to gen conversation key"); +			return (NULL); +		} +	} else { +		auth->ah_key = *ckey; +	} + +	/* +	 * Set up auth handle +	 */  +	auth->ah_cred.oa_flavor = AUTH_DES; +	auth->ah_verf.oa_flavor = AUTH_DES; +	auth->ah_ops = &authdes_ops; +	auth->ah_private = (caddr_t)ad; + +	if (!authdes_refresh(auth)) { +		goto failed; +	}	 +	return (auth); + +failed: +	if (auth != NULL)  +		FREE(auth, sizeof(AUTH));  +	if (ad != NULL)  +		FREE(ad, sizeof(struct ad_private)); +	if (ad->ad_fullname != NULL)  +		FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); +	if (ad->ad_servername != NULL)  +		FREE(ad->ad_servername, ad->ad_servernamelen + 1); +	return (NULL); +} + +/* + * Slightly modified version of authdes_create which takes the public key + * of the server principal as an argument. This spares us a call to + * getpublickey() which in the nameserver context can cause a deadlock. + */ +AUTH * +authdes_pk_create(servername, pkey, window, timehost, ckey, srvr) +	char *servername;		/* network name of server */ +	netobj *pkey;			/* public key of server */ +	u_int window;			/* time to live */ +	char *timehost;			/* optional hostname to sync with */ +	des_block *ckey;		/* optional conversation key to use */ +	nis_server *srvr;		/* optional NIS+ server struct */ +{ +	AUTH *auth; +	struct ad_private *ad; +	char namebuf[MAXNETNAMELEN+1]; + +	/* +	 * Allocate everything now +	 */ +	auth = ALLOC(AUTH); +	if (auth == NULL) { +		debug("authdes_pk_create: out of memory"); +		return (NULL); +	} +	ad = ALLOC(struct ad_private); +	if (ad == NULL) { +		debug("authdes_pk_create: out of memory"); +		goto failed; +	} +	ad->ad_fullname = ad->ad_servername = NULL; /* Sanity reasons */ +	ad->ad_timehost = NULL; +	ad->ad_netid = NULL; +	ad->ad_uaddr = NULL; +	ad->ad_nis_srvr = NULL; +	ad->ad_timediff.tv_sec = 0; +	ad->ad_timediff.tv_usec = 0; +	memcpy(ad->ad_pkey, pkey->n_bytes, pkey->n_len); +	if (!getnetname(namebuf)) +		goto failed; +	ad->ad_fullnamelen = RNDUP((u_int) strlen(namebuf)); +	ad->ad_fullname = (char *)mem_alloc(ad->ad_fullnamelen + 1); +	ad->ad_servernamelen = strlen(servername); +	ad->ad_servername = (char *)mem_alloc(ad->ad_servernamelen + 1); + +	if (ad->ad_fullname == NULL || ad->ad_servername == NULL) { +		debug("authdes_pk_create: out of memory"); +		goto failed; +	} +	if (timehost != NULL) { +		ad->ad_timehost = (char *)mem_alloc(strlen(timehost) + 1); +		if (ad->ad_timehost == NULL) { +			debug("authdes_pk_create: out of memory"); +			goto failed; +		} +		memcpy(ad->ad_timehost, timehost, strlen(timehost) + 1); +		ad->ad_dosync = TRUE; +	} else if (srvr != NULL) { +		ad->ad_nis_srvr = srvr;	/* transient */ +		ad->ad_dosync = TRUE; +	} else { +		ad->ad_dosync = FALSE; +	} +	memcpy(ad->ad_fullname, namebuf, ad->ad_fullnamelen + 1); +	memcpy(ad->ad_servername, servername, ad->ad_servernamelen + 1); +	ad->ad_window = window; +	if (ckey == NULL) { +		if (key_gendes(&auth->ah_key) < 0) { +			debug("authdes_pk_create: unable to gen conversation key"); +			goto failed; +		} +	} else { +		auth->ah_key = *ckey; +	} + +	/* +	 * Set up auth handle +	 */ +	auth->ah_cred.oa_flavor = AUTH_DES; +	auth->ah_verf.oa_flavor = AUTH_DES; +	auth->ah_ops = &authdes_ops; +	auth->ah_private = (caddr_t)ad; + +	if (!authdes_refresh(auth)) { +		goto failed; +	} +	ad->ad_nis_srvr = NULL; /* not needed any longer */ +	return (auth); + +failed: +	if (auth) +		FREE(auth, sizeof (AUTH)); +	if (ad) { +		if (ad->ad_fullname) +			FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); +		if (ad->ad_servername) +			FREE(ad->ad_servername, ad->ad_servernamelen + 1); +		if (ad->ad_timehost) +			FREE(ad->ad_timehost, strlen(ad->ad_timehost) + 1); +		if (ad->ad_netid) +			free(ad->ad_netid); +		if (ad->ad_uaddr) +			free(ad->ad_uaddr); +		FREE(ad, sizeof (struct ad_private)); +	} +	return (NULL); +} +/* + * Implement the five authentication operations + */ + + +/* + * 1. Next Verifier + */	 +/*ARGSUSED*/ +static void +authdes_nextverf(auth) +	AUTH *auth; +{ +	/* what the heck am I supposed to do??? */ +} +		 + + +/* + * 2. Marshal + */ +static bool_t +authdes_marshal(auth, xdrs) +	AUTH *auth; +	XDR *xdrs; +{ +	struct ad_private *ad = AUTH_PRIVATE(auth); +	struct authdes_cred *cred = &ad->ad_cred; +	struct authdes_verf *verf = &ad->ad_verf; +	des_block cryptbuf[2];	 +	des_block ivec; +	int status; +	long len; +	int32_t *ixdr; + +	/* +	 * Figure out the "time", accounting for any time difference +	 * with the server if necessary. +	 */ +	(void) gettimeofday(&ad->ad_timestamp, (struct timezone *)NULL); +	ad->ad_timestamp.tv_sec += ad->ad_timediff.tv_sec; +	ad->ad_timestamp.tv_usec += ad->ad_timediff.tv_usec; +	if (ad->ad_timestamp.tv_usec >= MILLION) { +		ad->ad_timestamp.tv_usec -= MILLION; +		ad->ad_timestamp.tv_sec += 1; +	} + +	/* +	 * XDR the timestamp and possibly some other things, then +	 * encrypt them. +	 */ +	ixdr = (int32_t *)cryptbuf; +	IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_sec); +	IXDR_PUT_LONG(ixdr, ad->ad_timestamp.tv_usec); +	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { +		IXDR_PUT_U_LONG(ixdr, ad->ad_window); +		IXDR_PUT_U_LONG(ixdr, ad->ad_window - 1); +		ivec.key.high = ivec.key.low = 0;	 +		status = cbc_crypt((char *)&auth->ah_key, (char *)cryptbuf,  +			2*sizeof(des_block), DES_ENCRYPT | DES_HW, (char *)&ivec); +	} else { +		status = ecb_crypt((char *)&auth->ah_key, (char *)cryptbuf,  +			sizeof(des_block), DES_ENCRYPT | DES_HW); +	} +	if (DES_FAILED(status)) { +		debug("authdes_marshal: DES encryption failure"); +		return (FALSE); +	} +	ad->ad_verf.adv_xtimestamp = cryptbuf[0]; +	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { +		ad->ad_cred.adc_fullname.window = cryptbuf[1].key.high; +		ad->ad_verf.adv_winverf = cryptbuf[1].key.low; +	} else { +		ad->ad_cred.adc_nickname = ad->ad_nickname; +		ad->ad_verf.adv_winverf = 0; +	} + +	/* +	 * Serialize the credential and verifier into opaque +	 * authentication data. +	 */ +	if (ad->ad_cred.adc_namekind == ADN_FULLNAME) { +		len = ((1 + 1 + 2 + 1)*BYTES_PER_XDR_UNIT + ad->ad_fullnamelen); +	} else { +		len = (1 + 1)*BYTES_PER_XDR_UNIT; +	} + +	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { +		IXDR_PUT_LONG(ixdr, AUTH_DES); +		IXDR_PUT_LONG(ixdr, len); +	} else { +		ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_cred.oa_flavor));  +		ATTEMPT(xdr_putlong(xdrs, &len));  +	} +	ATTEMPT(xdr_authdes_cred(xdrs, cred)); + +	len = (2 + 1)*BYTES_PER_XDR_UNIT;  +	if ((ixdr = xdr_inline(xdrs, 2*BYTES_PER_XDR_UNIT))) { +		IXDR_PUT_LONG(ixdr, AUTH_DES); +		IXDR_PUT_LONG(ixdr, len); +	} else { +		ATTEMPT(xdr_putlong(xdrs, (long *)&auth->ah_verf.oa_flavor));  +		ATTEMPT(xdr_putlong(xdrs, &len));  +	} +	ATTEMPT(xdr_authdes_verf(xdrs, verf)); +	return (TRUE); +} + + +/* + * 3. Validate + */ +static bool_t +authdes_validate(auth, rverf) +	AUTH *auth; +	struct opaque_auth *rverf; +{ +	struct ad_private *ad = AUTH_PRIVATE(auth); +	struct authdes_verf verf; +	int status; +	register u_long *ixdr; + +	if (rverf->oa_length != (2 + 1) * BYTES_PER_XDR_UNIT) { +		return (FALSE); +	} +	ixdr = (u_long *)rverf->oa_base; +	verf.adv_xtimestamp.key.high = (u_long)*ixdr++; +	verf.adv_xtimestamp.key.low = (u_long)*ixdr++; +	verf.adv_int_u = (u_long)*ixdr++;	/* nickname not XDR'd ! */ + +	/* +	 * Decrypt the timestamp +	 */ +	status = ecb_crypt((char *)&auth->ah_key, (char *)&verf.adv_xtimestamp, +		sizeof(des_block), DES_DECRYPT | DES_HW); + +	if (DES_FAILED(status)) { +		debug("authdes_validate: DES decryption failure"); +		return (FALSE); +	} + +	/* +	 * xdr the decrypted timestamp  +	 */ +	ixdr = (u_long *)verf.adv_xtimestamp.c; +	verf.adv_timestamp.tv_sec = IXDR_GET_LONG(ixdr) + 1; +	verf.adv_timestamp.tv_usec = IXDR_GET_LONG(ixdr); + +	/* +	 * validate +	 */ +	if (bcmp((char *)&ad->ad_timestamp, (char *)&verf.adv_timestamp, +		 sizeof(struct timeval)) != 0) { +		debug("authdes_validate: verifier mismatch\n"); +		return (FALSE); +	} + +	/* +	 * We have a nickname now, let's use it +	 */ +	ad->ad_nickname = verf.adv_nickname;	 +	ad->ad_cred.adc_namekind = ADN_NICKNAME;  +	return (TRUE);	 +} + +/* + * 4. Refresh + */ +static bool_t +authdes_refresh(auth) +	AUTH *auth; +{ +	struct ad_private *ad = AUTH_PRIVATE(auth); +	struct authdes_cred *cred = &ad->ad_cred; +	netobj		pkey; + +	if (ad->ad_dosync && +#ifdef old +			!synchronize(&ad->ad_syncaddr, &ad->ad_timediff)) { +#else +			!__rpc_get_time_offset(&ad->ad_timediff,ad->ad_nis_srvr, +					       ad->ad_timehost, &(ad->ad_uaddr), +				(struct sockaddr_in *)&(ad->ad_syncaddr))) { +#endif +		/* +		 * Hope the clocks are synced! +		 */ +		ad->ad_timediff.tv_sec = ad->ad_timediff.tv_usec = 0; +		ad->ad_dosync = 0; +		debug("authdes_refresh: unable to synchronize with server"); +	} +	ad->ad_xkey = auth->ah_key; +	pkey.n_bytes = (char *)(ad->ad_pkey); +	pkey.n_len = strlen((char *)ad->ad_pkey) + 1; +	if (key_encryptsession_pk(ad->ad_servername, &pkey, &ad->ad_xkey) < 0) { +		debug("authdes_create: unable to encrypt conversation key"); +		return (FALSE); +	} +	cred->adc_fullname.key = ad->ad_xkey; +	cred->adc_namekind = ADN_FULLNAME; +	cred->adc_fullname.name = ad->ad_fullname; +	return (TRUE); +} + + +/* + * 5. Destroy + */ +static void +authdes_destroy(auth) +	AUTH *auth; +{ +	struct ad_private *ad = AUTH_PRIVATE(auth); + +	FREE(ad->ad_fullname, ad->ad_fullnamelen + 1); +	FREE(ad->ad_servername, ad->ad_servernamelen + 1); +	FREE(ad, sizeof(struct ad_private)); +	FREE(auth, sizeof(AUTH)); +} +	 + +#ifdef old +/* + * Synchronize with the server at the given address, that is, + * adjust timep to reflect the delta between our clocks + */ +static bool_t +synchronize(syncaddr, timep) +	struct sockaddr *syncaddr; +	struct timeval *timep; +{ +	struct timeval mytime; +	struct timeval timeout; + +	timeout.tv_sec = RTIME_TIMEOUT; +	timeout.tv_usec = 0; +	if (rtime((struct sockaddr_in *)syncaddr, timep, NULL /*&timeout*/) < 0) { +		return (FALSE); +	} +	(void) gettimeofday(&mytime, (struct timezone *)NULL); +	timep->tv_sec -= mytime.tv_sec; +	if (mytime.tv_usec > timep->tv_usec) { +		timep->tv_sec -= 1; +		timep->tv_usec += MILLION; +	} +	timep->tv_usec -= mytime.tv_usec; +	return (TRUE); +} +#endif diff --git a/lib/libc/rpc/auth_none.c b/lib/libc/rpc/auth_none.c index 9c5a664795f6..b2e2995ac8fd 100644 --- a/lib/libc/rpc/auth_none.c +++ b/lib/libc/rpc/auth_none.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,17 +30,18 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)auth_none.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)auth_none.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: auth_none.c,v 1.1 1993/10/27 05:40:10 paul Exp $"; +static char *rcsid = "$Id: auth_none.c,v 1.5 1996/12/30 14:13:30 peter Exp $";  #endif  /*   * auth_none.c - * Creates a client authentication handle for passing "null"  - * credentials and verifiers to remote systems.  - *  - * Copyright (C) 1984, Sun Microsystems, Inc.  + * Creates a client authentication handle for passing "null" + * credentials and verifiers to remote systems. + * + * Copyright (C) 1984, Sun Microsystems, Inc.   */ +#include <stdlib.h>  #include <rpc/types.h>  #include <rpc/xdr.h>  #include <rpc/auth.h> @@ -110,7 +111,7 @@ authnone_marshal(client, xdrs)  	    ap->marshalled_client, ap->mcnt));  } -static void  +static void  authnone_verf()  {  } diff --git a/lib/libc/rpc/auth_time.c b/lib/libc/rpc/auth_time.c new file mode 100644 index 000000000000..2b9a5a929e41 --- /dev/null +++ b/lib/libc/rpc/auth_time.c @@ -0,0 +1,500 @@ +#pragma ident	"@(#)auth_time.c	1.4	92/11/10 SMI" + +/* + *	auth_time.c + * + * This module contains the private function __rpc_get_time_offset() + * which will return the difference in seconds between the local system's + * notion of time and a remote server's notion of time. This must be + * possible without calling any functions that may invoke the name + * service. (netdir_getbyxxx, getXbyY, etc). The function is used in the + * synchronize call of the authdes code to synchronize clocks between + * NIS+ clients and their servers. + * + * Note to minimize the amount of duplicate code, portions of the + * synchronize() function were folded into this code, and the synchronize + * call becomes simply a wrapper around this function. Further, if this + * function is called with a timehost it *DOES* recurse to the name + * server so don't use it in that mode if you are doing name service code. + * + *	Copyright (c) 1992 Sun Microsystems Inc. + *	All rights reserved. + * + * Side effects : + *	When called a client handle to a RPCBIND process is created + *	and destroyed. Two strings "netid" and "uaddr" are malloc'd + *	and returned. The SIGALRM processing is modified only if + *	needed to deal with TCP connections. + * + * NOTE: This code has had the crap beaten out it in order to convert + *       it from TI-RPC back to TD-RPC for use on FreeBSD. + */ +#include <stdio.h> +#include <syslog.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <netdb.h> +#include <sys/signal.h> +#include <sys/errno.h> +#include <sys/socket.h> +#include <netinet/in.h> +#include <arpa/inet.h> +#include <rpc/rpc.h> +#include <rpc/rpc_com.h> +#undef NIS +#include <rpcsvc/nis.h> + +/* + * FreeBSD currently uses RPC 4.0, which uses portmap rather than + * rpcbind. Consequently, we need to fake up these values here. + * Luckily, the RPCB_GETTIME procedure uses only base XDR data types + * so we don't need anything besides these magic numbers. + */ +#define RPCBPROG (u_long)100000 +#define RPCBVERS (u_long)3 +#define RPCBPROC_GETTIME (u_long)6 + +#ifdef TESTING +#define	msg(x)	printf("ERROR: %s\n", x) +/* #define msg(x) syslog(LOG_ERR, "%s", x) */ +#else +#define	msg(x) +#endif + +static int saw_alarm = 0; + +static void +alarm_hndler(s) +	int	s; +{ +	saw_alarm = 1; +	return; +} + +/* + * The internet time server defines the epoch to be Jan 1, 1900 + * whereas UNIX defines it to be Jan 1, 1970. To adjust the result + * from internet time-service time, into UNIX time we subtract the + * following offset : + */ +#define	NYEARS	(1970 - 1900) +#define	TOFFSET ((u_long)60*60*24*(365*NYEARS + (NYEARS/4))) + + +/* + * Stolen from rpc.nisd: + * Turn a 'universal address' into a struct sockaddr_in. + * Bletch. + */ +static int uaddr_to_sockaddr(uaddr, sin) +#ifdef foo +	endpoint		*endpt; +#endif +	char			*uaddr; +	struct sockaddr_in	*sin; +{ +	unsigned char		p_bytes[2]; +	int			i; +	unsigned long		a[6]; + +	i = sscanf(uaddr, "%lu.%lu.%lu.%lu.%lu.%lu", &a[0], &a[1], &a[2], +						&a[3], &a[4], &a[5]); + +	if (i < 6) +		return(1); + +	for (i = 0; i < 4; i++) +		sin->sin_addr.s_addr |= (a[i] & 0x000000FF) << (8 * i); + +	p_bytes[0] = (unsigned char)a[4] & 0x000000FF; +	p_bytes[1] = (unsigned char)a[5] & 0x000000FF; + +	sin->sin_family = AF_INET; /* always */ +	bcopy((char *)&p_bytes, (char *)&sin->sin_port, 2); + +	return (0); +} + +/* + * free_eps() + * + * Free the strings that were strduped into the eps structure. + */ +static void +free_eps(eps, num) +	endpoint	eps[]; +	int		num; +{ +	int		i; + +	for (i = 0; i < num; i++) { +		free(eps[i].uaddr); +		free(eps[i].proto); +		free(eps[i].family); +	} +	return; +} + +/* + * get_server() + * + * This function constructs a nis_server structure description for the + * indicated hostname. + * + * NOTE: There is a chance we may end up recursing here due to the + * fact that gethostbyname() could do an NIS search. Ideally, the + * NIS+ server will call __rpc_get_time_offset() with the nis_server + * structure already populated. + */ +static nis_server * +get_server(sin, host, srv, eps, maxep) +	struct sockaddr_in *sin; +	char		*host;	/* name of the time host	*/ +	nis_server	*srv;	/* nis_server struct to use.	*/ +	endpoint	eps[];	/* array of endpoints		*/ +	int		maxep;	/* max array size		*/ +{ +	char			hname[256]; +	int			num_ep = 0, i; +	struct hostent		*he; +	struct hostent		dummy; +	char			*ptr[2]; + +	if (host == NULL && sin == NULL) +		return (NULL); + +	if (sin == NULL) { +		he = gethostbyname(host); +		if (he == NULL) +			return(NULL); +	} else { +		he = &dummy; +		ptr[0] = (char *)&sin->sin_addr.s_addr; +		ptr[1] = NULL; +		dummy.h_addr_list = ptr; +	} + +	/* +	 * This is lame. We go around once for TCP, then again +	 * for UDP. +	 */ +	for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep); +						i++, num_ep++) { +		struct in_addr *a; + +		a = (struct in_addr *)he->h_addr_list[i]; +		snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a)); +		eps[num_ep].uaddr = strdup(hname); +		eps[num_ep].family = strdup("inet"); +		eps[num_ep].proto =  strdup("tcp"); +	} + +	for (i = 0; (he->h_addr_list[i] != NULL) && (num_ep < maxep); +						i++, num_ep++) { +		struct in_addr *a; + +		a = (struct in_addr *)he->h_addr_list[i]; +		snprintf(hname, sizeof(hname), "%s.0.111", inet_ntoa(*a)); +		eps[num_ep].uaddr = strdup(hname); +		eps[num_ep].family = strdup("inet"); +		eps[num_ep].proto =  strdup("udp"); +	} + +	srv->name = (nis_name) host; +	srv->ep.ep_len = num_ep; +	srv->ep.ep_val = eps; +	srv->key_type = NIS_PK_NONE; +	srv->pkey.n_bytes = NULL; +	srv->pkey.n_len = 0; +	return (srv); +} + +/* + * __rpc_get_time_offset() + * + * This function uses a nis_server structure to contact the a remote + * machine (as named in that structure) and returns the offset in time + * between that machine and this one. This offset is returned in seconds + * and may be positive or negative. + * + * The first time through, a lot of fiddling is done with the netconfig + * stuff to find a suitable transport. The function is very aggressive + * about choosing UDP or at worst TCP if it can. This is because + * those transports support both the RCPBIND call and the internet + * time service. + * + * Once through, *uaddr is set to the universal address of + * the machine and *netid is set to the local netid for the transport + * that uaddr goes with. On the second call, the netconfig stuff + * is skipped and the uaddr/netid pair are used to fetch the netconfig + * structure and to then contact the machine for the time. + * + * td = "server" - "client" + */ +int +__rpc_get_time_offset(td, srv, thost, uaddr, netid) +	struct timeval	*td;	 /* Time difference			*/ +	nis_server	*srv;	 /* NIS Server description 		*/ +	char		*thost;	 /* if no server, this is the timehost	*/ +	char		**uaddr; /* known universal address		*/ +	struct sockaddr_in *netid; /* known network identifier		*/ +{ +	CLIENT			*clnt; 		/* Client handle 	*/ +	endpoint		*ep,		/* useful endpoints	*/ +				*useep = NULL;	/* endpoint of xp	*/ +	char			*useua = NULL;	/* uaddr of selected xp	*/ +	int			epl, i;		/* counters		*/ +	enum clnt_stat		status;		/* result of clnt_call	*/ +	u_long			thetime, delta; +	int			needfree = 0; +	struct timeval		tv; +	int			time_valid; +	int			udp_ep = -1, tcp_ep = -1; +	int			a1, a2, a3, a4; +	char			ut[64], ipuaddr[64]; +	endpoint		teps[32]; +	nis_server		tsrv; +	void			(*oldsig)() = NULL; /* old alarm handler */ +	struct sockaddr_in	sin; +	int			s = RPC_ANYSOCK, len; +	int			type = 0; + +	td->tv_sec = 0; +	td->tv_usec = 0; + +	/* +	 * First check to see if we need to find and address for this +	 * server. +	 */ +	if (*uaddr == NULL) { +		if ((srv != NULL) && (thost != NULL)) { +			msg("both timehost and srv pointer used!"); +			return (0); +		} +		if (! srv) { +			srv = get_server(netid, thost, &tsrv, teps, 32); +			if (srv == NULL) { +				msg("unable to contruct server data."); +				return (0); +			} +			needfree = 1;	/* need to free data in endpoints */ +		} + +		ep = srv->ep.ep_val; +		epl = srv->ep.ep_len; + +		/* Identify the TCP and UDP endpoints */ +		for (i = 0; +			(i < epl) && ((udp_ep == -1) || (tcp_ep == -1)); i++) { +			if (strcasecmp(ep[i].proto, "udp") == 0) +				udp_ep = i; +			if (strcasecmp(ep[i].proto, "tcp") == 0) +				tcp_ep = i; +		} + +		/* Check to see if it is UDP or TCP */ +		if (tcp_ep > -1) { +			useep = &ep[tcp_ep]; +			useua = ep[tcp_ep].uaddr; +			type = SOCK_STREAM; +		} else if (udp_ep > -1) { +			useep = &ep[udp_ep]; +			useua = ep[udp_ep].uaddr; +			type = SOCK_DGRAM; +		} + +		if (useep == NULL) { +			msg("no acceptable transport endpoints."); +			if (needfree) +				free_eps(teps, tsrv.ep.ep_len); +			return (0); +		} +	} + +	/* +	 * Create a sockaddr from the uaddr. +	 */ +	if (*uaddr != NULL) +		useua = *uaddr; + +	/* Fixup test for NIS+ */ +	sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4); +	sprintf(ipuaddr, "%d.%d.%d.%d.0.111", a1, a2, a3, a4); +	useua = &ipuaddr[0]; + +	if (uaddr_to_sockaddr(useua, &sin)) { +		msg("unable to translate uaddr to sockaddr."); +		if (needfree) +			free_eps(teps, tsrv.ep.ep_len); +		return (0); +	} + +	/* +	 * Create the client handle to rpcbind. Note we always try +	 * version 3 since that is the earliest version that supports +	 * the RPCB_GETTIME call. Also it is the version that comes +	 * standard with SVR4. Since most everyone supports TCP/IP +	 * we could consider trying the rtime call first. +	 */ +	clnt = clnttcp_create(&sin, RPCBPROG, RPCBVERS, &s, 0, 0); +	if (clnt == NULL) { +		msg("unable to create client handle to rpcbind."); +		if (needfree) +			free_eps(teps, tsrv.ep.ep_len); +		return (0); +	} + +	tv.tv_sec = 5; +	tv.tv_usec = 0; +	time_valid = 0; +	status = clnt_call(clnt, RPCBPROC_GETTIME, xdr_void, NULL, +					xdr_u_long, (char *)&thetime, tv); +	/* +	 * The only error we check for is anything but success. In +	 * fact we could have seen PROGMISMATCH if talking to a 4.1 +	 * machine (pmap v2) or TIMEDOUT if the net was busy. +	 */ +	if (status == RPC_SUCCESS) +		time_valid = 1; +	else { +		int save; + +		/* Blow away possible stale CLNT handle. */ +		if (clnt != NULL) { +			clnt_destroy(clnt); +			clnt = NULL; +		} + +		/* +		 * Convert PMAP address into timeservice address +		 * We take advantage of the fact that we "know" what +		 * the universal address looks like for inet transports. +		 * +		 * We also know that the internet timeservice is always +		 * listening on port 37. +		 */ +		sscanf(useua, "%d.%d.%d.%d.", &a1, &a2, &a3, &a4); +		sprintf(ut, "%d.%d.%d.%d.0.37", a1, a2, a3, a4); + +		if (uaddr_to_sockaddr(ut, &sin)) { +			msg("cannot convert timeservice uaddr to sockaddr."); +			goto error; +		} + +		s = socket(AF_INET, type, 0); +		if (s == -1) { +			msg("unable to open fd to network."); +			goto error; +		} + +		/* +		 * Now depending on whether or not we're talking to +		 * UDP we set a timeout or not. +		 */ +		if (type == SOCK_DGRAM) { +			struct timeval timeout = { 20, 0 }; +			struct sockaddr_in from; +			fd_set readfds; +			int res; + +			if (sendto(s, &thetime, sizeof(thetime), 0, +				(struct sockaddr *)&sin, sizeof(sin)) == -1) { +				msg("udp : sendto failed."); +				goto error; +			} +			do { +				FD_ZERO(&readfds); +				FD_SET(s, &readfds); +				res = select(_rpc_dtablesize(), &readfds, +				     (fd_set *)NULL, (fd_set *)NULL, &timeout); +			} while (res < 0 && errno == EINTR); +			if (res <= 0) +				goto error; +			len = sizeof(from); +			res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0, +				       (struct sockaddr *)&from, &len); +			if (res == -1) { +				msg("recvfrom failed on udp transport."); +				goto error; +			} +			time_valid = 1; +		} else { +			int res; + +			oldsig = (void (*)())signal(SIGALRM, alarm_hndler); +			saw_alarm = 0; /* global tracking the alarm */ +			alarm(20); /* only wait 20 seconds */ +			res = connect(s, (struct sockaddr *)&sin, sizeof(sin)); +			if (res == -1) { +				msg("failed to connect to tcp endpoint."); +				goto error; +			} +			if (saw_alarm) { +				msg("alarm caught it, must be unreachable."); +				goto error; +			} +			res = read(s, (char *)&thetime, sizeof(thetime)); +			if (res != sizeof(thetime)) { +				if (saw_alarm) +					msg("timed out TCP call."); +				else +					msg("wrong size of results returned"); + +				goto error; +			} +			time_valid = 1; +		} +		save = errno; +		(void) close(s); +		errno = save; +		s = RPC_ANYSOCK; + +		if (time_valid) { +			thetime = ntohl(thetime); +			thetime = thetime - TOFFSET; /* adjust to UNIX time */ +		} else +			thetime = 0; +	} + +	gettimeofday(&tv, 0); + +error: +	/* +	 * clean up our allocated data structures. +	 */ + +	if (s != RPC_ANYSOCK) +		(void) close(s); + +	if (clnt != NULL) +		clnt_destroy(clnt); + +	alarm(0);	/* reset that alarm if its outstanding */ +	if (oldsig) { +		signal(SIGALRM, oldsig); +	} + +	/* +	 * note, don't free uaddr strings until after we've made a +	 * copy of them. +	 */ +	if (time_valid) { +		if (*uaddr == NULL) +			*uaddr = strdup(useua); + +		/* Round to the nearest second */ +		tv.tv_sec += (tv.tv_sec > 500000) ? 1 : 0; +		delta = (thetime > tv.tv_sec) ? thetime - tv.tv_sec : +						tv.tv_sec - thetime; +		td->tv_sec = (thetime < tv.tv_sec) ? - delta : delta; +		td->tv_usec = 0; +	} else { +		msg("unable to get the server's time."); +	} + +	if (needfree) +		free_eps(teps, tsrv.ep.ep_len); + +	return (time_valid); +} diff --git a/lib/libc/rpc/auth_unix.c b/lib/libc/rpc/auth_unix.c index 334dc56c265a..32200c2cb35a 100644 --- a/lib/libc/rpc/auth_unix.c +++ b/lib/libc/rpc/auth_unix.c @@ -5,11 +5,11 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. @@ -17,11 +17,11 @@   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,12 +30,12 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)auth_unix.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)auth_unix.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: auth_unix.c,v 1.1 1993/10/27 05:40:11 paul Exp $"; +static char *rcsid = "$Id: auth_unix.c,v 1.7 1996/12/30 14:14:39 peter Exp $";  #endif  /* - * auth_unix.c, Implements UNIX style authentication parameters.  - *   + * auth_unix.c, Implements UNIX style authentication parameters. + *   * Copyright (C) 1984, Sun Microsystems, Inc.   *   * The system is very weak.  The client uses no encryption for it's @@ -47,7 +47,10 @@ static char *rcsid = "$Id: auth_unix.c,v 1.1 1993/10/27 05:40:11 paul Exp $";  #include <stdio.h>  #include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/param.h>  #include <rpc/types.h>  #include <rpc/xdr.h>  #include <rpc/auth.h> @@ -82,8 +85,20 @@ struct audata {  };  #define	AUTH_PRIVATE(auth)	((struct audata *)auth->ah_private) -static bool_t marshal_new_auth(); +static void marshal_new_auth(); + +/* + * This goop is here because some servers refuse to accept a + * credential with more than some number (usually 8) supplementary + * groups.  Blargh! + */ +static int authunix_maxgrouplist = 0; +void +set_rpc_maxgrouplist(int num) +{ +	authunix_maxgrouplist = num; +}  /*   * Create a unix style authenticator. @@ -134,14 +149,20 @@ authunix_create(machname, uid, gid, len, aup_gids)  	aup.aup_machname = machname;  	aup.aup_uid = uid;  	aup.aup_gid = gid; -	aup.aup_len = (u_int)len; +	/* GW: continuation of max group list hack */ +	if(authunix_maxgrouplist != 0) { +		aup.aup_len = ((len < authunix_maxgrouplist) ? len +			       : authunix_maxgrouplist); +	} else { +		aup.aup_len = (u_int)len; +	}  	aup.aup_gids = aup_gids;  	/*  	 * Serialize the parameters into origcred  	 */  	xdrmem_create(&xdrs, mymem, MAX_AUTH_BYTES, XDR_ENCODE); -	if (! xdr_authunix_parms(&xdrs, &aup))  +	if (! xdr_authunix_parms(&xdrs, &aup))  		abort();  	au->au_origcred.oa_length = len = XDR_GETPOS(&xdrs);  	au->au_origcred.oa_flavor = AUTH_UNIX; @@ -153,7 +174,7 @@ authunix_create(machname, uid, gid, len, aup_gids)  		return (NULL);  	}  #endif -	bcopy(mymem, au->au_origcred.oa_base, (u_int)len); +	memcpy(au->au_origcred.oa_base, mymem, (u_int)len);  	/*  	 * set auth handle to reflect new cred. @@ -175,14 +196,20 @@ authunix_create_default()  	register int uid;  	register int gid;  	int gids[NGRPS]; +	int i; +	gid_t real_gids[NGROUPS];  	if (gethostname(machname, MAX_MACHINE_NAME) == -1)  		abort();  	machname[MAX_MACHINE_NAME] = 0; -	uid = geteuid(); -	gid = getegid(); -	if ((len = getgroups(NGRPS, gids)) < 0) +	uid = (int)geteuid(); +	gid = (int)getegid(); +	if ((len = getgroups(NGROUPS, real_gids)) < 0)  		abort(); +	if(len > NGRPS) len = NGRPS; /* GW: turn `gid_t's into `int's */ +	for(i = 0; i < len; i++) { +		gids[i] = (int)real_gids[i]; +	}  	return (authunix_create(machname, uid, gid, len, gids));  } @@ -259,7 +286,7 @@ authunix_refresh(auth)  	xdrmem_create(&xdrs, au->au_origcred.oa_base,  	    au->au_origcred.oa_length, XDR_DECODE);  	stat = xdr_authunix_parms(&xdrs, &aup); -	if (! stat)  +	if (! stat)  		goto done;  	/* update the time and serialize in place */ @@ -303,7 +330,7 @@ authunix_destroy(auth)   * Marshals (pre-serializes) an auth struct.   * sets private data, au_marshed and au_mpos   */ -static bool_t +static void  marshal_new_auth(auth)  	register AUTH *auth;  { diff --git a/lib/libc/rpc/authdes_prot.c b/lib/libc/rpc/authdes_prot.c new file mode 100644 index 000000000000..14679c00a9cc --- /dev/null +++ b/lib/libc/rpc/authdes_prot.c @@ -0,0 +1,82 @@ +#if defined(LIBC_SCCS) && !defined(lint) +static char sccsid[] = 	"@(#)authdes_prot.c	2.1 88/07/29 4.0 RPCSRC; from 1.6 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + *  + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + *  + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + *  + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * authdes_prot.c, XDR routines for DES authentication + */ + +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> + +#define ATTEMPT(xdr_op) if (!(xdr_op)) return (FALSE) + +bool_t +xdr_authdes_cred(xdrs, cred) +	XDR *xdrs; +	struct authdes_cred *cred; +{ +	/* +	 * Unrolled xdr +	 */ +	ATTEMPT(xdr_enum(xdrs, (enum_t *)&cred->adc_namekind)); +	switch (cred->adc_namekind) { +	case ADN_FULLNAME: +		ATTEMPT(xdr_string(xdrs, &cred->adc_fullname.name, MAXNETNAMELEN)); +		ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.key, sizeof(des_block))); +		ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_fullname.window, sizeof(cred->adc_fullname.window))); +		return (TRUE); +	case ADN_NICKNAME: +		ATTEMPT(xdr_opaque(xdrs, (caddr_t)&cred->adc_nickname, sizeof(cred->adc_nickname))); +		return (TRUE); +	default: +		return (FALSE); +	} +} + + +bool_t +xdr_authdes_verf(xdrs, verf) +	register XDR *xdrs; +	register struct authdes_verf *verf;	 +{ +	/* + 	 * Unrolled xdr + 	 */ +	ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_xtimestamp, sizeof(des_block))); +	ATTEMPT(xdr_opaque(xdrs, (caddr_t)&verf->adv_int_u, sizeof(verf->adv_int_u))); +	return (TRUE); +} diff --git a/lib/libc/rpc/authunix_prot.c b/lib/libc/rpc/authunix_prot.c index 15faf184cfb5..c818ba0de77c 100644 --- a/lib/libc/rpc/authunix_prot.c +++ b/lib/libc/rpc/authunix_prot.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)authunix_prot.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)authunix_prot.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: authunix_prot.c,v 1.1 1993/10/27 05:40:15 paul Exp $"; +static char *rcsid = "$Id: authunix_prot.c,v 1.2 1995/05/30 05:41:12 rgrimes Exp $";  #endif  /* diff --git a/lib/libc/rpc/bindresvport.3 b/lib/libc/rpc/bindresvport.3 index 1fb1f9a30600..5dd71e35d25f 100644 --- a/lib/libc/rpc/bindresvport.3 +++ b/lib/libc/rpc/bindresvport.3 @@ -1,27 +1,30 @@  .\" @(#)bindresvport.3n	2.2 88/08/02 4.0 RPCSRC; from 1.7 88/03/14 SMI -.TH BINDRESVPORT 3N  "22 november 1987" -.SH NAME -bindresvport \- bind a socket to a privileged IP port -.SH SYNOPSIS -.nf -.B #include <sys/types.h> -.B #include <netinet/in.h> -.LP -.B int bindresvport(sd, sin) -.B int sd; -.B struct sockaddr_in \(**sin; -.fi -.SH DESCRIPTION -.LP -.B bindresvport(\|) +.Dd "22 november 1987" +.Dt BINDRESVPORT 3 +.Os +.Sh NAME +.Nm bindresvport +.Ndbind a socket to a privileged IP port +.Sh SYNOPSIS +.Fd #include <sys/types.h> +.Fd #include <netinet/in.h> +.Ft int +.Fn bindresvport "int sd" "struct sockaddr_in **sin" +.Sh DESCRIPTION +.Nm Bindresvport  is used to bind a socket descriptor to a privileged -.SM IP +.Tn IP  port, that is, a  port number in the range 0-1023.  The routine returns 0 if it is successful, -otherwise \-1 is returned and -.B errno +otherwise -1 is returned and +.Va errno  set to reflect the cause of the error. -.LP +.Pp  Only root can bind to a privileged port; this call will fail for any  other users. +.Pp +If the value of sin->sin_port is non-zero +.Fn bindresvport +will attempt to use that specific port.  If it fails, it chooses another +privileged port automatically. diff --git a/lib/libc/rpc/bindresvport.c b/lib/libc/rpc/bindresvport.c index a085c910c3c3..dea87057c019 100644 --- a/lib/libc/rpc/bindresvport.c +++ b/lib/libc/rpc/bindresvport.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,55 +30,78 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)bindresvport.c 1.8 88/02/08 SMI";*/  /*static char *sccsid = "from: @(#)bindresvport.c	2.2 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: bindresvport.c,v 1.1 1993/10/27 05:40:17 paul Exp $"; +/*from: OpenBSD: bindresvport.c,v 1.7 1996/07/30 16:25:47 downsj Exp */ +static char *rcsid = "$Id: bindresvport.c,v 1.6 1996/12/30 14:12:36 peter Exp $";  #endif  /*   * Copyright (c) 1987 by Sun Microsystems, Inc. + * + * Portions Copyright(C) 1996, Jason Downs.  All rights reserved.   */  #include <sys/types.h>  #include <sys/errno.h>  #include <sys/socket.h>  #include <netinet/in.h> +#include <unistd.h> +#include <string.h>  /*   * Bind a socket to a privileged IP port   */ +int  bindresvport(sd, sin)  	int sd;  	struct sockaddr_in *sin;  { -	int res; -	static short port; +	int on, old, error;  	struct sockaddr_in myaddr; -	extern int errno; -	int i; - -#define STARTPORT 600 -#define ENDPORT (IPPORT_RESERVED - 1) -#define NPORTS	(ENDPORT - STARTPORT + 1) +	int sinlen = sizeof(struct sockaddr_in);  	if (sin == (struct sockaddr_in *)0) {  		sin = &myaddr; -		bzero(sin, sizeof (*sin)); +		memset(sin, 0, sinlen); +		sin->sin_len = sinlen;  		sin->sin_family = AF_INET;  	} else if (sin->sin_family != AF_INET) {  		errno = EPFNOSUPPORT;  		return (-1);  	} -	if (port == 0) { -		port = (getpid() % NPORTS) + STARTPORT; + +	if (sin->sin_port == 0) { +		int oldlen = sizeof(old); +		error = getsockopt(sd, IPPROTO_IP, IP_PORTRANGE, +				   &old, &oldlen); +		if (error < 0) +			return(error); + +		on = IP_PORTRANGE_LOW; +		error = setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, +		           	   &on, sizeof(on)); +		if (error < 0) +			return(error);  	} -	res = -1; -	errno = EADDRINUSE; -	for (i = 0; i < NPORTS && res < 0 && errno == EADDRINUSE; i++) { -		sin->sin_port = htons(port++); -		if (port > ENDPORT) { -			port = STARTPORT; + +	error = bind(sd, (struct sockaddr *)sin, sinlen); + +	if (sin->sin_port == 0) { +		int saved_errno = errno; + +		if (error) { +			if (setsockopt(sd, IPPROTO_IP, IP_PORTRANGE, +			    &old, sizeof(old)) < 0) +				errno = saved_errno; +			return (error); +		} + +		if (sin != &myaddr) { +			/* Hmm, what did the kernel assign... */ +			if (getsockname(sd, (struct sockaddr *)sin, +			    &sinlen) < 0) +				errno = saved_errno; +			return (error);  		} -		res = bind(sd, -		    (struct sockaddr *)sin, sizeof(struct sockaddr_in));  	} -	return (res); +	return (error);  } diff --git a/lib/libc/rpc/clnt_generic.c b/lib/libc/rpc/clnt_generic.c index ad9c22bb7191..ed754ea6a697 100644 --- a/lib/libc/rpc/clnt_generic.c +++ b/lib/libc/rpc/clnt_generic.c @@ -5,11 +5,11 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. @@ -17,11 +17,11 @@   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)clnt_generic.c 1.4 87/08/11 (C) 1987 SMI";*/  /*static char *sccsid = "from: @(#)clnt_generic.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: clnt_generic.c,v 1.1 1993/10/27 05:40:19 paul Exp $"; +static char *rcsid = "$Id: clnt_generic.c,v 1.5 1996/12/30 14:17:20 peter Exp $";  #endif  /* @@ -40,10 +40,11 @@ static char *rcsid = "$Id: clnt_generic.c,v 1.1 1993/10/27 05:40:19 paul Exp $";  #include <sys/socket.h>  #include <sys/errno.h>  #include <netdb.h> +#include <string.h>  /*   * Generic client creation: takes (hostname, program-number, protocol) and - * returns client handle. Default options are set, which the user can  + * returns client handle. Default options are set, which the user can   * change using the rpc equivalent of ioctl()'s.   */  CLIENT * @@ -56,10 +57,27 @@ clnt_create(hostname, prog, vers, proto)  	struct hostent *h;  	struct protoent *p;  	struct sockaddr_in sin; +	struct sockaddr_un sun;  	int sock; -	struct timeval tv; +	static struct timeval tv;  	CLIENT *client; +	if (!strcmp(proto, "unix")) { +		bzero((char *)&sun, sizeof(sun)); +		sun.sun_family = AF_UNIX; +		strcpy(sun.sun_path, hostname); +		sun.sun_len = sizeof(sun.sun_len) + sizeof(sun.sun_family) + +				strlen(sun.sun_path) + 1; +		sock = RPC_ANYSOCK; +		client = clntunix_create(&sun, prog, vers, &sock, 0, 0); +		if (client == NULL) +			return(NULL); +		tv.tv_sec = 25; +		tv.tv_usec = 0; +		clnt_control(client, CLSET_TIMEOUT, &tv); +		return(client); +	} +  	h = gethostbyname(hostname);  	if (h == NULL) {  		rpc_createerr.cf_stat = RPC_UNKNOWNHOST; @@ -70,17 +88,18 @@ clnt_create(hostname, prog, vers, proto)  		 * Only support INET for now  		 */  		rpc_createerr.cf_stat = RPC_SYSTEMERROR; -		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;  +		rpc_createerr.cf_error.re_errno = EAFNOSUPPORT;  		return (NULL);  	} +	memset(&sin, 0, sizeof(sin)); +	sin.sin_len = sizeof(struct sockaddr_in);  	sin.sin_family = h->h_addrtype;  	sin.sin_port = 0; -	bzero(sin.sin_zero, sizeof(sin.sin_zero)); -	bcopy(h->h_addr, (char*)&sin.sin_addr, h->h_length); +	memcpy((char*)&sin.sin_addr, h->h_addr, h->h_length);  	p = getprotobyname(proto);  	if (p == NULL) {  		rpc_createerr.cf_stat = RPC_UNKNOWNPROTO; -		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;  +		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;  		return (NULL);  	}  	sock = RPC_ANYSOCK; @@ -92,21 +111,26 @@ clnt_create(hostname, prog, vers, proto)  		if (client == NULL) {  			return (NULL);  		} +#if 0	/* XXX do we need this? */  		tv.tv_sec = 25; +		tv.tv_usec = 0;  		clnt_control(client, CLSET_TIMEOUT, &tv); +#endif  		break;  	case IPPROTO_TCP:  		client = clnttcp_create(&sin, prog, vers, &sock, 0, 0);  		if (client == NULL) {  			return (NULL);  		} +#if 0	/* XXX do we need this? */  		tv.tv_sec = 25;  		tv.tv_usec = 0;  		clnt_control(client, CLSET_TIMEOUT, &tv); +#endif  		break;  	default:  		rpc_createerr.cf_stat = RPC_SYSTEMERROR; -		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;  +		rpc_createerr.cf_error.re_errno = EPFNOSUPPORT;  		return (NULL);  	}  	return (client); diff --git a/lib/libc/rpc/clnt_perror.c b/lib/libc/rpc/clnt_perror.c index 9a7d76cbc200..79baac248b44 100644 --- a/lib/libc/rpc/clnt_perror.c +++ b/lib/libc/rpc/clnt_perror.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)clnt_perror.c 1.15 87/10/07 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)clnt_perror.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: clnt_perror.c,v 1.1 1993/10/27 05:40:20 paul Exp $"; +static char *rcsid = "$Id: clnt_perror.c,v 1.6 1996/12/30 14:19:34 peter Exp $";  #endif  /* @@ -40,6 +40,7 @@ static char *rcsid = "$Id: clnt_perror.c,v 1.1 1993/10/27 05:40:20 paul Exp $";   *   */  #include <stdio.h> +#include <stdlib.h>  #include <string.h>  #include <rpc/rpc.h>  #include <rpc/types.h> @@ -47,6 +48,7 @@ static char *rcsid = "$Id: clnt_perror.c,v 1.1 1993/10/27 05:40:20 paul Exp $";  #include <rpc/clnt.h>  static char *auth_errmsg(); +#define CLNT_PERROR_BUFLEN 256  static char *buf; @@ -55,7 +57,7 @@ _buf()  {  	if (buf == 0) -		buf = (char *)malloc(256); +		buf = (char *)malloc(CLNT_PERROR_BUFLEN);  	return (buf);  } @@ -68,7 +70,6 @@ clnt_sperror(rpch, s)  	char *s;  {  	struct rpc_err e; -	void clnt_perrno();  	char *err;  	char *str = _buf();  	char *strstart = str; @@ -77,17 +78,14 @@ clnt_sperror(rpch, s)  		return (0);  	CLNT_GETERR(rpch, &e); -	(void) sprintf(str, "%s: ", s);   -	str += strlen(str); - -	(void) strcpy(str, clnt_sperrno(e.re_status));   +	(void) sprintf(str, "%s: %s", s, clnt_sperrno(e.re_status));  	str += strlen(str);  	switch (e.re_status) {  	case RPC_SUCCESS:  	case RPC_CANTENCODEARGS:  	case RPC_CANTDECODERES: -	case RPC_TIMEDOUT:      +	case RPC_TIMEDOUT:  	case RPC_PROGUNAVAIL:  	case RPC_PROCUNAVAIL:  	case RPC_CANTDECODEARGS: @@ -101,16 +99,14 @@ clnt_sperror(rpch, s)  	case RPC_CANTSEND:  	case RPC_CANTRECV: -		(void) sprintf(str, "; errno = %s", -		    strerror(e.re_errno));  -		str += strlen(str); +		(void) snprintf(str, CLNT_PERROR_BUFLEN - (str - strstart), +			"; errno = %s\n", strerror(e.re_errno));  		break;  	case RPC_VERSMISMATCH:  		(void) sprintf(str, -			"; low version = %lu, high version = %lu",  +			"; low version = %lu, high version = %lu\n",  			e.re_vers.low, e.re_vers.high); -		str += strlen(str);  		break;  	case RPC_AUTHERROR: @@ -118,30 +114,28 @@ clnt_sperror(rpch, s)  		(void) sprintf(str,"; why = ");  		str += strlen(str);  		if (err != NULL) { -			(void) sprintf(str, "%s",err); +			(void) sprintf(str, "%s\n",err);  		} else {  			(void) sprintf(str, -				"(unknown authentication error - %d)", +				"(unknown authentication error - %d)\n",  				(int) e.re_why);  		} -		str += strlen(str);  		break;  	case RPC_PROGVERSMISMATCH: -		(void) sprintf(str,  -			"; low version = %lu, high version = %lu",  +		(void) sprintf(str, +			"; low version = %lu, high version = %lu\n",  			e.re_vers.low, e.re_vers.high); -		str += strlen(str);  		break;  	default:	/* unknown */ -		(void) sprintf(str,  -			"; s1 = %lu, s2 = %lu",  +		(void) sprintf(str, +			"; s1 = %lu, s2 = %lu\n",  			e.re_lb.s1, e.re_lb.s2); -		str += strlen(str);  		break;  	} -	(void) sprintf(str, "\n"); +	strstart[CLNT_PERROR_BUFLEN-2] = '\n'; +	strstart[CLNT_PERROR_BUFLEN-1] = '\0';  	return(strstart) ;  } @@ -150,52 +144,29 @@ clnt_perror(rpch, s)  	CLIENT *rpch;  	char *s;  { -	(void) fprintf(stderr,"%s",clnt_sperror(rpch,s)); +	(void) fprintf(stderr,"%s\n",clnt_sperror(rpch,s));  } -struct rpc_errtab { -	enum clnt_stat status; -	char *message; -}; - -static struct rpc_errtab  rpc_errlist[] = { -	{ RPC_SUCCESS,  -		"RPC: Success" },  -	{ RPC_CANTENCODEARGS,  -		"RPC: Can't encode arguments" }, -	{ RPC_CANTDECODERES,  -		"RPC: Can't decode result" }, -	{ RPC_CANTSEND,  -		"RPC: Unable to send" }, -	{ RPC_CANTRECV,  -		"RPC: Unable to receive" }, -	{ RPC_TIMEDOUT,  -		"RPC: Timed out" }, -	{ RPC_VERSMISMATCH,  -		"RPC: Incompatible versions of RPC" }, -	{ RPC_AUTHERROR,  -		"RPC: Authentication error" }, -	{ RPC_PROGUNAVAIL,  -		"RPC: Program unavailable" }, -	{ RPC_PROGVERSMISMATCH,  -		"RPC: Program/version mismatch" }, -	{ RPC_PROCUNAVAIL,  -		"RPC: Procedure unavailable" }, -	{ RPC_CANTDECODEARGS,  -		"RPC: Server can't decode arguments" }, -	{ RPC_SYSTEMERROR,  -		"RPC: Remote system error" }, -	{ RPC_UNKNOWNHOST,  -		"RPC: Unknown host" }, -	{ RPC_UNKNOWNPROTO, -		"RPC: Unknown protocol" }, -	{ RPC_PMAPFAILURE,  -		"RPC: Port mapper failure" }, -	{ RPC_PROGNOTREGISTERED,  -		"RPC: Program not registered"}, -	{ RPC_FAILED,  -		"RPC: Failed (unspecified error)"} +static const char *const rpc_errlist[] = { +	"RPC: Success",				/*  0 - RPC_SUCCESS */ +	"RPC: Can't encode arguments",		/*  1 - RPC_CANTENCODEARGS */ +	"RPC: Can't decode result",		/*  2 - RPC_CANTDECODERES */ +	"RPC: Unable to send",			/*  3 - RPC_CANTSEND */ +	"RPC: Unable to receive",		/*  4 - RPC_CANTRECV */ +	"RPC: Timed out",			/*  5 - RPC_TIMEDOUT */ +	"RPC: Incompatible versions of RPC",	/*  6 - RPC_VERSMISMATCH */ +	"RPC: Authentication error",		/*  7 - RPC_AUTHERROR */ +	"RPC: Program unavailable",		/*  8 - RPC_PROGUNAVAIL */ +	"RPC: Program/version mismatch",	/*  9 - RPC_PROGVERSMISMATCH */ +	"RPC: Procedure unavailable",		/* 10 - RPC_PROCUNAVAIL */ +	"RPC: Server can't decode arguments",	/* 11 - RPC_CANTDECODEARGS */ +	"RPC: Remote system error",		/* 12 - RPC_SYSTEMERROR */ +	"RPC: Unknown host",			/* 13 - RPC_UNKNOWNHOST */ +	"RPC: Port mapper failure",		/* 14 - RPC_PMAPFAILURE */ +	"RPC: Program not registered",		/* 15 - RPC_PROGNOTREGISTERED */ +	"RPC: Failed (unspecified error)",	/* 16 - RPC_FAILED */ +	"RPC: Unknown protocol"			/* 17 - RPC_UNKNOWNPROTO */  }; @@ -206,13 +177,11 @@ char *  clnt_sperrno(stat)  	enum clnt_stat stat;  { -	int i; +	unsigned int errnum = stat; + +	if (errnum < (sizeof(rpc_errlist)/sizeof(rpc_errlist[0]))) +		return (char *)rpc_errlist[errnum]; -	for (i = 0; i < sizeof(rpc_errlist)/sizeof(struct rpc_errtab); i++) { -		if (rpc_errlist[i].status == stat) { -			return (rpc_errlist[i].message); -		} -	}  	return ("RPC: (unknown error code)");  } @@ -220,7 +189,7 @@ void  clnt_perrno(num)  	enum clnt_stat num;  { -	(void) fprintf(stderr,"%s",clnt_sperrno(num)); +	(void) fprintf(stderr,"%s\n",clnt_sperrno(num));  } @@ -228,32 +197,29 @@ char *  clnt_spcreateerror(s)  	char *s;  { -	extern int sys_nerr;  	char *str = _buf();  	if (str == 0)  		return(0); -	(void) sprintf(str, "%s: ", s); -	(void) strcat(str, clnt_sperrno(rpc_createerr.cf_stat));  	switch (rpc_createerr.cf_stat) {  	case RPC_PMAPFAILURE: -		(void) strcat(str, " - "); -		(void) strcat(str, +		(void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, +		    clnt_sperrno(rpc_createerr.cf_stat),  		    clnt_sperrno(rpc_createerr.cf_error.re_status));  		break;  	case RPC_SYSTEMERROR: -		(void) strcat(str, " - "); -		if (rpc_createerr.cf_error.re_errno > 0 -		    && rpc_createerr.cf_error.re_errno < sys_nerr) -			(void) strcat(str, -			    strerror(rpc_createerr.cf_error.re_errno)); -		else -			(void) sprintf(&str[strlen(str)], "Error %d", -			    rpc_createerr.cf_error.re_errno); +		(void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s - %s\n", s, +		    clnt_sperrno(rpc_createerr.cf_stat), +		    strerror(rpc_createerr.cf_error.re_errno)); +		break; +	default: +		(void) snprintf(str, CLNT_PERROR_BUFLEN, "%s: %s\n", s, +		clnt_sperrno(rpc_createerr.cf_stat));  		break;  	} -	(void) strcat(str, "\n"); +	str[CLNT_PERROR_BUFLEN-2] = '\n'; +	str[CLNT_PERROR_BUFLEN-1] = '\0';  	return (str);  } @@ -261,43 +227,28 @@ void  clnt_pcreateerror(s)  	char *s;  { -	(void) fprintf(stderr,"%s",clnt_spcreateerror(s)); +	(void) fprintf(stderr,"%s\n",clnt_spcreateerror(s));  } -struct auth_errtab { -	enum auth_stat status;	 -	char *message; -}; - -static struct auth_errtab auth_errlist[] = { -	{ AUTH_OK, -		"Authentication OK" }, -	{ AUTH_BADCRED, -		"Invalid client credential" }, -	{ AUTH_REJECTEDCRED, -		"Server rejected credential" }, -	{ AUTH_BADVERF, -		"Invalid client verifier" }, -	{ AUTH_REJECTEDVERF, -		"Server rejected verifier" }, -	{ AUTH_TOOWEAK, -		"Client credential too weak" }, -	{ AUTH_INVALIDRESP, -		"Invalid server verifier" }, -	{ AUTH_FAILED, -		"Failed (unspecified error)" }, +static const char *const auth_errlist[] = { +	"Authentication OK",			/* 0 - AUTH_OK */ +	"Invalid client credential",		/* 1 - AUTH_BADCRED */ +	"Server rejected credential",		/* 2 - AUTH_REJECTEDCRED */ +	"Invalid client verifier",		/* 3 - AUTH_BADVERF */ +	"Server rejected verifier",		/* 4 - AUTH_REJECTEDVERF */ +	"Client credential too weak",		/* 5 - AUTH_TOOWEAK */ +	"Invalid server verifier",		/* 6 - AUTH_INVALIDRESP */ +	"Failed (unspecified error)"		/* 7 - AUTH_FAILED */  };  static char *  auth_errmsg(stat)  	enum auth_stat stat;  { -	int i; +	unsigned int errnum = stat; + +	if (errnum < (sizeof(auth_errlist)/sizeof(auth_errlist[0]))) +		return (char *)auth_errlist[errnum]; -	for (i = 0; i < sizeof(auth_errlist)/sizeof(struct auth_errtab); i++) { -		if (auth_errlist[i].status == stat) { -			return(auth_errlist[i].message); -		} -	}  	return(NULL);  } diff --git a/lib/libc/rpc/clnt_raw.c b/lib/libc/rpc/clnt_raw.c index 9ee87b225701..c715ef698efa 100644 --- a/lib/libc/rpc/clnt_raw.c +++ b/lib/libc/rpc/clnt_raw.c @@ -5,11 +5,11 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. @@ -17,11 +17,11 @@   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)clnt_raw.c 1.22 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)clnt_raw.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: clnt_raw.c,v 1.1 1993/10/27 05:40:22 paul Exp $"; +static char *rcsid = "$Id: clnt_raw.c,v 1.6 1996/12/30 14:21:36 peter Exp $";  #endif  /* @@ -45,6 +45,8 @@ static char *rcsid = "$Id: clnt_raw.c,v 1.1 1993/10/27 05:40:22 paul Exp $";   */  #include <rpc/rpc.h> +#include <stdlib.h> +#include <stdio.h>  #define MCALL_MSG_SIZE 24 @@ -97,13 +99,13 @@ clntraw_create(prog, vers)  		clntraw_private = clp;  	}  	/* -	 * pre-serialize the staic part of the call msg and stash it away +	 * pre-serialize the static part of the call msg and stash it away  	 */  	call_msg.rm_direction = CALL;  	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;  	call_msg.rm_call.cb_prog = prog;  	call_msg.rm_call.cb_vers = vers; -	xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);  +	xdrmem_create(xdrs, clp->mashl_callmsg, MCALL_MSG_SIZE, XDR_ENCODE);  	if (! xdr_callhdr(xdrs, &call_msg)) {  		perror("clnt_raw.c - Fatal header serialization error.");  	} @@ -123,7 +125,7 @@ clntraw_create(prog, vers)  	return (client);  } -static enum clnt_stat  +static enum clnt_stat  clntraw_call(h, proc, xargs, argsp, xresults, resultsp, timeout)  	CLIENT *h;  	u_long proc; diff --git a/lib/libc/rpc/clnt_simple.c b/lib/libc/rpc/clnt_simple.c index 671e2eb61a93..5bcfd47df3ed 100644 --- a/lib/libc/rpc/clnt_simple.c +++ b/lib/libc/rpc/clnt_simple.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,18 +30,20 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)clnt_simple.c 1.35 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)clnt_simple.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: clnt_simple.c,v 1.1 1993/10/27 05:40:23 paul Exp $"; +static char *rcsid = "$Id: clnt_simple.c,v 1.6 1996/12/30 14:23:50 peter Exp $";  #endif -/*  +/*   * clnt_simple.c   * Simplified front end to rpc.   *   * Copyright (C) 1984, Sun Microsystems, Inc.   */ +#include <sys/param.h>  #include <stdio.h>  #include <stdlib.h> +#include <unistd.h>  #include <string.h>  #include <rpc/rpc.h>  #include <sys/socket.h> @@ -54,8 +56,10 @@ static struct callrpc_private {  	char	*oldhost;  } *callrpc_private; +int  callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)  	char *host; +	int prognum, versnum, procnum;  	xdrproc_t inproc, outproc;  	char *in, *out;  { @@ -72,16 +76,17 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)  		callrpc_private = crp;  	}  	if (crp->oldhost == NULL) { -		crp->oldhost = malloc(256); +		crp->oldhost = malloc(MAXHOSTNAMELEN);  		crp->oldhost[0] = 0;  		crp->socket = RPC_ANYSOCK;  	}  	if (crp->valid && crp->oldprognum == prognum && crp->oldversnum == versnum  		&& strcmp(crp->oldhost, host) == 0) { -		/* reuse old client */		 +		/* reuse old client */  	} else {  		crp->valid = 0; -		(void)close(crp->socket); +		if (crp->socket != -1) +			(void)close(crp->socket);  		crp->socket = RPC_ANYSOCK;  		if (crp->client) {  			clnt_destroy(crp->client); @@ -91,7 +96,9 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)  			return ((int) RPC_UNKNOWNHOST);  		timeout.tv_usec = 0;  		timeout.tv_sec = 5; -		bcopy(hp->h_addr, (char *)&server_addr.sin_addr, hp->h_length); +		memset(&server_addr, 0, sizeof(server_addr)); +		memcpy((char *)&server_addr.sin_addr, hp->h_addr, hp->h_length); +		server_addr.sin_len = sizeof(struct sockaddr_in);  		server_addr.sin_family = AF_INET;  		server_addr.sin_port =  0;  		if ((crp->client = clntudp_create(&server_addr, (u_long)prognum, @@ -106,7 +113,7 @@ callrpc(host, prognum, versnum, procnum, inproc, in, outproc, out)  	tottimeout.tv_usec = 0;  	clnt_stat = clnt_call(crp->client, procnum, inproc, in,  	    outproc, out, tottimeout); -	/*  +	/*  	 * if call failed, empty cache  	 */  	if (clnt_stat != RPC_SUCCESS) diff --git a/lib/libc/rpc/clnt_tcp.c b/lib/libc/rpc/clnt_tcp.c index efc041ab8db3..cfb3746d2897 100644 --- a/lib/libc/rpc/clnt_tcp.c +++ b/lib/libc/rpc/clnt_tcp.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,9 +30,9 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)clnt_tcp.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)clnt_tcp.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: clnt_tcp.c,v 1.1 1993/10/27 05:40:24 paul Exp $"; +static char *rcsid = "$Id: clnt_tcp.c,v 1.7 1996/12/30 14:36:17 peter Exp $";  #endif -  +  /*   * clnt_tcp.c, Implements a TCP/IP based, client side RPC.   * @@ -53,6 +53,9 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.1 1993/10/27 05:40:24 paul Exp $";   */  #include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h>  #include <rpc/rpc.h>  #include <sys/socket.h>  #include <netdb.h> @@ -61,8 +64,6 @@ static char *rcsid = "$Id: clnt_tcp.c,v 1.1 1993/10/27 05:40:24 paul Exp $";  #define MCALL_MSG_SIZE 24 -extern int errno; -  static int	readtcp();  static int	writetcp(); @@ -87,7 +88,7 @@ struct ct_data {  	bool_t		ct_closeit;  	struct timeval	ct_wait;  	bool_t          ct_waitset;       /* wait set by clnt_control? */ -	struct sockaddr_in ct_addr;  +	struct sockaddr_in ct_addr;  	struct rpc_err	ct_error;  	char		ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */  	u_int		ct_mpos;			/* pos after marshal */ @@ -118,9 +119,13 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)  	u_int recvsz;  {  	CLIENT *h; -	register struct ct_data *ct; +	register struct ct_data *ct = NULL;  	struct timeval now;  	struct rpc_msg call_msg; +	static u_int32_t disrupt; + +	if (disrupt == 0) +		disrupt = (u_int32_t)(long)raddr;  	h  = (CLIENT *)mem_alloc(sizeof(*h));  	if (h == NULL) { @@ -161,7 +166,8 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)  		    sizeof(*raddr)) < 0)) {  			rpc_createerr.cf_stat = RPC_SYSTEMERROR;  			rpc_createerr.cf_error.re_errno = errno; -			(void)close(*sockp); +			if (*sockp != -1) +				(void)close(*sockp);  			goto fooy;  		}  		ct->ct_closeit = TRUE; @@ -181,14 +187,14 @@ clnttcp_create(raddr, prog, vers, sockp, sendsz, recvsz)  	 * Initialize call message  	 */  	(void)gettimeofday(&now, (struct timezone *)0); -	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; +	call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;  	call_msg.rm_direction = CALL;  	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;  	call_msg.rm_call.cb_prog = prog;  	call_msg.rm_call.cb_vers = vers;  	/* -	 * pre-serialize the staic part of the call msg and stash it away +	 * pre-serialize the static part of the call msg and stash it away  	 */  	xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE,  	    XDR_ENCODE); @@ -216,8 +222,10 @@ fooy:  	/*  	 * Something goofed, free stuff and barf  	 */ -	mem_free((caddr_t)ct, sizeof(struct ct_data)); -	mem_free((caddr_t)h, sizeof(CLIENT)); +	if (ct) +		mem_free((caddr_t)ct, sizeof(struct ct_data)); +	if (h) +		mem_free((caddr_t)h, sizeof(CLIENT));  	return ((CLIENT *)NULL);  } @@ -235,7 +243,7 @@ clnttcp_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout)  	register XDR *xdrs = &(ct->ct_xdrs);  	struct rpc_msg reply_msg;  	u_long x_id; -	u_long *msg_x_id = (u_long *)(ct->ct_mcall);	/* yuk */ +	u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall);	/* yuk */  	register bool_t shipnow;  	int refreshes = 2; @@ -347,6 +355,7 @@ clnttcp_abort()  {  } +  static bool_t  clnttcp_control(cl, request, info)  	CLIENT *cl; @@ -354,18 +363,102 @@ clnttcp_control(cl, request, info)  	char *info;  {  	register struct ct_data *ct = (struct ct_data *)cl->cl_private; +	register struct timeval *tv; +	int len;  	switch (request) { +	case CLSET_FD_CLOSE: +		ct->ct_closeit = TRUE; +		break; +	case CLSET_FD_NCLOSE: +		ct->ct_closeit = FALSE; +		break;  	case CLSET_TIMEOUT: -		ct->ct_wait = *(struct timeval *)info; +		if (info == NULL) +			return(FALSE); +		tv = (struct timeval *)info; +		ct->ct_wait.tv_sec = tv->tv_sec; +		ct->ct_wait.tv_usec = tv->tv_usec;  		ct->ct_waitset = TRUE;  		break;  	case CLGET_TIMEOUT: +		if (info == NULL) +			return(FALSE);  		*(struct timeval *)info = ct->ct_wait;  		break;  	case CLGET_SERVER_ADDR: +		if (info == NULL) +			return(FALSE);  		*(struct sockaddr_in *)info = ct->ct_addr;  		break; +	case CLGET_FD: +		if (info == NULL) +			return(FALSE); +		*(int *)info = ct->ct_sock; +		break; +	case CLGET_XID: +		/* +		 * use the knowledge that xid is the +		 * first element in the call structure *. +		 * This will get the xid of the PREVIOUS call +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)ct->ct_mcall); +		break; +	case CLSET_XID: +		/* This will set the xid of the NEXT call */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)ct->ct_mcall =  htonl(*(u_long *)info - 1); +		/* decrement by 1 as clnttcp_call() increments once */ +	case CLGET_VERS: +		/* +		 * This RELIES on the information that, in the call body, +		 * the version number field is the fifth field from the +		 * begining of the RPC header. MUST be changed if the +		 * call_struct is changed +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + +						4 * BYTES_PER_XDR_UNIT)); +		break; +	case CLSET_VERS: +		if (info == NULL) +			return(FALSE); +		*(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) +				= htonl(*(u_long *)info); +		break; +	case CLGET_PROG: +		/* +		 * This RELIES on the information that, in the call body, +		 * the program number field is the  field from the +		 * begining of the RPC header. MUST be changed if the +		 * call_struct is changed +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + +						3 * BYTES_PER_XDR_UNIT)); +		break; +	case CLSET_PROG: +		if (info == NULL) +			return(FALSE); +		*(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) +				= htonl(*(u_long *)info); +		break; +	case CLGET_LOCAL_ADDR: +		len = sizeof(struct sockaddr); +		if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0) +			return(FALSE); +		break; +	case CLGET_RETRY_TIMEOUT: +	case CLSET_RETRY_TIMEOUT: +	case CLGET_SVC_ADDR: +	case CLSET_SVC_ADDR: +	case CLSET_PUSH_TIMOD: +	case CLSET_POP_TIMOD:  	default:  		return (FALSE);  	} @@ -399,35 +492,54 @@ readtcp(ct, buf, len)  	caddr_t buf;  	register int len;  { -#ifdef FD_SETSIZE -	fd_set mask; -	fd_set readfds; +	fd_set *fds, readfds; +	struct timeval start, after, duration, delta, tmp, tv; +	int r, save_errno;  	if (len == 0)  		return (0); -	FD_ZERO(&mask); -	FD_SET(ct->ct_sock, &mask); -#else -	register int mask = 1 << (ct->ct_sock); -	int readfds; -	if (len == 0) -		return (0); +	if (ct->ct_sock + 1 > FD_SETSIZE) { +		int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask); +		fds = (fd_set *)malloc(bytes); +		if (fds == NULL) +			return (-1); +		memset(fds, 0, bytes); +	} else { +		fds = &readfds; +		FD_ZERO(fds); +	} -#endif /* def FD_SETSIZE */ +	gettimeofday(&start, NULL); +	delta = ct->ct_wait;  	while (TRUE) { -		readfds = mask; -		switch (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL, -			       &(ct->ct_wait))) { +		/* XXX we know the other bits are still clear */ +		FD_SET(ct->ct_sock, fds); +		tv = delta;	/* in case select writes back */ +		r = select(ct->ct_sock+1, fds, NULL, NULL, &tv); +		save_errno = errno; + +		gettimeofday(&after, NULL); +		timersub(&start, &after, &duration); +		timersub(&delta, &duration, &tmp); +		delta = tmp; +		if (delta.tv_sec < 0 || !timerisset(&delta)) +			r = 0; + +		switch (r) {  		case 0: +			if (fds != &readfds) +				free(fds);  			ct->ct_error.re_status = RPC_TIMEDOUT;  			return (-1);  		case -1:  			if (errno == EINTR)  				continue; +			if (fds != &readfds) +				free(fds);  			ct->ct_error.re_status = RPC_CANTRECV; -			ct->ct_error.re_errno = errno; +			ct->ct_error.re_errno = save_errno;  			return (-1);  		}  		break; diff --git a/lib/libc/rpc/clnt_udp.c b/lib/libc/rpc/clnt_udp.c index 4df4631079a7..035ce96fd4af 100644 --- a/lib/libc/rpc/clnt_udp.c +++ b/lib/libc/rpc/clnt_udp.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)clnt_udp.c 1.39 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)clnt_udp.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: clnt_udp.c,v 1.1 1993/10/27 05:40:25 paul Exp $"; +static char *rcsid = "$Id: clnt_udp.c,v 1.8 1996/12/30 14:40:34 peter Exp $";  #endif  /* @@ -40,6 +40,9 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.1 1993/10/27 05:40:25 paul Exp $";   */  #include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h>  #include <rpc/rpc.h>  #include <sys/socket.h>  #include <sys/ioctl.h> @@ -47,8 +50,6 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.1 1993/10/27 05:40:25 paul Exp $";  #include <errno.h>  #include <rpc/pmap_clnt.h> -extern int errno; -  /*   * UDP bases client side rpc operations   */ @@ -68,7 +69,7 @@ static struct clnt_ops udp_ops = {  	clntudp_control  }; -/*  +/*   * Private data kept per client handle   */  struct cu_data { @@ -114,9 +115,13 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)  	u_int recvsz;  {  	CLIENT *cl; -	register struct cu_data *cu; +	register struct cu_data *cu = NULL;  	struct timeval now;  	struct rpc_msg call_msg; +	static u_int32_t disrupt; + +	if (disrupt == 0) +		disrupt = (u_int32_t)(long)raddr;  	cl = (CLIENT *)mem_alloc(sizeof(CLIENT));  	if (cl == NULL) { @@ -154,7 +159,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)  	cu->cu_total.tv_usec = -1;  	cu->cu_sendsz = sendsz;  	cu->cu_recvsz = recvsz; -	call_msg.rm_xid = getpid() ^ now.tv_sec ^ now.tv_usec; +	call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec;  	call_msg.rm_direction = CALL;  	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION;  	call_msg.rm_call.cb_prog = program; @@ -174,7 +179,7 @@ clntudp_bufcreate(raddr, program, version, wait, sockp, sendsz, recvsz)  			rpc_createerr.cf_error.re_errno = errno;  			goto fooy;  		} -		/* attempt to bind to prov port */ +		/* attempt to bind to priv port */  		(void)bindresvport(*sockp, (struct sockaddr_in *)0);  		/* the sockets rpc controls are non-blocking */  		(void)ioctl(*sockp, FIONBIO, (char *) &dontblock); @@ -206,7 +211,7 @@ clntudp_create(raddr, program, version, wait, sockp)  	    UDPMSGSIZE, UDPMSGSIZE));  } -static enum clnt_stat  +static enum clnt_stat  clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)  	register CLIENT	*cl;		/* client handle */  	u_long		proc;		/* procedure number */ @@ -221,29 +226,33 @@ clntudp_call(cl, proc, xargs, argsp, xresults, resultsp, utimeout)  	register int outlen;  	register int inlen;  	int fromlen; -#ifdef FD_SETSIZE -	fd_set readfds; -	fd_set mask; -#else -	int readfds; -	register int mask; -#endif /* def FD_SETSIZE */ +	fd_set *fds, readfds;  	struct sockaddr_in from;  	struct rpc_msg reply_msg;  	XDR reply_xdrs; -	struct timeval time_waited; +	struct timeval time_waited, start, after, tmp1, tmp2, tv;  	bool_t ok;  	int nrefreshes = 2;	/* number of times to refresh cred */  	struct timeval timeout; -	if (cu->cu_total.tv_usec == -1) { +	if (cu->cu_total.tv_usec == -1)  		timeout = utimeout;     /* use supplied timeout */ -	} else { +	else  		timeout = cu->cu_total; /* use default timeout */ + +	if (cu->cu_sock + 1 > FD_SETSIZE) { +		int bytes = howmany(cu->cu_sock + 1, NFDBITS) * sizeof(fd_mask); +		fds = (fd_set *)malloc(bytes); +		if (fds == NULL) +			return (cu->cu_error.re_status = RPC_CANTSEND); +		memset(fds, 0, bytes); +	} else { +		fds = &readfds; +		FD_ZERO(fds);  	} -	time_waited.tv_sec = 0; -	time_waited.tv_usec = 0; +	timerclear(&time_waited); +  call_again:  	xdrs = &(cu->cu_outxdrs);  	xdrs->x_op = XDR_ENCODE; @@ -254,22 +263,28 @@ call_again:  	(*(u_short *)(cu->cu_outbuf))++;  	if ((! XDR_PUTLONG(xdrs, (long *)&proc)) ||  	    (! AUTH_MARSHALL(cl->cl_auth, xdrs)) || -	    (! (*xargs)(xdrs, argsp))) +	    (! (*xargs)(xdrs, argsp))) { +		if (fds != &readfds) +			free(fds);  		return (cu->cu_error.re_status = RPC_CANTENCODEARGS); +	}  	outlen = (int)XDR_GETPOS(xdrs);  send_again:  	if (sendto(cu->cu_sock, cu->cu_outbuf, outlen, 0, -	    (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) -	    != outlen) { +	    (struct sockaddr *)&(cu->cu_raddr), cu->cu_rlen) != outlen) {  		cu->cu_error.re_errno = errno; +		if (fds != &readfds) +			free(fds);  		return (cu->cu_error.re_status = RPC_CANTSEND);  	}  	/*  	 * Hack to provide rpc-based message passing  	 */ -	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { +	if (!timerisset(&timeout)) { +		if (fds != &readfds) +			free(fds);  		return (cu->cu_error.re_status = RPC_TIMEDOUT);  	}  	/* @@ -280,57 +295,60 @@ send_again:  	reply_msg.acpted_rply.ar_verf = _null_auth;  	reply_msg.acpted_rply.ar_results.where = resultsp;  	reply_msg.acpted_rply.ar_results.proc = xresults; -#ifdef FD_SETSIZE -	FD_ZERO(&mask); -	FD_SET(cu->cu_sock, &mask); -#else -	mask = 1 << cu->cu_sock; -#endif /* def FD_SETSIZE */ + +	gettimeofday(&start, NULL);  	for (;;) { -		readfds = mask; -		switch (select(_rpc_dtablesize(), &readfds, (int *)NULL,  -			       (int *)NULL, &(cu->cu_wait))) { +		/* XXX we know the other bits are still clear */ +		FD_SET(cu->cu_sock, fds); +		tv = cu->cu_wait; +		switch (select(cu->cu_sock+1, fds, NULL, NULL, &tv)) {  		case 0: -			time_waited.tv_sec += cu->cu_wait.tv_sec; -			time_waited.tv_usec += cu->cu_wait.tv_usec; -			while (time_waited.tv_usec >= 1000000) { -				time_waited.tv_sec++; -				time_waited.tv_usec -= 1000000; -			} -			if ((time_waited.tv_sec < timeout.tv_sec) || -				((time_waited.tv_sec == timeout.tv_sec) && -				(time_waited.tv_usec < timeout.tv_usec))) -				goto send_again;	 +			timeradd(&time_waited, &cu->cu_wait, &tmp1); +			time_waited = tmp1; +			if (timercmp(&time_waited, &timeout, <)) +				goto send_again; +			if (fds != &readfds) +				free(fds);  			return (cu->cu_error.re_status = RPC_TIMEDOUT); -		/* -		 * buggy in other cases because time_waited is not being -		 * updated. -		 */  		case -1: -			if (errno == EINTR) -				continue;	 +			if (errno == EINTR) { +				gettimeofday(&after, NULL); +				timersub(&after, &start, &tmp1); +				timeradd(&time_waited, &tmp1, &tmp2); +				time_waited = tmp2; +				if (timercmp(&time_waited, &timeout, <)) +					continue; +				if (fds != &readfds) +					free(fds); +				return (cu->cu_error.re_status = RPC_TIMEDOUT); +			}  			cu->cu_error.re_errno = errno; +			if (fds != &readfds) +				free(fds);  			return (cu->cu_error.re_status = RPC_CANTRECV);  		} +  		do {  			fromlen = sizeof(struct sockaddr); -			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,  +			inlen = recvfrom(cu->cu_sock, cu->cu_inbuf,  				(int) cu->cu_recvsz, 0,  				(struct sockaddr *)&from, &fromlen);  		} while (inlen < 0 && errno == EINTR);  		if (inlen < 0) {  			if (errno == EWOULDBLOCK) -				continue;	 +				continue;  			cu->cu_error.re_errno = errno; +			if (fds != &readfds) +				free(fds);  			return (cu->cu_error.re_status = RPC_CANTRECV);  		} -		if (inlen < sizeof(u_long)) -			continue;	 +		if (inlen < sizeof(u_int32_t)) +			continue;  		/* see if reply transaction id matches sent id */ -		if (*((u_long *)(cu->cu_inbuf)) != *((u_long *)(cu->cu_outbuf))) -			continue;	 +		if (*((u_int32_t *)(cu->cu_inbuf)) != *((u_int32_t *)(cu->cu_outbuf))) +			continue;  		/* we now assume we have the proper reply */  		break;  	} @@ -353,7 +371,7 @@ send_again:  				xdrs->x_op = XDR_FREE;  				(void)xdr_opaque_auth(xdrs,  				    &(reply_msg.acpted_rply.ar_verf)); -			}  +			}  		}  /* end successful completion */  		else {  			/* maybe our credentials need to be refreshed ... */ @@ -366,6 +384,8 @@ send_again:  	else {  		cu->cu_error.re_status = RPC_CANTDECODERES;  	} +	if (fds != &readfds) +		free(fds);  	return (cu->cu_error.re_status);  } @@ -393,12 +413,13 @@ clntudp_freeres(cl, xdr_res, res_ptr)  	return ((*xdr_res)(xdrs, res_ptr));  } -static void  +static void  clntudp_abort(/*h*/)  	/*CLIENT *h;*/  {  } +  static bool_t  clntudp_control(cl, request, info)  	CLIENT *cl; @@ -406,29 +427,117 @@ clntudp_control(cl, request, info)  	char *info;  {  	register struct cu_data *cu = (struct cu_data *)cl->cl_private; +	register struct timeval *tv; +	int len;  	switch (request) { +	case CLSET_FD_CLOSE: +		cu->cu_closeit = TRUE; +		break; +	case CLSET_FD_NCLOSE: +		cu->cu_closeit = FALSE; +		break;  	case CLSET_TIMEOUT: -		cu->cu_total = *(struct timeval *)info; +		if (info == NULL) +			return(FALSE); +		tv = (struct timeval *)info; +		cu->cu_total.tv_sec = tv->tv_sec; +		cu->cu_total.tv_usec = tv->tv_usec;  		break;  	case CLGET_TIMEOUT: +		if (info == NULL) +			return(FALSE);  		*(struct timeval *)info = cu->cu_total;  		break;  	case CLSET_RETRY_TIMEOUT: -		cu->cu_wait = *(struct timeval *)info; +		if (info == NULL) +			return(FALSE); +		tv = (struct timeval *)info; +		cu->cu_wait.tv_sec = tv->tv_sec; +		cu->cu_wait.tv_usec = tv->tv_usec;  		break;  	case CLGET_RETRY_TIMEOUT: +		if (info == NULL) +			return(FALSE);  		*(struct timeval *)info = cu->cu_wait;  		break;  	case CLGET_SERVER_ADDR: +		if (info == NULL) +			return(FALSE);  		*(struct sockaddr_in *)info = cu->cu_raddr;  		break; +	case CLGET_FD: +		if (info == NULL) +			return(FALSE); +		*(int *)info = cu->cu_sock; +		break; +	case CLGET_XID: +		/* +		 * use the knowledge that xid is the +		 * first element in the call structure *. +		 * This will get the xid of the PREVIOUS call +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)cu->cu_outbuf); +		break; +	case CLSET_XID: +		/* This will set the xid of the NEXT call */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)cu->cu_outbuf =  htonl(*(u_long *)info - 1); +		/* decrement by 1 as clntudp_call() increments once */ +	case CLGET_VERS: +		/* +		 * This RELIES on the information that, in the call body, +		 * the version number field is the fifth field from the +		 * begining of the RPC header. MUST be changed if the +		 * call_struct is changed +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + +						4 * BYTES_PER_XDR_UNIT)); +		break; +	case CLSET_VERS: +		if (info == NULL) +			return(FALSE); +		*(u_long *)(cu->cu_outbuf + 4 * BYTES_PER_XDR_UNIT) +				= htonl(*(u_long *)info); +		break; +	case CLGET_PROG: +		/* +		 * This RELIES on the information that, in the call body, +		 * the program number field is the  field from the +		 * begining of the RPC header. MUST be changed if the +		 * call_struct is changed +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)(cu->cu_outbuf + +						3 * BYTES_PER_XDR_UNIT)); +		break; +	case CLSET_PROG: +		if (info == NULL) +			return(FALSE); +		*(u_long *)(cu->cu_outbuf + 3 * BYTES_PER_XDR_UNIT) +				= htonl(*(u_long *)info); +		break; +	case CLGET_LOCAL_ADDR: +		len = sizeof(struct sockaddr); +		if (getsockname(cu->cu_sock, (struct sockaddr *)info, &len) <0) +			return(FALSE); +		break; +	case CLGET_SVC_ADDR: +	case CLSET_SVC_ADDR: +	case CLSET_PUSH_TIMOD: +	case CLSET_POP_TIMOD:  	default:  		return (FALSE);  	}  	return (TRUE);  } -	 +  static void  clntudp_destroy(cl)  	CLIENT *cl; diff --git a/lib/libc/rpc/clnt_unix.c b/lib/libc/rpc/clnt_unix.c new file mode 100644 index 000000000000..e4c43094bc9c --- /dev/null +++ b/lib/libc/rpc/clnt_unix.c @@ -0,0 +1,635 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)clnt_unix.c 1.37 87/10/05 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)clnt_unix.c	2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$Id: clnt_unix.c,v 1.7 1996/12/30 14:36:17 peter Exp $"; +#endif + +/* + * clnt_unix.c, Implements a AF_UNIX based, client side RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * AF_UNIX based RPC supports 'batched calls'. + * A sequence of calls may be batched-up in a send buffer.  The rpc call + * return immediately to the client even though the call was not necessarily + * sent.  The batching occurs if the results' xdr routine is NULL (0) AND + * the rpc timeout value is zero (see clnt.h, rpc). + * + * Clients should NOT casually batch calls that in fact return results; that is, + * the server side should be aware that a call is batched and not produce any + * return message.  Batched calls that produce many result messages can + * deadlock (netlock) the client and the server.... + * + * Now go hang yourself. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <sys/uio.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <netdb.h> +#include <errno.h> +#include <rpc/pmap_clnt.h> + +#define MCALL_MSG_SIZE 24 + +static int	readunix(); +static int	writeunix(); + +static enum clnt_stat	clntunix_call(); +static void		clntunix_abort(); +static void		clntunix_geterr(); +static bool_t		clntunix_freeres(); +static bool_t           clntunix_control(); +static void		clntunix_destroy(); + +static struct clnt_ops unix_ops = { +	clntunix_call, +	clntunix_abort, +	clntunix_geterr, +	clntunix_freeres, +	clntunix_destroy, +	clntunix_control +}; + +struct ct_data { +	int		ct_sock; +	bool_t		ct_closeit; +	struct timeval	ct_wait; +	bool_t          ct_waitset;       /* wait set by clnt_control? */ +	struct sockaddr_un ct_addr; +	struct rpc_err	ct_error; +	char		ct_mcall[MCALL_MSG_SIZE];	/* marshalled callmsg */ +	u_int		ct_mpos;			/* pos after marshal */ +	XDR		ct_xdrs; +}; + +/* + * Create a client handle for a unix/ip connection. + * If *sockp<0, *sockp is set to a newly created TCP socket and it is + * connected to raddr.  If *sockp non-negative then + * raddr is ignored.  The rpc/unix package does buffering + * similar to stdio, so the client must pick send and receive buffer sizes,]; + * 0 => use the default. + * If raddr->sin_port is 0, then a binder on the remote machine is + * consulted for the right port number. + * NB: *sockp is copied into a private area. + * NB: It is the clients responsibility to close *sockp. + * NB: The rpch->cl_auth is set null authentication.  Caller may wish to set this + * something more useful. + */ +CLIENT * +clntunix_create(raddr, prog, vers, sockp, sendsz, recvsz) +	struct sockaddr_un *raddr; +	u_long prog; +	u_long vers; +	register int *sockp; +	u_int sendsz; +	u_int recvsz; +{ +	CLIENT *h; +	register struct ct_data *ct = NULL; +	struct timeval now; +	struct rpc_msg call_msg; +	static u_int32_t disrupt; +	int len; + +	if (disrupt == 0) +		disrupt = (u_int32_t)(long)raddr; + +	h  = (CLIENT *)mem_alloc(sizeof(*h)); +	if (h == NULL) { +		(void)fprintf(stderr, "clntunix_create: out of memory\n"); +		rpc_createerr.cf_stat = RPC_SYSTEMERROR; +		rpc_createerr.cf_error.re_errno = errno; +		goto fooy; +	} +	ct = (struct ct_data *)mem_alloc(sizeof(*ct)); +	if (ct == NULL) { +		(void)fprintf(stderr, "clntunix_create: out of memory\n"); +		rpc_createerr.cf_stat = RPC_SYSTEMERROR; +		rpc_createerr.cf_error.re_errno = errno; +		goto fooy; +	} + +	/* +	 * If no socket given, open one +	 */ +	if (*sockp < 0) { +		*sockp = socket(AF_UNIX, SOCK_STREAM, 0); +		len = strlen(raddr->sun_path) + sizeof(raddr->sun_family) + +			sizeof(raddr->sun_len) + 1; +		raddr->sun_len = len; +		if ((*sockp < 0) +		    || (connect(*sockp, (struct sockaddr *)raddr, len) < 0)) { +			rpc_createerr.cf_stat = RPC_SYSTEMERROR; +			rpc_createerr.cf_error.re_errno = errno; +			if (*sockp != -1) +				(void)close(*sockp); +			goto fooy; +		} +		ct->ct_closeit = TRUE; +	} else { +		ct->ct_closeit = FALSE; +	} + +	/* +	 * Set up private data struct +	 */ +	ct->ct_sock = *sockp; +	ct->ct_wait.tv_usec = 0; +	ct->ct_waitset = FALSE; +	ct->ct_addr = *raddr; + +	/* +	 * Initialize call message +	 */ +	(void)gettimeofday(&now, (struct timezone *)0); +	call_msg.rm_xid = (++disrupt) ^ getpid() ^ now.tv_sec ^ now.tv_usec; +	call_msg.rm_direction = CALL; +	call_msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; +	call_msg.rm_call.cb_prog = prog; +	call_msg.rm_call.cb_vers = vers; + +	/* +	 * pre-serialize the static part of the call msg and stash it away +	 */ +	xdrmem_create(&(ct->ct_xdrs), ct->ct_mcall, MCALL_MSG_SIZE, +	    XDR_ENCODE); +	if (! xdr_callhdr(&(ct->ct_xdrs), &call_msg)) { +		if (ct->ct_closeit) { +			(void)close(*sockp); +		} +		goto fooy; +	} +	ct->ct_mpos = XDR_GETPOS(&(ct->ct_xdrs)); +	XDR_DESTROY(&(ct->ct_xdrs)); + +	/* +	 * Create a client handle which uses xdrrec for serialization +	 * and authnone for authentication. +	 */ +	xdrrec_create(&(ct->ct_xdrs), sendsz, recvsz, +	    (caddr_t)ct, readunix, writeunix); +	h->cl_ops = &unix_ops; +	h->cl_private = (caddr_t) ct; +	h->cl_auth = authnone_create(); +	return (h); + +fooy: +	/* +	 * Something goofed, free stuff and barf +	 */ +	if (ct) +		mem_free((caddr_t)ct, sizeof(struct ct_data)); +	if (h) +		mem_free((caddr_t)h, sizeof(CLIENT)); +	return ((CLIENT *)NULL); +} + +static enum clnt_stat +clntunix_call(h, proc, xdr_args, args_ptr, xdr_results, results_ptr, timeout) +	register CLIENT *h; +	u_long proc; +	xdrproc_t xdr_args; +	caddr_t args_ptr; +	xdrproc_t xdr_results; +	caddr_t results_ptr; +	struct timeval timeout; +{ +	register struct ct_data *ct = (struct ct_data *) h->cl_private; +	register XDR *xdrs = &(ct->ct_xdrs); +	struct rpc_msg reply_msg; +	u_long x_id; +	u_int32_t *msg_x_id = (u_int32_t *)(ct->ct_mcall);	/* yuk */ +	register bool_t shipnow; +	int refreshes = 2; + +	if (!ct->ct_waitset) { +		ct->ct_wait = timeout; +	} + +	shipnow = +	    (xdr_results == (xdrproc_t)0 && timeout.tv_sec == 0 +	    && timeout.tv_usec == 0) ? FALSE : TRUE; + +call_again: +	xdrs->x_op = XDR_ENCODE; +	ct->ct_error.re_status = RPC_SUCCESS; +	x_id = ntohl(--(*msg_x_id)); +	if ((! XDR_PUTBYTES(xdrs, ct->ct_mcall, ct->ct_mpos)) || +	    (! XDR_PUTLONG(xdrs, (long *)&proc)) || +	    (! AUTH_MARSHALL(h->cl_auth, xdrs)) || +	    (! (*xdr_args)(xdrs, args_ptr))) { +		if (ct->ct_error.re_status == RPC_SUCCESS) +			ct->ct_error.re_status = RPC_CANTENCODEARGS; +		(void)xdrrec_endofrecord(xdrs, TRUE); +		return (ct->ct_error.re_status); +	} +	if (! xdrrec_endofrecord(xdrs, shipnow)) +		return (ct->ct_error.re_status = RPC_CANTSEND); +	if (! shipnow) +		return (RPC_SUCCESS); +	/* +	 * Hack to provide rpc-based message passing +	 */ +	if (timeout.tv_sec == 0 && timeout.tv_usec == 0) { +		return(ct->ct_error.re_status = RPC_TIMEDOUT); +	} + + +	/* +	 * Keep receiving until we get a valid transaction id +	 */ +	xdrs->x_op = XDR_DECODE; +	while (TRUE) { +		reply_msg.acpted_rply.ar_verf = _null_auth; +		reply_msg.acpted_rply.ar_results.where = NULL; +		reply_msg.acpted_rply.ar_results.proc = xdr_void; +		if (! xdrrec_skiprecord(xdrs)) +			return (ct->ct_error.re_status); +		/* now decode and validate the response header */ +		if (! xdr_replymsg(xdrs, &reply_msg)) { +			if (ct->ct_error.re_status == RPC_SUCCESS) +				continue; +			return (ct->ct_error.re_status); +		} +		if (reply_msg.rm_xid == x_id) +			break; +	} + +	/* +	 * process header +	 */ +	_seterr_reply(&reply_msg, &(ct->ct_error)); +	if (ct->ct_error.re_status == RPC_SUCCESS) { +		if (! AUTH_VALIDATE(h->cl_auth, &reply_msg.acpted_rply.ar_verf)) { +			ct->ct_error.re_status = RPC_AUTHERROR; +			ct->ct_error.re_why = AUTH_INVALIDRESP; +		} else if (! (*xdr_results)(xdrs, results_ptr)) { +			if (ct->ct_error.re_status == RPC_SUCCESS) +				ct->ct_error.re_status = RPC_CANTDECODERES; +		} +		/* free verifier ... */ +		if (reply_msg.acpted_rply.ar_verf.oa_base != NULL) { +			xdrs->x_op = XDR_FREE; +			(void)xdr_opaque_auth(xdrs, &(reply_msg.acpted_rply.ar_verf)); +		} +	}  /* end successful completion */ +	else { +		/* maybe our credentials need to be refreshed ... */ +		if (refreshes-- && AUTH_REFRESH(h->cl_auth)) +			goto call_again; +	}  /* end of unsuccessful completion */ +	return (ct->ct_error.re_status); +} + +static void +clntunix_geterr(h, errp) +	CLIENT *h; +	struct rpc_err *errp; +{ +	register struct ct_data *ct = +	    (struct ct_data *) h->cl_private; + +	*errp = ct->ct_error; +} + +static bool_t +clntunix_freeres(cl, xdr_res, res_ptr) +	CLIENT *cl; +	xdrproc_t xdr_res; +	caddr_t res_ptr; +{ +	register struct ct_data *ct = (struct ct_data *)cl->cl_private; +	register XDR *xdrs = &(ct->ct_xdrs); + +	xdrs->x_op = XDR_FREE; +	return ((*xdr_res)(xdrs, res_ptr)); +} + +static void +clntunix_abort() +{ +} + + +static bool_t +clntunix_control(cl, request, info) +	CLIENT *cl; +	int request; +	char *info; +{ +	register struct ct_data *ct = (struct ct_data *)cl->cl_private; +	register struct timeval *tv; +	int len; + +	switch (request) { +	case CLSET_FD_CLOSE: +		ct->ct_closeit = TRUE; +		break; +	case CLSET_FD_NCLOSE: +		ct->ct_closeit = FALSE; +		break; +	case CLSET_TIMEOUT: +		if (info == NULL) +			return(FALSE); +		tv = (struct timeval *)info; +		ct->ct_wait.tv_sec = tv->tv_sec; +		ct->ct_wait.tv_usec = tv->tv_usec; +		ct->ct_waitset = TRUE; +		break; +	case CLGET_TIMEOUT: +		if (info == NULL) +			return(FALSE); +		*(struct timeval *)info = ct->ct_wait; +		break; +	case CLGET_SERVER_ADDR: +		if (info == NULL) +			return(FALSE); +		*(struct sockaddr_un *)info = ct->ct_addr; +		break; +	case CLGET_FD: +		if (info == NULL) +			return(FALSE); +		*(int *)info = ct->ct_sock; +		break; +	case CLGET_XID: +		/* +		 * use the knowledge that xid is the +		 * first element in the call structure *. +		 * This will get the xid of the PREVIOUS call +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)ct->ct_mcall); +		break; +	case CLSET_XID: +		/* This will set the xid of the NEXT call */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)ct->ct_mcall =  htonl(*(u_long *)info - 1); +		/* decrement by 1 as clntunix_call() increments once */ +	case CLGET_VERS: +		/* +		 * This RELIES on the information that, in the call body, +		 * the version number field is the fifth field from the +		 * begining of the RPC header. MUST be changed if the +		 * call_struct is changed +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + +						4 * BYTES_PER_XDR_UNIT)); +		break; +	case CLSET_VERS: +		if (info == NULL) +			return(FALSE); +		*(u_long *)(ct->ct_mcall + 4 * BYTES_PER_XDR_UNIT) +				= htonl(*(u_long *)info); +		break; +	case CLGET_PROG: +		/* +		 * This RELIES on the information that, in the call body, +		 * the program number field is the  field from the +		 * begining of the RPC header. MUST be changed if the +		 * call_struct is changed +		 */ +		if (info == NULL) +			return(FALSE); +		*(u_long *)info = ntohl(*(u_long *)(ct->ct_mcall + +						3 * BYTES_PER_XDR_UNIT)); +		break; +	case CLSET_PROG: +		if (info == NULL) +			return(FALSE); +		*(u_long *)(ct->ct_mcall + 3 * BYTES_PER_XDR_UNIT) +				= htonl(*(u_long *)info); +		break; +	case CLGET_LOCAL_ADDR: +		len = sizeof(struct sockaddr); +		if (getsockname(ct->ct_sock, (struct sockaddr *)info, &len) <0) +			return(FALSE); +		break; +	case CLGET_RETRY_TIMEOUT: +	case CLSET_RETRY_TIMEOUT: +	case CLGET_SVC_ADDR: +	case CLSET_SVC_ADDR: +	case CLSET_PUSH_TIMOD: +	case CLSET_POP_TIMOD: +	default: +		return (FALSE); +	} +	return (TRUE); +} + + +static void +clntunix_destroy(h) +	CLIENT *h; +{ +	register struct ct_data *ct = +	    (struct ct_data *) h->cl_private; + +	if (ct->ct_closeit) { +		(void)close(ct->ct_sock); +	} +	XDR_DESTROY(&(ct->ct_xdrs)); +	mem_free((caddr_t)ct, sizeof(struct ct_data)); +	mem_free((caddr_t)h, sizeof(CLIENT)); +} + +/* + * read() and write() are replaced with recvmsg()/sendmsg() so that + * we can pass ancillary control data. In this case, the data constists + * of credential information which the kernel will fill in for us. + * XXX: This code is specific to FreeBSD and will not work on other + * platforms without the requisite kernel modifications. + */ +struct cmessage { +	struct cmsghdr cmsg; +	struct cmsgcred cmcred; +}; + +static int __msgread(sock, buf, cnt) +	int sock; +	void *buf; +	size_t cnt; +{ +	struct iovec iov[1]; +	struct msghdr msg; +	struct cmessage cm; + +	bzero((char *)&cm, sizeof(cm)); +	iov[0].iov_base = buf; +	iov[0].iov_len = cnt; + +	msg.msg_iov = iov; +	msg.msg_iovlen = 1; +	msg.msg_name = NULL; +	msg.msg_namelen = 0; +	msg.msg_control = (caddr_t)&cm; +	msg.msg_controllen = sizeof(struct cmessage); +	msg.msg_flags = 0; + +	return(recvmsg(sock, &msg, 0)); +} + +static int __msgwrite(sock, buf, cnt) +	int sock; +	void *buf; +	size_t cnt; +{ +	struct iovec iov[1]; +	struct msghdr msg; +	struct cmessage cm; + +	bzero((char *)&cm, sizeof(cm)); +	iov[0].iov_base = buf; +	iov[0].iov_len = cnt; + +	cm.cmsg.cmsg_type = SCM_CREDS; +	cm.cmsg.cmsg_level = SOL_SOCKET; +	cm.cmsg.cmsg_len = sizeof(struct cmessage); + +	msg.msg_iov = iov; +	msg.msg_iovlen = 1; +	msg.msg_name = NULL; +	msg.msg_namelen = 0; +	msg.msg_control = (caddr_t)&cm; +	msg.msg_controllen = sizeof(struct cmessage); +	msg.msg_flags = 0; + +	return(sendmsg(sock, &msg, 0)); +} + +/* + * Interface between xdr serializer and unix connection. + * Behaves like the system calls, read & write, but keeps some error state + * around for the rpc level. + */ +static int +readunix(ct, buf, len) +	register struct ct_data *ct; +	caddr_t buf; +	register int len; +{ +	fd_set *fds, readfds; +	struct timeval start, after, duration, delta, tmp, tv; +	int r, save_errno; + +	if (len == 0) +		return (0); + +	if (ct->ct_sock + 1 > FD_SETSIZE) { +		int bytes = howmany(ct->ct_sock + 1, NFDBITS) * sizeof(fd_mask); +		fds = (fd_set *)malloc(bytes); +		if (fds == NULL) +			return (-1); +		memset(fds, 0, bytes); +	} else { +		fds = &readfds; +		FD_ZERO(fds); +	} + +	gettimeofday(&start, NULL); +	delta = ct->ct_wait; +	while (TRUE) { +		/* XXX we know the other bits are still clear */ +		FD_SET(ct->ct_sock, fds); +		tv = delta;	/* in case select writes back */ +		r = select(ct->ct_sock+1, fds, NULL, NULL, &tv); +		save_errno = errno; + +		gettimeofday(&after, NULL); +		timersub(&start, &after, &duration); +		timersub(&delta, &duration, &tmp); +		delta = tmp; +		if (delta.tv_sec < 0 || !timerisset(&delta)) +			r = 0; + +		switch (r) { +		case 0: +			if (fds != &readfds) +				free(fds); +			ct->ct_error.re_status = RPC_TIMEDOUT; +			return (-1); + +		case -1: +			if (errno == EINTR) +				continue; +			if (fds != &readfds) +				free(fds); +			ct->ct_error.re_status = RPC_CANTRECV; +			ct->ct_error.re_errno = save_errno; +			return (-1); +		} +		break; +	} +	switch (len = __msgread(ct->ct_sock, buf, len)) { + +	case 0: +		/* premature eof */ +		ct->ct_error.re_errno = ECONNRESET; +		ct->ct_error.re_status = RPC_CANTRECV; +		len = -1;  /* it's really an error */ +		break; + +	case -1: +		ct->ct_error.re_errno = errno; +		ct->ct_error.re_status = RPC_CANTRECV; +		break; +	} +	return (len); +} + +static int +writeunix(ct, buf, len) +	struct ct_data *ct; +	caddr_t buf; +	int len; +{ +	register int i, cnt; + +	for (cnt = len; cnt > 0; cnt -= i, buf += i) { +		if ((i = __msgwrite(ct->ct_sock, buf, cnt)) == -1) { +			ct->ct_error.re_errno = errno; +			ct->ct_error.re_status = RPC_CANTSEND; +			return (-1); +		} +	} +	return (len); +} diff --git a/lib/libc/rpc/crypt_client.c b/lib/libc/rpc/crypt_client.c new file mode 100644 index 000000000000..cdc0c061d8b3 --- /dev/null +++ b/lib/libc/rpc/crypt_client.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1996 + *	Bill Paul <wpaul@ctr.columbia.edu>.  All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + *    notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + *    notice, this list of conditions and the following disclaimer in the + *    documentation and/or other materials provided with the distribution. + * 3. All advertising materials mentioning features or use of this software + *    must display the following acknowledgement: + *	This product includes software developed by Bill Paul. + * 4. Neither the name of the author nor the names of any co-contributors + *    may be used to endorse or promote products derived from this software + *    without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY Bill Paul AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED.  IN NO EVENT SHALL Bill Paul OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + *	$Id$ + */ + +#include <sys/types.h> +#include <rpc/des_crypt.h> +#include <rpc/des.h> +#include <string.h> +#include <rpcsvc/crypt.h> + +#ifndef lint +static const char rcsid[] = "$Id$"; +#endif + +#ifndef KEYSERVSOCK +#define KEYSERVSOCK "/var/run/keyservsock" +#endif + +int +_des_crypt_call(buf, len, dparms) +	char *buf; +	int len; +	struct desparams *dparms; +{ +	CLIENT *clnt; +	desresp  *result_1; +	desargs  des_crypt_1_arg; +	int	stat; + +	clnt = clnt_create(KEYSERVSOCK, CRYPT_PROG, CRYPT_VERS, "unix"); +	if (clnt == (CLIENT *) NULL) { +		return(DESERR_HWERROR); +	} + +	des_crypt_1_arg.desbuf.desbuf_len = len; +	des_crypt_1_arg.desbuf.desbuf_val = buf; +	des_crypt_1_arg.des_dir = dparms->des_dir; +	des_crypt_1_arg.des_mode = dparms->des_mode; +	bcopy(dparms->des_ivec, des_crypt_1_arg.des_ivec, 8); +	bcopy(dparms->des_key, des_crypt_1_arg.des_key, 8); + +	result_1 = des_crypt_1(&des_crypt_1_arg, clnt); +	if (result_1 == (desresp *) NULL) { +		return(DESERR_HWERROR); +	} + +	stat = result_1->stat; + +	if (result_1->stat == DESERR_NONE || +	    result_1->stat == DESERR_NOHWDEVICE) { +		bcopy(result_1->desbuf.desbuf_val, buf, len); +		bcopy(result_1->des_ivec, dparms->des_ivec, 8); +	} + +	clnt_freeres(clnt, xdr_desresp, (char *)result_1); +	clnt_destroy(clnt); + +	return(stat); +} diff --git a/lib/libc/rpc/des_crypt.3 b/lib/libc/rpc/des_crypt.3 new file mode 100644 index 000000000000..ca0a33e1c27d --- /dev/null +++ b/lib/libc/rpc/des_crypt.3 @@ -0,0 +1,126 @@ +.\" @(#)des_crypt.3	2.1 88/08/11 4.0 RPCSRC; from 1.16 88/03/02 SMI; +.TH DES_CRYPT 3  "6 October 1987" +.SH NAME +des_crypt, ecb_crypt, cbc_crypt, des_setparity \- fast DES encryption +.SH SYNOPSIS +.nf +.B #include <des_crypt.h> +.LP +.B int ecb_crypt(key, data, datalen, mode) +.B char *key; +.B char *data; +.B unsigned datalen; +.B unsigned mode; +.LP +.B int cbc_crypt(key, data, datalen, mode, ivec) +.B char *key; +.B char *data; +.B unsigned datalen; +.B unsigned mode; +.B char *ivec; +.LP +.B void des_setparity(key) +.B char *key; +.fi +.SH DESCRIPTION +.IX encryption cbc_crypt "" \fLcbc_crypt\fP +.IX "des encryption" cbc_crypt "DES encryption" \fLcbc_crypt\fP +.IX encryption des_setparity "" \fLdes_setparity\fP +.IX "des encryption" des_setparity "DES encryption" \fLdes_setparity\fP +.B ecb_crypt(\|) +and +.B cbc_crypt(\|) +implement the +.SM NBS +.SM DES +(Data Encryption Standard). +These routines are faster and more general purpose than +.BR crypt (3). +They also are able to utilize +.SM DES +hardware if it is available. +.B ecb_crypt(\|) +encrypts in +.SM ECB +(Electronic Code Book) +mode, which encrypts blocks of data independently. +.B cbc_crypt(\|) +encrypts in +.SM CBC +(Cipher Block Chaining) +mode, which chains together +successive blocks. +.SM CBC +mode protects against insertions, deletions and +substitutions of blocks. Also, regularities in the clear text will +not appear in the cipher text. +.LP +Here is how to use these routines.  The first parameter, +.IR key , +is the 8-byte encryption key with parity. +To set the key's parity, which for +.SM DES +is in the low bit of each byte, use +.IR des_setparity . +The second parameter, +.IR data , +contains the data to be encrypted or decrypted. The +third parameter, +.IR datalen , +is the length in bytes of +.IR data , +which must be a multiple of 8. The fourth parameter, +.IR mode , +is formed by +.SM OR\s0'ing +together some things.  For the encryption direction 'or' in either +.SM DES_ENCRYPT +or +.SM DES_DECRYPT\s0. +For software versus hardware +encryption, 'or' in either +.SM DES_HW +or +.SM DES_SW\s0. +If +.SM DES_HW +is specified, and there is no hardware, then the encryption is performed +in software and the routine returns +.SM DESERR_NOHWDEVICE\s0. +For +.IR cbc_crypt , +the parameter +.I ivec +is the the 8-byte initialization +vector for the chaining.  It is updated to the next initialization +vector upon return. +.LP +.SH "SEE ALSO" +.BR des (1), +.BR crypt (3) +.SH DIAGNOSTICS +.PD 0 +.TP 20 +.SM DESERR_NONE +No error. +.TP +.SM DESERR_NOHWDEVICE +Encryption succeeded, but done in software instead of the requested hardware. +.TP +.SM DESERR_HWERR +An error occurred in the hardware or driver. +.TP +.SM DESERR_BADPARAM +Bad parameter to routine. +.PD +.LP +Given a result status +.IR stat , +the macro +.SM DES_FAILED\c +.BR ( stat ) +is false only for the first two statuses. +.SH RESTRICTIONS +These routines are not available in RPCSRC 4.0. +This information is provided to describe the DES interface expected by +Secure RPC. diff --git a/lib/libc/rpc/des_crypt.c b/lib/libc/rpc/des_crypt.c new file mode 100644 index 000000000000..18c99724d3ea --- /dev/null +++ b/lib/libc/rpc/des_crypt.c @@ -0,0 +1,153 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + *  + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + *  + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + *  + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +/* + * des_crypt.c, DES encryption library routines + * Copyright (C) 1986, Sun Microsystems, Inc. + */ + +#include <sys/types.h> +#include <rpc/des_crypt.h> +#include <rpc/des.h> + +#ifndef lint +/* from: static char sccsid[] = "@(#)des_crypt.c	2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; */ +static const char rcsid[] = "$Id$"; +#endif + +static int common_crypt	__P(( char *, char *, register unsigned, unsigned, struct desparams * )); +int (*__des_crypt_LOCAL)() = 0; +extern _des_crypt_call __P(( char *, int, struct desparams * )); +/* + * Copy 8 bytes + */ +#define COPY8(src, dst) { \ +	register char *a = (char *) dst; \ +	register char *b = (char *) src; \ +	*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +	*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +} +  +/* + * Copy multiple of 8 bytes + */ +#define DESCOPY(src, dst, len) { \ +	register char *a = (char *) dst; \ +	register char *b = (char *) src; \ +	register int i; \ +	for (i = (int) len; i > 0; i -= 8) { \ +		*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +		*a++ = *b++; *a++ = *b++; *a++ = *b++; *a++ = *b++; \ +	} \ +} + +/* + * CBC mode encryption + */ +int +cbc_crypt(key, buf, len, mode, ivec) +	char *key; +	char *buf; +	unsigned len; +	unsigned mode; +	char *ivec;	 +{ +	int err; +	struct desparams dp; + +#ifdef BROKEN_DES +	dp.UDES.UDES_buf = buf; +	dp.des_mode = ECB; +#else +	dp.des_mode = CBC; +#endif +	COPY8(ivec, dp.des_ivec); +	err = common_crypt(key, buf, len, mode, &dp); +	COPY8(dp.des_ivec, ivec); +	return(err); +} + + +/* + * ECB mode encryption + */ +int +ecb_crypt(key, buf, len, mode) +	char *key; +	char *buf; +	unsigned len; +	unsigned mode; +{ +	struct desparams dp; + +#ifdef BROKEN_DES +	dp.UDES.UDES_buf = buf; +	dp.des_mode = CBC; +#else +	dp.des_mode = ECB; +#endif +	return(common_crypt(key, buf, len, mode, &dp)); +} + + + +/* + * Common code to cbc_crypt() & ecb_crypt() + */ +static int +common_crypt(key, buf, len, mode, desp)	 +	char *key;	 +	char *buf; +	register unsigned len; +	unsigned mode; +	register struct desparams *desp; +{ +	register int desdev; + +	if ((len % 8) != 0 || len > DES_MAXDATA) { +		return(DESERR_BADPARAM); +	} +	desp->des_dir = +		((mode & DES_DIRMASK) == DES_ENCRYPT) ? ENCRYPT : DECRYPT; + +	desdev = mode & DES_DEVMASK; +	COPY8(key, desp->des_key); +	/*  +	 * software +	 */ +	if (__des_crypt_LOCAL != NULL) { +		if (!__des_crypt_LOCAL(buf, len, desp)) { +			return (DESERR_HWERROR); +		} +	} else { +		if (!_des_crypt_call(buf, len, desp)) { +			return (DESERR_HWERROR); +		} +	} +	return(desdev == DES_SW ? DESERR_NONE : DESERR_NOHWDEVICE); +} diff --git a/lib/libc/rpc/des_soft.c b/lib/libc/rpc/des_soft.c new file mode 100644 index 000000000000..01dd7f280b2f --- /dev/null +++ b/lib/libc/rpc/des_soft.c @@ -0,0 +1,67 @@ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)des_soft.c	2.2 88/08/10 4.0 RPCSRC; from 1.13 88/02/08 SMI"; +#endif +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + *  + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + *  + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + *  + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +/* + * Table giving odd parity in the low bit for ASCII characters + */ +static char partab[128] = { +	0x01, 0x01, 0x02, 0x02, 0x04, 0x04, 0x07, 0x07, +	0x08, 0x08, 0x0b, 0x0b, 0x0d, 0x0d, 0x0e, 0x0e, +	0x10, 0x10, 0x13, 0x13, 0x15, 0x15, 0x16, 0x16, +	0x19, 0x19, 0x1a, 0x1a, 0x1c, 0x1c, 0x1f, 0x1f, +	0x20, 0x20, 0x23, 0x23, 0x25, 0x25, 0x26, 0x26, +	0x29, 0x29, 0x2a, 0x2a, 0x2c, 0x2c, 0x2f, 0x2f, +	0x31, 0x31, 0x32, 0x32, 0x34, 0x34, 0x37, 0x37, +	0x38, 0x38, 0x3b, 0x3b, 0x3d, 0x3d, 0x3e, 0x3e, +	0x40, 0x40, 0x43, 0x43, 0x45, 0x45, 0x46, 0x46, +	0x49, 0x49, 0x4a, 0x4a, 0x4c, 0x4c, 0x4f, 0x4f, +	0x51, 0x51, 0x52, 0x52, 0x54, 0x54, 0x57, 0x57, +	0x58, 0x58, 0x5b, 0x5b, 0x5d, 0x5d, 0x5e, 0x5e, +	0x61, 0x61, 0x62, 0x62, 0x64, 0x64, 0x67, 0x67, +	0x68, 0x68, 0x6b, 0x6b, 0x6d, 0x6d, 0x6e, 0x6e, +	0x70, 0x70, 0x73, 0x73, 0x75, 0x75, 0x76, 0x76, +	0x79, 0x79, 0x7a, 0x7a, 0x7c, 0x7c, 0x7f, 0x7f, +}; + +/* + * Add odd parity to low bit of 8 byte key + */ +void +des_setparity(p) +	char *p; +{ +	int i; + +	for (i = 0; i < 8; i++) { +		*p = partab[*p & 0x7f]; +		p++; +	} +} diff --git a/lib/libc/rpc/get_myaddress.c b/lib/libc/rpc/get_myaddress.c index 2b0b20d96f0e..f8bfa7c59610 100644 --- a/lib/libc/rpc/get_myaddress.c +++ b/lib/libc/rpc/get_myaddress.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)get_myaddress.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)get_myaddress.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: get_myaddress.c,v 1.1 1993/10/27 05:40:27 paul Exp $"; +static char *rcsid = "$Id: get_myaddress.c,v 1.6 1996/12/30 14:26:28 peter Exp $";  #endif  /* @@ -45,55 +45,65 @@ static char *rcsid = "$Id: get_myaddress.c,v 1.1 1993/10/27 05:40:27 paul Exp $"  #include <rpc/pmap_prot.h>  #include <sys/socket.h>  #include <stdio.h> +#include <unistd.h>  #include <net/if.h>  #include <sys/ioctl.h>  #include <netinet/in.h>  #include <arpa/inet.h> -/*  +/*   * don't use gethostbyname, which would invoke yellow pages + * + * Avoid loopback interfaces.  We return information from a loopback + * interface only if there are no other possible interfaces.   */ +int  get_myaddress(addr)  	struct sockaddr_in *addr;  {  	int s;  	char buf[BUFSIZ];  	struct ifconf ifc; -	struct ifreq ifreq, *ifr; -	int len, slop; +	struct ifreq ifreq, *ifr, *end; +	int loopback = 0, gotit = 0;  	if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { -	    perror("get_myaddress: socket"); -	    exit(1); +		return(-1);  	}  	ifc.ifc_len = sizeof (buf);  	ifc.ifc_buf = buf;  	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) { -		perror("get_myaddress: ioctl (get interface configuration)"); -		exit(1); +		close(s); +		return(-1);  	} +again:  	ifr = ifc.ifc_req; -	for (len = ifc.ifc_len; len; len -= sizeof ifreq) { +	end = (struct ifreq *) (ifc.ifc_buf + ifc.ifc_len); + +	while (ifr < end) {  		ifreq = *ifr;  		if (ioctl(s, SIOCGIFFLAGS, (char *)&ifreq) < 0) { -			perror("get_myaddress: ioctl"); -			exit(1); +			close(s); +			return(-1);  		}  		if ((ifreq.ifr_flags & IFF_UP) && -		    ifr->ifr_addr.sa_family == AF_INET) { +		    ifr->ifr_addr.sa_family == AF_INET && +		    (loopback == 1 && (ifreq.ifr_flags & IFF_LOOPBACK))) {  			*addr = *((struct sockaddr_in *)&ifr->ifr_addr);  			addr->sin_port = htons(PMAPPORT); +			gotit = 1;  			break;  		} -		/* -		 * Deal with variable length addresses -		 */ -		slop = ifr->ifr_addr.sa_len - sizeof (struct sockaddr); -		if (slop) { -			ifr = (struct ifreq *) ((caddr_t)ifr + slop); -			len -= slop; -		} +		if (ifr->ifr_addr.sa_len) +			ifr = (struct ifreq *) ((caddr_t) ifr + +			      ifr->ifr_addr.sa_len - +			      sizeof(struct sockaddr));  		ifr++;  	} +	if (gotit == 0 && loopback == 0) { +		loopback = 1; +		goto again; +	}  	(void) close(s); +	return (0);  } diff --git a/lib/libc/rpc/getrpcent.3 b/lib/libc/rpc/getrpcent.3 index f500c01b075f..5d700791c928 100644 --- a/lib/libc/rpc/getrpcent.3 +++ b/lib/libc/rpc/getrpcent.3 @@ -1,108 +1,95 @@  .\" @(#)getrpcent.3n	2.2 88/08/02 4.0 RPCSRC; from 1.11 88/03/14 SMI -.TH GETRPCENT 3N "14 December 1987" -.SH NAME -getrpcent, getrpcbyname, getrpcbynumber \- get RPC entry -.SH SYNOPSIS -.nf -.ft B -#include <netdb.h> -.LP -.ft B -struct rpcent *getrpcent(\|) -.LP -.ft B -struct rpcent *getrpcbyname(name) -char *name; -.LP -.ft B -struct rpcent *getrpcbynumber(number) -int number; -.LP -.ft B -setrpcent (stayopen) -int stayopen -.LP -.ft B -endrpcent (\|) -.fi -.SH DESCRIPTION -.LP -.BR getrpcent(\|) , -.BR getrpcbyname(\|) , +.Dd "December 14, 1987" +.Dt GETRPCENT 3 +.Os +.Sh NAME +.Nm getrpcent , +.Nm getrpcbyname , +.Nm getrpcbynumber , +.Nm endrpcent , +.Nm setrpcent +.Nd get RPC entry +.Sh SYNOPSIS +.Fd #include <netdb.h> +.Ft struct rpcent * +.Fn getrpcent void +.Ft struct rpcent * +.Fn getrpcbyname "char *name" +.Ft struct rpcent * +.Fn getrpcbynumber "int number" +.Ft void +.Fn setrpcent "int stayopen" +.Ft void +.Fn endrpcent void +.Sh DESCRIPTION +The +.Fn getrpcent , +.Fn getrpcbyname ,  and -.B getrpcbynumber(\|) -each return a pointer to an object with the +.Fn getrpcbynumber +functions each return a pointer to an object with the  following structure  containing the broken-out  fields of a line in the rpc program number data base, -.BR /etc/rpc . -.RS -.LP -.nf -.ft B +.Pa /etc/rpc . +.Bd -literal +  struct	rpcent {  	char	*r_name;	/* name of server for this rpc program */  	char	**r_aliases;	/* alias list */  	long	r_number;	/* rpc program number */  }; -.ft R -.fi -.RE -.LP +.Ed +.Pp  The members of this structure are: -.RS -.PD 0 -.TP 20 -.B r_name +.Bl -tag -width r_aliasesxxx +.It Fa r_name  The name of the server for this rpc program. -.TP 20 -.B r_aliases +.It Fa r_aliases  A zero terminated list of alternate names for the rpc program. -.TP  20 -.B r_number +.It Fa r_number  The rpc program number for this service. -.PD -.RE -.LP -.B getrpcent(\|) -reads the next line of the file, opening the file if necessary. -.LP -.B getrpcent(\|) -opens and rewinds the file.  If the -.I stayopen +.El +.Pp +The +.Fn getrpcent +function reads the next line of the file, opening the file if necessary. +The +.Nm getrpcent +function opens and rewinds the file.  If the +.Fa stayopen  flag is non-zero,  the net data base will not be closed after each call to -.B getrpcent(\|) +.Fn getrpcent  (either directly, or indirectly through one of -the other \*(lqgetrpc\*(rq calls). -.LP -.B endrpcent +the other  +.Fn getrpcent +function family. +.Pp +.Fn endrpcent  closes the file. -.LP -.B getrpcbyname(\|) +.Pp +.Fn getrpcbyname  and -.B getrpcbynumber(\|) +.Fn getrpcbynumber  sequentially search from the beginning  of the file until a matching rpc program name or  program number is found, or until end-of-file is encountered. -.SH FILES -.PD 0 -.TP 20 -.B /etc/rpc -.PD -.SH "SEE ALSO" -.BR rpc (5), -.BR rpcinfo (8C), -.BR ypserv (8) -.SH DIAGNOSTICS -.LP +.Sh FILES +.Bl -tag -width /etc/rpc -compact +.It Pa /etc/rpc +.El +.Sh "SEE ALSO" +.Xr rpc 5 , +.Xr rpcinfo 8 , +.Xr ypserv 8 +.Sh DIAGNOSTICS  A -.SM NULL +.Dv NULL  pointer is returned on  -.SM EOF +.Dv EOF  or error. -.SH BUGS -.LP +.Sh BUGS  All information  is contained in a static area  so it must be copied if it is diff --git a/lib/libc/rpc/getrpcent.c b/lib/libc/rpc/getrpcent.c index a495278f8d27..826628529e5c 100644 --- a/lib/libc/rpc/getrpcent.c +++ b/lib/libc/rpc/getrpcent.c @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)getrpcent.c 1.14 91/03/11 Copyr 1984 Sun Micro";*/ -static char *rcsid = "$Id: getrpcent.c,v 1.1 1993/10/27 05:40:29 paul Exp $"; +static char *rcsid = "$Id: getrpcent.c,v 1.6 1996/12/30 14:42:31 peter Exp $";  #endif  /* @@ -38,6 +38,7 @@ static char *rcsid = "$Id: getrpcent.c,v 1.1 1993/10/27 05:40:29 paul Exp $";   */  #include <stdio.h> +#include <stdlib.h>  #include <sys/types.h>  #include <string.h>  #include <rpc/rpc.h> @@ -65,6 +66,7 @@ struct rpcdata {  #ifdef	YP  static int	__yp_nomap = 0; +extern int _yp_check(char **);  #endif	/* YP */  static	struct rpcent *interpret(); @@ -122,7 +124,7 @@ getrpcbynumber(number)  no_yp:  #endif	/* YP */  	setrpcent(0); -	while (p = getrpcent()) { +	while ((p = getrpcent())) {  		if (p->r_number == number)  			break;  	} @@ -134,20 +136,21 @@ struct rpcent *  getrpcbyname(name)  	char *name;  { -	struct rpcent *rpc; +	struct rpcent *rpc = NULL;  	char **rp;  	setrpcent(0); -	while (rpc = getrpcent()) { +	while ((rpc = getrpcent())) {  		if (strcmp(rpc->r_name, name) == 0) -			return (rpc); +			goto done;  		for (rp = rpc->r_aliases; *rp != NULL; rp++) {  			if (strcmp(*rp, name) == 0) -				return (rpc); +				goto done;  		}  	} +done:  	endrpcent(); -	return (NULL); +	return (rpc);  }  void @@ -201,12 +204,12 @@ endrpcent()  struct rpcent *  getrpcent()  { -	struct rpcent *hp; -	int reason;  	register struct rpcdata *d = _rpcdata();  #ifdef	YP -	char *key = NULL, *val = NULL; -	int keylen, vallen; +	struct rpcent *hp; +	int reason; +	char *val = NULL; +	int vallen;  #endif  	if (d == 0) @@ -243,7 +246,8 @@ no_yp:  #endif	/* YP */  	if (d->rpcf == NULL && (d->rpcf = fopen(RPCDB, "r")) == NULL)  		return (NULL); -        if (fgets(d->line, BUFSIZ, d->rpcf) == NULL) +	/* -1 so there is room to append a \n below */ +        if (fgets(d->line, BUFSIZ - 1, d->rpcf) == NULL)  		return (NULL);  	return (interpret(d->line, strlen(d->line)));  } @@ -259,9 +263,10 @@ interpret(val, len)  	if (d == 0)  		return (0); -	(void) strncpy(d->line, val, len); +	(void) strncpy(d->line, val, BUFSIZ); +	d->line[BUFSIZ] = '\0';  	p = d->line; -	d->line[len] = '\n'; +	p[len] = '\n';  	if (*p == '#')  		return (getrpcent());  	cp = strpbrk(p, "#\n"); @@ -279,7 +284,7 @@ interpret(val, len)  	d->rpc.r_number = atoi(cp);  	q = d->rpc.r_aliases = d->rpc_aliases;  	cp = strpbrk(cp, " \t"); -	if (cp != NULL)  +	if (cp != NULL)  		*cp++ = '\0';  	while (cp && *cp) {  		if (*cp == ' ' || *cp == '\t') { diff --git a/lib/libc/rpc/getrpcport.3 b/lib/libc/rpc/getrpcport.3 index 0323d34a07c8..f9c3cb413765 100644 --- a/lib/libc/rpc/getrpcport.3 +++ b/lib/libc/rpc/getrpcport.3 @@ -1,31 +1,29 @@  .\" @(#)getrpcport.3r	2.2 88/08/02 4.0 RPCSRC; from 1.12 88/02/26 SMI -.TH GETRPCPORT 3R "6 October 1987" -.SH NAME -getrpcport \- get RPC port number -.SH SYNOPSIS -.ft B -.nf -int getrpcport(host, prognum, versnum, proto) -	char *host; -	int prognum, versnum, proto; -.fi -.SH DESCRIPTION -.IX getrpcport "" "\fLgetrpcport\fR \(em get RPC port number" -.B getrpcport(\|) +.Dd "October 6, 1987" +.Dt GETRPCPORT 3 +.Os +.Sh NAME +.Nm getrpcport +.Nd get RPC port number +.Sh SYNOPSIS +.Ft int +.Fn getrpcport "char *host" "int prognum" "int versnum" "int proto" +.Sh DESCRIPTION +.Fn getrpcport  returns the port number for version -.I versnum +.Fa versnum  of the RPC program -.I prognum +.Fa prognum  running on -.I host +.Fa host  and using protocol -.IR proto . +.Fa proto .  It returns 0 if it cannot contact the portmapper, or if -.I prognum +.Fa prognum  is not registered.  If -.I prognum +.Fa prognum  is registered but not with version -.IR versnum , +.Fa versnum ,  it will still return a port number (for some version of the program)  indicating that the program is indeed registered.  The version mismatch will be detected upon the first call to the service. diff --git a/lib/libc/rpc/getrpcport.c b/lib/libc/rpc/getrpcport.c index f1d58f9eb718..04a8de224ae9 100644 --- a/lib/libc/rpc/getrpcport.c +++ b/lib/libc/rpc/getrpcport.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)getrpcport.c 1.3 87/08/11 SMI";*/  /*static char *sccsid = "from: @(#)getrpcport.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: getrpcport.c,v 1.1 1993/10/27 05:40:31 paul Exp $"; +static char *rcsid = "$Id: getrpcport.c,v 1.6 1996/12/30 14:43:42 peter Exp $";  #endif  /* @@ -38,20 +38,26 @@ static char *rcsid = "$Id: getrpcport.c,v 1.1 1993/10/27 05:40:31 paul Exp $";   */  #include <stdio.h> +#include <string.h>  #include <rpc/rpc.h> +#include <rpc/pmap_clnt.h>  #include <netdb.h>  #include <sys/socket.h> +int  getrpcport(host, prognum, versnum, proto)  	char *host; +	int prognum, versnum, proto;  {  	struct sockaddr_in addr;  	struct hostent *hp;  	if ((hp = gethostbyname(host)) == NULL)  		return (0); -	bcopy(hp->h_addr, (char *) &addr.sin_addr, hp->h_length); +	memset(&addr, 0, sizeof(addr)); +	addr.sin_len = sizeof(struct sockaddr_in);  	addr.sin_family = AF_INET;  	addr.sin_port =  0; +	memcpy((char *)&addr.sin_addr, hp->h_addr, hp->h_length);  	return (pmap_getport(&addr, prognum, versnum, proto));  } diff --git a/lib/libc/rpc/key_call.c b/lib/libc/rpc/key_call.c new file mode 100644 index 000000000000..bcef22ed8b72 --- /dev/null +++ b/lib/libc/rpc/key_call.c @@ -0,0 +1,425 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + *  + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + *  + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + *  + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc.  + */ + +#ident	"@(#)key_call.c	1.25	94/04/24 SMI" + +/* + * key_call.c, Interface to keyserver + * + * setsecretkey(key) - set your secret key + * encryptsessionkey(agent, deskey) - encrypt a session key to talk to agent + * decryptsessionkey(agent, deskey) - decrypt ditto + * gendeskey(deskey) - generate a secure des key + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <errno.h> +#include <rpc/rpc.h> +#include <rpc/auth.h> +#include <rpc/auth_unix.h> +#include <rpc/key_prot.h> +#include <string.h> +#include <sys/utsname.h> +#include <stdlib.h> +#include <signal.h> +#include <sys/wait.h> +#include <sys/fcntl.h> + + +#define	KEY_TIMEOUT	5	/* per-try timeout in seconds */ +#define	KEY_NRETRY	12	/* number of retries */ + +#ifdef DEBUG +#define	debug(msg)	(void) fprintf(stderr, "%s\n", msg); +#else +#define	debug(msg) +#endif /* DEBUG */ + +/* + * Hack to allow the keyserver to use AUTH_DES (for authenticated + * NIS+ calls, for example).  The only functions that get called + * are key_encryptsession_pk, key_decryptsession_pk, and key_gendes. + * + * The approach is to have the keyserver fill in pointers to local + * implementations of these functions, and to call those in key_call(). + */ + +cryptkeyres *(*__key_encryptsession_pk_LOCAL)() = 0; +cryptkeyres *(*__key_decryptsession_pk_LOCAL)() = 0; +des_block *(*__key_gendes_LOCAL)() = 0; + +static int key_call __P(( u_long, xdrproc_t, char *, xdrproc_t, char * )); + +int +key_setsecret(secretkey) +	const char *secretkey; +{ +	keystatus status; + +	if (!key_call((u_long) KEY_SET, xdr_keybuf, (char *) secretkey, +			xdr_keystatus, (char *)&status)) { +		return (-1); +	} +	if (status != KEY_SUCCESS) { +		debug("set status is nonzero"); +		return (-1); +	} +	return (0); +} + + +/* key_secretkey_is_set() returns 1 if the keyserver has a secret key + * stored for the caller's effective uid; it returns 0 otherwise + * + * N.B.:  The KEY_NET_GET key call is undocumented.  Applications shouldn't + * be using it, because it allows them to get the user's secret key. + */ + +int +key_secretkey_is_set(void) +{ +	struct key_netstres 	kres; + +	memset((void*)&kres, 0, sizeof (kres)); +	if (key_call((u_long) KEY_NET_GET, xdr_void, (char *)NULL, +			xdr_key_netstres, (char *) &kres) && +	    (kres.status == KEY_SUCCESS) && +	    (kres.key_netstres_u.knet.st_priv_key[0] != 0)) { +		/* avoid leaving secret key in memory */ +		memset(kres.key_netstres_u.knet.st_priv_key, 0, HEXKEYBYTES); +		return (1); +	} +	return (0); +} + +int +key_encryptsession_pk(remotename, remotekey, deskey) +	char *remotename; +	netobj *remotekey; +	des_block *deskey; +{ +	cryptkeyarg2 arg; +	cryptkeyres res; + +	arg.remotename = remotename; +	arg.remotekey = *remotekey; +	arg.deskey = *deskey; +	if (!key_call((u_long)KEY_ENCRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, +			xdr_cryptkeyres, (char *)&res)) { +		return (-1); +	} +	if (res.status != KEY_SUCCESS) { +		debug("encrypt status is nonzero"); +		return (-1); +	} +	*deskey = res.cryptkeyres_u.deskey; +	return (0); +} + +int +key_decryptsession_pk(remotename, remotekey, deskey) +	char *remotename; +	netobj *remotekey; +	des_block *deskey; +{ +	cryptkeyarg2 arg; +	cryptkeyres res; + +	arg.remotename = remotename; +	arg.remotekey = *remotekey; +	arg.deskey = *deskey; +	if (!key_call((u_long)KEY_DECRYPT_PK, xdr_cryptkeyarg2, (char *)&arg, +			xdr_cryptkeyres, (char *)&res)) { +		return (-1); +	} +	if (res.status != KEY_SUCCESS) { +		debug("decrypt status is nonzero"); +		return (-1); +	} +	*deskey = res.cryptkeyres_u.deskey; +	return (0); +} + +int +key_encryptsession(remotename, deskey) +	const char *remotename; +	des_block *deskey; +{ +	cryptkeyarg arg; +	cryptkeyres res; + +	arg.remotename = (char *) remotename; +	arg.deskey = *deskey; +	if (!key_call((u_long)KEY_ENCRYPT, xdr_cryptkeyarg, (char *)&arg, +			xdr_cryptkeyres, (char *)&res)) { +		return (-1); +	} +	if (res.status != KEY_SUCCESS) { +		debug("encrypt status is nonzero"); +		return (-1); +	} +	*deskey = res.cryptkeyres_u.deskey; +	return (0); +} + +int +key_decryptsession(remotename, deskey) +	const char *remotename; +	des_block *deskey; +{ +	cryptkeyarg arg; +	cryptkeyres res; + +	arg.remotename = (char *) remotename; +	arg.deskey = *deskey; +	if (!key_call((u_long)KEY_DECRYPT, xdr_cryptkeyarg, (char *)&arg, +			xdr_cryptkeyres, (char *)&res)) { +		return (-1); +	} +	if (res.status != KEY_SUCCESS) { +		debug("decrypt status is nonzero"); +		return (-1); +	} +	*deskey = res.cryptkeyres_u.deskey; +	return (0); +} + +int +key_gendes(key) +	des_block *key; +{ +	if (!key_call((u_long)KEY_GEN, xdr_void, (char *)NULL, +			xdr_des_block, (char *)key)) { +		return (-1); +	} +	return (0); +} + +int +key_setnet(arg) +struct netstarg *arg; +{ +	keystatus status; + + +	if (!key_call((u_long) KEY_NET_PUT, xdr_key_netstarg, (char *) arg, +		xdr_keystatus, (char *) &status)){ +		return (-1); +	} + +	if (status != KEY_SUCCESS) { +		debug("key_setnet status is nonzero"); +		return (-1); +	} +	return (1); +} + + +int +key_get_conv(pkey, deskey) +	char *pkey; +	des_block *deskey; +{ +	cryptkeyres res; + +	if (!key_call((u_long) KEY_GET_CONV, xdr_keybuf, pkey, +		xdr_cryptkeyres, (char *)&res)) { +		return (-1); +	} +	if (res.status != KEY_SUCCESS) { +		debug("get_conv status is nonzero"); +		return (-1); +	} +	*deskey = res.cryptkeyres_u.deskey; +	return (0); +} + +struct  key_call_private { +	CLIENT	*client;	/* Client handle */ +	pid_t	pid;		/* process-id at moment of creation */ +	uid_t	uid;		/* user-id at last authorization */ +}; +static struct key_call_private *key_call_private_main = NULL; + +#ifdef foo +static void +key_call_destroy(void *vp) +{ +	register struct key_call_private *kcp = (struct key_call_private *)vp; + +	if (kcp) { +		if (kcp->client) +			clnt_destroy(kcp->client); +		free(kcp); +	} +} +#endif + +/* + * Keep the handle cached.  This call may be made quite often. + */ +static CLIENT * +getkeyserv_handle(vers) +int	vers; +{ +	struct key_call_private *kcp = key_call_private_main; +	struct timeval wait_time; +	int fd; +	struct sockaddr_un name; +	int namelen = sizeof(struct sockaddr_un); + +#define	TOTAL_TIMEOUT	30	/* total timeout talking to keyserver */ +#define	TOTAL_TRIES	5	/* Number of tries */ + +	if (kcp == (struct key_call_private *)NULL) { +		kcp = (struct key_call_private *)malloc(sizeof (*kcp)); +		if (kcp == (struct key_call_private *)NULL) { +			return ((CLIENT *) NULL); +		} +		key_call_private_main = kcp; +		kcp->client = NULL; +	} + +	/* if pid has changed, destroy client and rebuild */ +	if (kcp->client != NULL && kcp->pid != getpid()) { +		clnt_destroy(kcp->client); +		kcp->client = NULL; +	} + +	if (kcp->client != NULL) { +		/* if other side closed socket, build handle again */ +		clnt_control(kcp->client, CLGET_FD, (char *)&fd); +		if (getpeername(fd,(struct sockaddr *)&name,&namelen) == -1) { +			auth_destroy(kcp->client->cl_auth); +			clnt_destroy(kcp->client); +			kcp->client = NULL; +		} +	} + +	if (kcp->client != NULL) { +		/* if uid has changed, build client handle again */ +		if (kcp->uid != geteuid()) { +			kcp->uid = geteuid(); +			auth_destroy(kcp->client->cl_auth); +			kcp->client->cl_auth = +				authsys_create("", kcp->uid, 0, 0, NULL); +			if (kcp->client->cl_auth == NULL) { +				clnt_destroy(kcp->client); +				kcp->client = NULL; +				return ((CLIENT *) NULL); +			} +		} +		/* Change the version number to the new one */ +		clnt_control(kcp->client, CLSET_VERS, (void *)&vers); +		return (kcp->client); +	} + +	if ((kcp->client == (CLIENT *) NULL)) +		/* Use the AF_UNIX transport */ +		kcp->client = clnt_create("/var/run/keyservsock", KEY_PROG, +							vers, "unix"); + +	if (kcp->client == (CLIENT *) NULL) { +		return ((CLIENT *) NULL); +	} +	kcp->uid = geteuid(); +	kcp->pid = getpid(); +	kcp->client->cl_auth = authsys_create("", kcp->uid, 0, 0, NULL); +	if (kcp->client->cl_auth == NULL) { +		clnt_destroy(kcp->client); +		kcp->client = NULL; +		return ((CLIENT *) NULL); +	} + +	wait_time.tv_sec = TOTAL_TIMEOUT/TOTAL_TRIES; +	wait_time.tv_usec = 0; +	(void) clnt_control(kcp->client, CLSET_RETRY_TIMEOUT, +		(char *)&wait_time); +	if (clnt_control(kcp->client, CLGET_FD, (char *)&fd)) +		fcntl(fd, F_SETFD, 1);	/* make it "close on exec" */ + +	return (kcp->client); +} + +/* returns  0 on failure, 1 on success */ + +static int +key_call(proc, xdr_arg, arg, xdr_rslt, rslt) +	u_long proc; +	xdrproc_t xdr_arg; +	char *arg; +	xdrproc_t xdr_rslt; +	char *rslt; +{ +	CLIENT *clnt; +	struct timeval wait_time; + +	if (proc == KEY_ENCRYPT_PK && __key_encryptsession_pk_LOCAL) { +		cryptkeyres *res; +		res = (*__key_encryptsession_pk_LOCAL)(geteuid(), arg); +		*(cryptkeyres*)rslt = *res; +		return (1); +	} else if (proc == KEY_DECRYPT_PK && __key_decryptsession_pk_LOCAL) { +		cryptkeyres *res; +		res = (*__key_decryptsession_pk_LOCAL)(geteuid(), arg); +		*(cryptkeyres*)rslt = *res; +		return (1); +	} else if (proc == KEY_GEN && __key_gendes_LOCAL) { +		des_block *res; +		res = (*__key_gendes_LOCAL)(geteuid(), 0); +		*(des_block*)rslt = *res; +		return (1); +	} + +	if ((proc == KEY_ENCRYPT_PK) || (proc == KEY_DECRYPT_PK) || +	    (proc == KEY_NET_GET) || (proc == KEY_NET_PUT) || +	    (proc == KEY_GET_CONV)) +		clnt = getkeyserv_handle(2); /* talk to version 2 */ +	else +		clnt = getkeyserv_handle(1); /* talk to version 1 */ + +	if (clnt == NULL) { +		return (0); +	} + +	wait_time.tv_sec = TOTAL_TIMEOUT; +	wait_time.tv_usec = 0; + +	if (clnt_call(clnt, proc, xdr_arg, arg, xdr_rslt, rslt, +		wait_time) == RPC_SUCCESS) { +		return (1); +	} else { +		return (0); +	} +} diff --git a/lib/libc/rpc/key_prot_xdr.c b/lib/libc/rpc/key_prot_xdr.c new file mode 100644 index 000000000000..8cd6b6b0678e --- /dev/null +++ b/lib/libc/rpc/key_prot_xdr.c @@ -0,0 +1,166 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include <rpc/key_prot.h> +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +#pragma ident	"@(#)key_prot.x	1.7	94/04/29 SMI" + +/* Copyright (c)  1990, 1991 Sun Microsystems, Inc. */ + +/*  + * Compiled from key_prot.x using rpcgen. + * DO NOT EDIT THIS FILE! + * This is NOT source code! + */ + +bool_t +xdr_keystatus(register XDR *xdrs, keystatus *objp) +{ + +	if (!xdr_enum(xdrs, (enum_t *)objp)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_keybuf(register XDR *xdrs, keybuf objp) +{ + +	if (!xdr_opaque(xdrs, objp, HEXKEYBYTES)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_netnamestr(register XDR *xdrs, netnamestr *objp) +{ + +	if (!xdr_string(xdrs, objp, MAXNETNAMELEN)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_cryptkeyarg(register XDR *xdrs, cryptkeyarg *objp) +{ + +	if (!xdr_netnamestr(xdrs, &objp->remotename)) +		return (FALSE); +	if (!xdr_des_block(xdrs, &objp->deskey)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_cryptkeyarg2(register XDR *xdrs, cryptkeyarg2 *objp) +{ + +	if (!xdr_netnamestr(xdrs, &objp->remotename)) +		return (FALSE); +	if (!xdr_netobj(xdrs, &objp->remotekey)) +		return (FALSE); +	if (!xdr_des_block(xdrs, &objp->deskey)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_cryptkeyres(register XDR *xdrs, cryptkeyres *objp) +{ + +	if (!xdr_keystatus(xdrs, &objp->status)) +		return (FALSE); +	switch (objp->status) { +	case KEY_SUCCESS: +		if (!xdr_des_block(xdrs, &objp->cryptkeyres_u.deskey)) +			return (FALSE); +		break; +	} +	return (TRUE); +} + +bool_t +xdr_unixcred(register XDR *xdrs, unixcred *objp) +{ + +	if (!xdr_u_int(xdrs, &objp->uid)) +		return (FALSE); +	if (!xdr_u_int(xdrs, &objp->gid)) +		return (FALSE); +	if (!xdr_array(xdrs, (char **)&objp->gids.gids_val, (u_int *) &objp->gids.gids_len, MAXGIDS, +		sizeof (u_int), (xdrproc_t) xdr_u_int)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_getcredres(register XDR *xdrs, getcredres *objp) +{ + +	if (!xdr_keystatus(xdrs, &objp->status)) +		return (FALSE); +	switch (objp->status) { +	case KEY_SUCCESS: +		if (!xdr_unixcred(xdrs, &objp->getcredres_u.cred)) +			return (FALSE); +		break; +	} +	return (TRUE); +} + +bool_t +xdr_key_netstarg(register XDR *xdrs, key_netstarg *objp) +{ + +	if (!xdr_keybuf(xdrs, objp->st_priv_key)) +		return (FALSE); +	if (!xdr_keybuf(xdrs, objp->st_pub_key)) +		return (FALSE); +	if (!xdr_netnamestr(xdrs, &objp->st_netname)) +		return (FALSE); +	return (TRUE); +} + +bool_t +xdr_key_netstres(register XDR *xdrs, key_netstres *objp) +{ + +	if (!xdr_keystatus(xdrs, &objp->status)) +		return (FALSE); +	switch (objp->status) { +	case KEY_SUCCESS: +		if (!xdr_key_netstarg(xdrs, &objp->key_netstres_u.knet)) +			return (FALSE); +		break; +	} +	return (TRUE); +} diff --git a/lib/libc/rpc/netname.c b/lib/libc/rpc/netname.c new file mode 100644 index 000000000000..3a3942b8a249 --- /dev/null +++ b/lib/libc/rpc/netname.c @@ -0,0 +1,136 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)netname.c 1.8 91/03/11 Copyr 1986 Sun Micro"; +#endif + +/* + * netname utility routines + * convert from unix names to network names and vice-versa + * This module is operating system dependent! + * What we define here will work with any unix system that has adopted + * the sun NIS domain architecture. + */ + +#include <sys/param.h> +#include <rpc/rpc.h> +#include <rpc/rpc_com.h> +#ifdef YP +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#endif +#include <ctype.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <stdio.h> + +#ifndef MAXHOSTNAMELEN +#define MAXHOSTNAMELEN 256 +#endif +#ifndef NGROUPS +#define NGROUPS 16 +#endif + +static char *OPSYS = "unix"; + +/* + * Figure out my fully qualified network name + */ +int +getnetname(name) +	char name[MAXNETNAMELEN+1]; +{ +	uid_t uid; + +	uid = geteuid(); +	if (uid == 0) { +		return (host2netname(name, (char *) NULL, (char *) NULL)); +	} else { +		return (user2netname(name, uid, (char *) NULL)); +	} +} + + +/* + * Convert unix cred to network-name + */ +int +user2netname(netname, uid, domain) +	char netname[MAXNETNAMELEN + 1]; +	uid_t uid; +	char *domain; +{ +	char *dfltdom; + +#define MAXIPRINT	(11)	/* max length of printed integer */ + +	if (domain == NULL) { +		if (_rpc_get_default_domain(&dfltdom) != 0) { +			return (0); +		} +		domain = dfltdom; +	} +	if (strlen(domain) + 1 + MAXIPRINT > MAXNETNAMELEN) { +		return (0); +	} +	(void) sprintf(netname, "%s.%ld@%s", OPSYS, uid, domain);	 +	return (1); +} + + +/* + * Convert host to network-name + */ +int +host2netname(netname, host, domain) +	char netname[MAXNETNAMELEN + 1]; +	char *host; +	char *domain; +{ +	char *dfltdom; +	char hostname[MAXHOSTNAMELEN+1]; + +	if (domain == NULL) { +		if (_rpc_get_default_domain(&dfltdom) != 0) { +			return (0); +		} +		domain = dfltdom; +	} +	if (host == NULL) { +		(void) gethostname(hostname, sizeof(hostname)); +		host = hostname; +	} +	if (strlen(domain) + 1 + strlen(host) > MAXNETNAMELEN) { +		return (0); +	}  +	(void) sprintf(netname, "%s.%s@%s", OPSYS, host, domain); +	return (1); +} diff --git a/lib/libc/rpc/netnamer.c b/lib/libc/rpc/netnamer.c new file mode 100644 index 000000000000..391cc208e0d4 --- /dev/null +++ b/lib/libc/rpc/netnamer.c @@ -0,0 +1,326 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)netnamer.c 1.13 91/03/11 Copyr 1986 Sun Micro"; +#endif +/* + * netname utility routines convert from unix names to network names and + * vice-versa This module is operating system dependent! What we define here + * will work with any unix system that has adopted the sun NIS domain + * architecture. + */ +#include <sys/param.h> +#include <rpc/rpc.h> +#include <rpc/rpc_com.h> +#ifdef YP +#include <rpcsvc/yp_prot.h> +#include <rpcsvc/ypclnt.h> +#endif +#include <ctype.h> +#include <stdio.h> +#include <grp.h> +#include <pwd.h> +#include <string.h> +#include <stdlib.h> +#include <unistd.h> + +static char    *OPSYS = "unix"; +static char    *NETID = "netid.byname"; +static char    *NETIDFILE = "/etc/netid"; + +static int getnetid __P(( char *, char * )); +static int _getgroups __P(( char *, gid_t * )); + +#ifndef NGROUPS +#define NGROUPS 16 +#endif + +/* + * Convert network-name into unix credential + */ +int +netname2user(netname, uidp, gidp, gidlenp, gidlist) +	char            netname[MAXNETNAMELEN + 1]; +	uid_t            *uidp; +	gid_t            *gidp; +	int            *gidlenp; +	gid_t	       *gidlist; +{ +	char           *p; +	int             gidlen; +	uid_t           uid; +	struct passwd  *pwd; +	char            val[1024]; +	char           *val1, *val2; +	char           *domain; +	int             vallen; +	int             err; + +	if (getnetid(netname, val)) { +		p = strtok(val, ":"); +		if (p == NULL) +			return (0); +		*uidp = (uid_t) atol(val); +		p = strtok(NULL, "\n,"); +		*gidp = (gid_t) atol(p); +		if (p == NULL) { +			return (0); +		} +		gidlen = 0; +		for (gidlen = 0; gidlen < NGROUPS; gidlen++) { +			p = strtok(NULL, "\n,"); +			if (p == NULL) +				break; +			gidlist[gidlen] = (gid_t) atol(p); +		} +		*gidlenp = gidlen; + +		return (1); +	} +	val1 = strchr(netname, '.'); +	if (val1 == NULL) +		return (0); +	if (strncmp(netname, OPSYS, (val1-netname))) +		return (0); +	val1++; +	val2 = strchr(val1, '@'); +	if (val2 == NULL) +		return (0); +	vallen = val2 - val1; +	if (vallen > (1024 - 1)) +		vallen = 1024 - 1; +	(void) strncpy(val, val1, 1024); +	val[vallen] = 0; + +	err = _rpc_get_default_domain(&domain);	/* change to rpc */ +	if (err) +		return (0); + +	if (strcmp(val2 + 1, domain)) +		return (0);	/* wrong domain */ + +	/* XXX: uid_t have different sizes on different OS's. sigh! */ +	if (sizeof (uid_t) == sizeof (short)) { +		if (sscanf(val, "%hd", (short *)&uid) != 1) +			return (0); +	} else { +	if (sscanf(val, "%ld", &uid) != 1) +		return (0); +	} +	/* use initgroups method */ +	pwd = getpwuid(uid); +	if (pwd == NULL) +		return (0); +	*uidp = pwd->pw_uid; +	*gidp = pwd->pw_gid; +	*gidlenp = _getgroups(pwd->pw_name, gidlist); +	return (1); +} + +/* + * initgroups + */ + +static int +_getgroups(uname, groups) +	char           *uname; +	gid_t          groups[NGROUPS]; +{ +	gid_t           ngroups = 0; +	register struct group *grp; +	register int    i; +	register int    j; +	int             filter; + +	setgrent(); +	while ((grp = getgrent())) { +		for (i = 0; grp->gr_mem[i]; i++) +			if (!strcmp(grp->gr_mem[i], uname)) { +				if (ngroups == NGROUPS) { +#ifdef DEBUG +					fprintf(stderr, +				"initgroups: %s is in too many groups\n", uname); +#endif +					goto toomany; +				} +				/* filter out duplicate group entries */ +				filter = 0; +				for (j = 0; j < ngroups; j++) +					if (groups[j] == grp->gr_gid) { +						filter++; +						break; +					} +				if (!filter) +					groups[ngroups++] = grp->gr_gid; +			} +	} +toomany: +	endgrent(); +	return (ngroups); +} + +/* + * Convert network-name to hostname + */ +int +netname2host(netname, hostname, hostlen) +	char            netname[MAXNETNAMELEN + 1]; +	char           *hostname; +	int             hostlen; +{ +	int             err; +	char            valbuf[1024]; +	char           *val; +	char           *val2; +	int             vallen; +	char           *domain; + +	if (getnetid(netname, valbuf)) { +		val = valbuf; +		if ((*val == '0') && (val[1] == ':')) { +			(void) strncpy(hostname, val + 2, hostlen); +			return (1); +		} +	} +	val = strchr(netname, '.'); +	if (val == NULL) +		return (0); +	if (strncmp(netname, OPSYS, (val - netname))) +		return (0); +	val++; +	val2 = strchr(val, '@'); +	if (val2 == NULL) +		return (0); +	vallen = val2 - val; +	if (vallen > (hostlen - 1)) +		vallen = hostlen - 1; +	(void) strncpy(hostname, val, vallen); +	hostname[vallen] = 0; + +	err = _rpc_get_default_domain(&domain);	/* change to rpc */ +	if (err) +		return (0); + +	if (strcmp(val2 + 1, domain)) +		return (0);	/* wrong domain */ +	else +		return (1); +} + +/* + * reads the file /etc/netid looking for a + to optionally go to the + * network information service. + */ +int +getnetid(key, ret) +	char           *key, *ret; +{ +	char            buf[1024];	/* big enough */ +	char           *res; +	char           *mkey; +	char           *mval; +	FILE           *fd; +#ifdef YP +	char           *domain; +	int             err; +	char           *lookup; +	int             len; +#endif + +	fd = fopen(NETIDFILE, "r"); +	if (fd == (FILE *) 0) { +#ifdef YP +		res = "+"; +		goto getnetidyp; +#else +		return (0); +#endif +	} +	for (;;) { +		if (fd == (FILE *) 0) +			return (0);	/* getnetidyp brings us here */ +		res = fgets(buf, 1024, fd); +		if (res == 0) { +			fclose(fd); +			return (0); +		} +		if (res[0] == '#') +			continue; +		else if (res[0] == '+') { +#ifdef YP +	getnetidyp: +			err = yp_get_default_domain(&domain); +			if (err) { +				continue; +			} +			lookup = NULL; +			err = yp_match(domain, NETID, key, +				strlen(key), &lookup, &len); +			if (err) { +#ifdef DEBUG +				fprintf(stderr, "match failed error %d\n", err); +#endif +				continue; +			} +			lookup[len] = 0; +			strcpy(ret, lookup); +			free(lookup); +			fclose(fd); +			return (2); +#else	/* YP */ +#ifdef DEBUG +			fprintf(stderr, +"Bad record in %s '+' -- NIS not supported in this library copy\n", +				NETIDFILE); +#endif +			continue; +#endif	/* YP */ +		} else { +			mkey = strtok(buf, "\t "); +			if (mkey == NULL) { +				fprintf(stderr, +		"Bad record in %s -- %s", NETIDFILE, buf); +				continue; +			} +			mval = strtok(NULL, " \t#\n"); +			if (mval == NULL) { +				fprintf(stderr, +		"Bad record in %s val problem - %s", NETIDFILE, buf); +				continue; +			} +			if (strcmp(mkey, key) == 0) { +				strcpy(ret, mval); +				fclose(fd); +				return (1); + +			} +		} +	} +} diff --git a/lib/libc/rpc/pmap_clnt.c b/lib/libc/rpc/pmap_clnt.c index 4ef44ec3144c..9901d8155f78 100644 --- a/lib/libc/rpc/pmap_clnt.c +++ b/lib/libc/rpc/pmap_clnt.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)pmap_clnt.c 1.37 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)pmap_clnt.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_clnt.c,v 1.1 1993/10/27 05:40:32 paul Exp $"; +static char *rcsid = "$Id: pmap_clnt.c,v 1.5 1996/12/30 14:46:33 peter Exp $";  #endif  /* @@ -40,15 +40,22 @@ static char *rcsid = "$Id: pmap_clnt.c,v 1.1 1993/10/27 05:40:32 paul Exp $";   * Copyright (C) 1984, Sun Microsystems, Inc.   */ +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h>  #include <rpc/rpc.h>  #include <rpc/pmap_prot.h>  #include <rpc/pmap_clnt.h> +#include <netinet/in.h>  static struct timeval timeout = { 5, 0 };  static struct timeval tottimeout = { 60, 0 };  void clnt_perror(); +#ifndef PORTMAPSOCK +#define PORTMAPSOCK "/var/run/portmapsock" +#endif  /*   * Set a mapping between program,version and port. @@ -66,10 +73,22 @@ pmap_set(program, version, protocol, port)  	register CLIENT *client;  	struct pmap parms;  	bool_t rslt; +	struct stat st; + +	/* +	 * Temporary hack for backwards compatibility. Eventually +	 * this test will go away and we'll use only the "unix" transport. +	 */ +	if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK) +		client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix"); +	else  { +		if (get_myaddress(&myaddress) != 0) +			return (FALSE); +		myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +		client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, +	    		timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); +	} -	get_myaddress(&myaddress); -	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, -	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE);  	if (client == (CLIENT *)NULL)  		return (FALSE);  	parms.pm_prog = program; @@ -82,7 +101,8 @@ pmap_set(program, version, protocol, port)  		return (FALSE);  	}  	CLNT_DESTROY(client); -	(void)close(socket); +	if (socket != -1) +		(void)close(socket);  	return (rslt);  } @@ -100,10 +120,21 @@ pmap_unset(program, version)  	register CLIENT *client;  	struct pmap parms;  	bool_t rslt; +	struct stat st; -	get_myaddress(&myaddress); -	client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, -	    timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); +	/* +	 * Temporary hack for backwards compatibility. Eventually +	 * this test will go away and we'll use only the "unix" transport. +	 */ +	if (stat(PORTMAPSOCK, &st) == 0 && st.st_mode & S_IFSOCK) +		client = clnt_create(PORTMAPSOCK, PMAPPROG, PMAPVERS, "unix"); +	else { +		if (get_myaddress(&myaddress) != 0) +			return (FALSE); +		myaddress.sin_addr.s_addr = htonl(INADDR_LOOPBACK); +		client = clntudp_bufcreate(&myaddress, PMAPPROG, PMAPVERS, +	    		timeout, &socket, RPCSMALLMSGSIZE, RPCSMALLMSGSIZE); +	}  	if (client == (CLIENT *)NULL)  		return (FALSE);  	parms.pm_prog = program; @@ -112,6 +143,7 @@ pmap_unset(program, version)  	CLNT_CALL(client, PMAPPROC_UNSET, xdr_pmap, &parms, xdr_bool, &rslt,  	    tottimeout);  	CLNT_DESTROY(client); -	(void)close(socket); +	if (socket != -1) +		(void)close(socket);  	return (rslt);  } diff --git a/lib/libc/rpc/pmap_getmaps.c b/lib/libc/rpc/pmap_getmaps.c index 5af52106454b..d4f27742a52d 100644 --- a/lib/libc/rpc/pmap_getmaps.c +++ b/lib/libc/rpc/pmap_getmaps.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)pmap_getmaps.c 1.10 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)pmap_getmaps.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_getmaps.c,v 1.1 1993/10/27 05:40:35 paul Exp $"; +static char *rcsid = "$Id: pmap_getmaps.c,v 1.5 1996/12/30 14:48:28 peter Exp $";  #endif  /* @@ -47,14 +47,13 @@ static char *rcsid = "$Id: pmap_getmaps.c,v 1.1 1993/10/27 05:40:35 paul Exp $";  #include <sys/socket.h>  #include <netdb.h>  #include <stdio.h> +#include <unistd.h>  #include <errno.h>  #include <net/if.h>  #include <sys/ioctl.h>  #define NAMELEN 255  #define MAX_BROADCAST_SIZE 1400 -extern int errno; -  /*   * Get a copy of the current port maps.   * Calls the pmap service remotely to do get the maps. @@ -80,7 +79,8 @@ pmap_getmaps(address)  		}  		CLNT_DESTROY(client);  	} -	(void)close(socket); +	if (socket != -1) +		(void)close(socket);  	address->sin_port = 0;  	return (head);  } diff --git a/lib/libc/rpc/pmap_getport.c b/lib/libc/rpc/pmap_getport.c index 06ed4d409fbb..3d4c48a5544e 100644 --- a/lib/libc/rpc/pmap_getport.c +++ b/lib/libc/rpc/pmap_getport.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)pmap_getport.c 1.9 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)pmap_getport.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_getport.c,v 1.1 1993/10/27 05:40:36 paul Exp $"; +static char *rcsid = "$Id: pmap_getport.c,v 1.4 1996/12/30 14:49:24 peter Exp $";  #endif  /* @@ -45,6 +45,7 @@ static char *rcsid = "$Id: pmap_getport.c,v 1.1 1993/10/27 05:40:36 paul Exp $";  #include <rpc/pmap_clnt.h>  #include <sys/socket.h>  #include <net/if.h> +#include <unistd.h>  static struct timeval timeout = { 5, 0 };  static struct timeval tottimeout = { 60, 0 }; @@ -83,7 +84,8 @@ pmap_getport(address, program, version, protocol)  		}  		CLNT_DESTROY(client);  	} -	(void)close(socket); +	if (socket != -1) +		(void)close(socket);  	address->sin_port = 0;  	return (port);  } diff --git a/lib/libc/rpc/pmap_prot.c b/lib/libc/rpc/pmap_prot.c index ea0a20dfb144..fcb9c9997157 100644 --- a/lib/libc/rpc/pmap_prot.c +++ b/lib/libc/rpc/pmap_prot.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)pmap_prot.c 1.17 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)pmap_prot.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_prot.c,v 1.1 1993/10/27 05:40:37 paul Exp $"; +static char *rcsid = "$Id: pmap_prot.c,v 1.2 1995/05/30 05:41:25 rgrimes Exp $";  #endif  /* @@ -51,8 +51,8 @@ xdr_pmap(xdrs, regs)  	struct pmap *regs;  { -	if (xdr_u_long(xdrs, ®s->pm_prog) &&  -		xdr_u_long(xdrs, ®s->pm_vers) &&  +	if (xdr_u_long(xdrs, ®s->pm_prog) && +		xdr_u_long(xdrs, ®s->pm_vers) &&  		xdr_u_long(xdrs, ®s->pm_prot))  		return (xdr_u_long(xdrs, ®s->pm_port));  	return (FALSE); diff --git a/lib/libc/rpc/pmap_prot2.c b/lib/libc/rpc/pmap_prot2.c index 71ab21a7103b..d81f6129802d 100644 --- a/lib/libc/rpc/pmap_prot2.c +++ b/lib/libc/rpc/pmap_prot2.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)pmap_prot2.c 1.3 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)pmap_prot2.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_prot2.c,v 1.1 1993/10/27 05:40:39 paul Exp $"; +static char *rcsid = "$Id: pmap_prot2.c,v 1.3 1996/06/10 20:13:05 jraynard Exp $";  #endif  /* @@ -45,7 +45,7 @@ static char *rcsid = "$Id: pmap_prot2.c,v 1.1 1993/10/27 05:40:39 paul Exp $";  #include <rpc/pmap_prot.h> -/*  +/*   * What is going on with linked lists? (!)   * First recall the link list declaration from pmap_prot.h:   * @@ -54,11 +54,11 @@ static char *rcsid = "$Id: pmap_prot2.c,v 1.1 1993/10/27 05:40:39 paul Exp $";   *	struct pmaplist *pml_map;   * };   * - * Compare that declaration with a corresponding xdr declaration that  + * Compare that declaration with a corresponding xdr declaration that   * is (a) pointer-less, and (b) recursive:   *   * typedef union switch (bool_t) { - *  + *   *	case TRUE: struct {   *		struct pmap;   * 		pmaplist_t foo; @@ -71,8 +71,8 @@ static char *rcsid = "$Id: pmap_prot2.c,v 1.1 1993/10/27 05:40:39 paul Exp $";   * the C declaration has no bool_t variable.  The bool_t can be   * interpreted as ``more data follows me''; if FALSE then nothing   * follows this bool_t; if TRUE then the bool_t is followed by - * an actual struct pmap, and then (recursively) by the  - * xdr union, pamplist_t.   + * an actual struct pmap, and then (recursively) by the + * xdr union, pamplist_t.   *   * This could be implemented via the xdr_union primitive, though this   * would cause a one recursive call per element in the list.  Rather than do @@ -95,7 +95,7 @@ xdr_pmaplist(xdrs, rp)  	 */  	bool_t more_elements;  	register int freeing = (xdrs->x_op == XDR_FREE); -	register struct pmaplist **next; +	register struct pmaplist **next = NULL;  	while (TRUE) {  		more_elements = (bool_t)(*rp != NULL); @@ -109,7 +109,7 @@ xdr_pmaplist(xdrs, rp)  		 * before we free the current object ...  		 */  		if (freeing) -			next = &((*rp)->pml_next);  +			next = &((*rp)->pml_next);  		if (! xdr_reference(xdrs, (caddr_t *)rp,  		    (u_int)sizeof(struct pmaplist), xdr_pmap))  			return (FALSE); diff --git a/lib/libc/rpc/pmap_rmt.c b/lib/libc/rpc/pmap_rmt.c index 339860c2c153..07a81e2b7fc5 100644 --- a/lib/libc/rpc/pmap_rmt.c +++ b/lib/libc/rpc/pmap_rmt.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)pmap_rmt.c 1.21 87/08/27 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)pmap_rmt.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: pmap_rmt.c,v 1.1 1993/10/27 05:40:40 paul Exp $"; +static char *rcsid = "$Id: pmap_rmt.c,v 1.9 1996/12/30 14:53:20 peter Exp $";  #endif  /* @@ -47,16 +47,17 @@ static char *rcsid = "$Id: pmap_rmt.c,v 1.1 1993/10/27 05:40:40 paul Exp $";  #include <rpc/pmap_rmt.h>  #include <sys/socket.h>  #include <stdio.h> +#include <stdlib.h> +#include <unistd.h>  #include <errno.h> +#include <string.h>  #include <net/if.h>  #include <sys/ioctl.h>  #include <arpa/inet.h>  #define MAX_BROADCAST_SIZE 1400 -extern int errno;  static struct timeval timeout = { 3, 0 }; -  /*   * pmapper remote-call-service interface.   * This routine is used to call the pmapper remote call service @@ -96,7 +97,8 @@ pmap_rmtcall(addr, prog, vers, proc, xdrargs, argsp, xdrres, resp, tout, port_pt  	} else {  		stat = RPC_FAILED;  	} -	(void)close(socket); +	if (socket != -1) +		(void)close(socket);  	addr->sin_port = 0;  	return (stat);  } @@ -156,7 +158,7 @@ xdr_rmtcallres(xdrs, crp)  /*   * The following is kludged-up support for simple rpc broadcasts. - * Someday a large, complicated system will replace these trivial  + * Someday a large, complicated system will replace these trivial   * routines which only support udp/ip .   */ @@ -167,10 +169,11 @@ getbroadcastnets(addrs, sock, buf)  	char *buf;  /* why allocxate more when we can use existing... */  {  	struct ifconf ifc; -        struct ifreq ifreq, *ifr; +	struct ifreq ifreq, *ifr;  	struct sockaddr_in *sin; -        char *cp, *cplim; -        int n, i = 0; +	struct	in_addr addr; +	char *cp, *cplim; +	int n, i = 0;          ifc.ifc_len = UDPMSGSIZE;          ifc.ifc_buf = buf; @@ -196,17 +199,24 @@ getbroadcastnets(addrs, sock, buf)  			sin = (struct sockaddr_in *)&ifr->ifr_addr;  #ifdef SIOCGIFBRDADDR   /* 4.3BSD */  			if (ioctl(sock, SIOCGIFBRDADDR, (char *)&ifreq) < 0) { -				addrs[i++] = +				addr =  				    inet_makeaddr(inet_netof(sin->sin_addr),  				    INADDR_ANY);  			} else { -				addrs[i++] = ((struct sockaddr_in*) +				addr = ((struct sockaddr_in*)  				  &ifreq.ifr_addr)->sin_addr;  			}  #else /* 4.2 BSD */ -			addrs[i++] = inet_makeaddr(inet_netof(sin->sin_addr), +			addr = inet_makeaddr(inet_netof(sin->sin_addr),  			    INADDR_ANY);  #endif +			for (n=i-1; n>=0; n--) { +				if (addr.s_addr == addrs[n].s_addr) +					break; +			} +			if (n<0) { +				addrs[i++] = addr; +			}  		}  	}  	return (i); @@ -214,7 +224,7 @@ getbroadcastnets(addrs, sock, buf)  typedef bool_t (*resultproc_t)(); -enum clnt_stat  +enum clnt_stat  clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  	u_long		prog;		/* program number */  	u_long		vers;		/* version number */ @@ -232,13 +242,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  	int outlen, inlen, fromlen, nets;  	register int sock;  	int on = 1; -#ifdef FD_SETSIZE -	fd_set mask; -	fd_set readfds; -#else -	int readfds; -	register int mask; -#endif /* def FD_SETSIZE */ +	fd_set *fds, readfds;  	register int i;  	bool_t done = FALSE;  	register u_long xid; @@ -248,8 +252,12 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  	struct rmtcallargs a;  	struct rmtcallres r;  	struct rpc_msg msg; -	struct timeval t;  +	struct timeval t, tv;  	char outbuf[MAX_BROADCAST_SIZE], inbuf[UDPMSGSIZE]; +	static u_int32_t disrupt; + +	if (disrupt == 0) +		disrupt = (u_int32_t)(long)resultsp;  	/*  	 * initialization: create a socket, a broadcast address, and @@ -267,20 +275,27 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  		goto done_broad;  	}  #endif /* def SO_BROADCAST */ -#ifdef FD_SETSIZE -	FD_ZERO(&mask); -	FD_SET(sock, &mask); -#else -	mask = (1 << sock); -#endif /* def FD_SETSIZE */ +	if (sock + 1 > FD_SETSIZE) { +		int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); +		fds = (fd_set *)malloc(bytes); +		if (fds == NULL) { +			stat = RPC_CANTSEND; +			goto done_broad; +		} +		memset(fds, 0, bytes); +	} else { +		fds = &readfds; +		FD_ZERO(fds); +	} +  	nets = getbroadcastnets(addrs, sock, inbuf); -	bzero((char *)&baddr, sizeof (baddr)); +	memset(&baddr, 0, sizeof (baddr)); +	baddr.sin_len = sizeof(struct sockaddr_in);  	baddr.sin_family = AF_INET;  	baddr.sin_port = htons(PMAPPORT);  	baddr.sin_addr.s_addr = htonl(INADDR_ANY); -/*	baddr.sin_addr.S_un.S_addr = htonl(INADDR_ANY); */  	(void)gettimeofday(&t, (struct timezone *)0); -	msg.rm_xid = xid = getpid() ^ t.tv_sec ^ t.tv_usec; +	msg.rm_xid = xid = (++disrupt) ^ getpid() ^ t.tv_sec ^ t.tv_usec;  	t.tv_usec = 0;  	msg.rm_direction = CALL;  	msg.rm_call.cb_rpcvers = RPC_MSG_VERSION; @@ -307,6 +322,12 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  	/*  	 * Basic loop: broadcast a packet and wait a while for response(s).  	 * The response timeout grows larger per iteration. +	 * +	 * XXX This will loop about 5 times the stop. If there are +	 * lots of signals being received by the process it will quit +	 * send them all in one quick burst, not paying attention to +	 * the intended function of sending them slowly over half a +	 * minute or so  	 */  	for (t.tv_sec = 4; t.tv_sec <= 14; t.tv_sec += 2) {  		for (i = 0; i < nets; i++) { @@ -326,10 +347,11 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  	recv_again:  		msg.acpted_rply.ar_verf = _null_auth;  		msg.acpted_rply.ar_results.where = (caddr_t)&r; -                msg.acpted_rply.ar_results.proc = xdr_rmtcallres; -		readfds = mask; -		switch (select(_rpc_dtablesize(), &readfds, (int *)NULL,  -			       (int *)NULL, &t)) { +		msg.acpted_rply.ar_results.proc = xdr_rmtcallres; +		/* XXX we know the other bits are still clear */ +		FD_SET(sock, fds); +		tv = t;		/* for select() that copies back */ +		switch (select(sock + 1, fds, NULL, NULL, &tv)) {  		case 0:  /* timed out */  			stat = RPC_TIMEDOUT; @@ -354,7 +376,7 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  			stat = RPC_CANTRECV;  			goto done_broad;  		} -		if (inlen < sizeof(u_long)) +		if (inlen < sizeof(u_int32_t))  			goto recv_again;  		/*  		 * see if reply transaction id matches sent id. @@ -369,13 +391,6 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  				done = (*eachresult)(resultsp, &raddr);  			}  			/* otherwise, we just ignore the errors ... */ -		} else { -#ifdef notdef -			/* some kind of deserialization problem ... */ -			if (msg.rm_xid == xid) -				fprintf(stderr, "Broadcast deserialization problem"); -			/* otherwise, just random garbage */ -#endif  		}  		xdrs->x_op = XDR_FREE;  		msg.acpted_rply.ar_results.proc = xdr_void; @@ -390,7 +405,10 @@ clnt_broadcast(prog, vers, proc, xargs, argsp, xresults, resultsp, eachresult)  		}  	}  done_broad: -	(void)close(sock); +	if (fds != &readfds) +		free(fds); +	if (sock >= 0) +		(void)close(sock);  	AUTH_DESTROY(unix_auth);  	return (stat);  } diff --git a/lib/libc/rpc/publickey.3 b/lib/libc/rpc/publickey.3 new file mode 100644 index 000000000000..7063e8a43ccc --- /dev/null +++ b/lib/libc/rpc/publickey.3 @@ -0,0 +1,44 @@ +.\" @(#)publickey.3r	2.1 88/08/07 4.0 RPCSRC +.TH PUBLICKEY 3R  "6 October 1987" +.SH NAME +publickey, getpublickey, getsecretkey \- get public or secret key +.SH SYNOPSIS +.nf +.B #include <rpc/rpc.h> +.B #include <rpc/key_prot.h> +.LP +.B getpublickey(netname, publickey) +.B	char netname[\s-1MAXNETNAMELEN\s0+1]; +.B	char publickey[\s-1HEXKEYBYTES\s0+1]; +.LP +.B getsecretkey(netname, secretkey, passwd) +.B	char netname[\s-1MAXNETNAMELEN\s0+1]; +.B	char secretkey[\s-1HEXKEYBYTES\s0+1]; +.B	char *passwd; +.fi +.SH DESCRIPTION +.IX "getpublickey function" "" "\fLgetpublickey()\fP function" +.IX "getsecretkey function" "" "\fLgetsecretkey()\fP function" +These routines are used to get public and secret keys from the +.SM YP +database. +.B getsecretkey(\|) +has an extra argument, +.IR passwd , +which is used to decrypt the encrypted secret key stored in the database. +Both routines return 1 if they are successful in finding the key, 0 otherwise. +The keys are returned as +.SM NULL\s0-terminated, +hexadecimal strings. If the password supplied to +.B getsecretkey(\|) +fails to decrypt the secret key, the routine will return 1 but the +.I secretkey +argument will be a +.SM NULL +string (``''). +.SH "SEE ALSO" +.BR publickey (5) +.LP +.I \s-1RPC\s0 Programmer's Manual +in +.TX NETP diff --git a/lib/libc/rpc/publickey.5 b/lib/libc/rpc/publickey.5 new file mode 100644 index 000000000000..de3c1e99e779 --- /dev/null +++ b/lib/libc/rpc/publickey.5 @@ -0,0 +1,37 @@ +.\" @(#)publickey.5	2.1 88/08/07 4.0 RPCSRC; from 1.6 88/02/29 SMI; +.TH PUBLICKEY 5 "19 October 1987" +.SH NAME +publickey \- public key database +.SH SYNOPSIS +.B /etc/publickey +.SH DESCRIPTION +.LP +.B /etc/publickey +is the public key database used for secure +networking. Each entry in +the database consists of a network user +name (which may either refer to +a user or a hostname), followed by the user's +public key (in hex +notation), a colon, and then the user's +secret key encrypted with +its login password (also in hex notation). +.LP +This file is altered either by the user through the +.BR chkey (1) +command or by the system administrator through the +.BR newkey (8) +command. +The file +.B /etc/publickey +should only contain data on the Yellow +Pages master machine, where it +is converted into the +.SM YP +database +.BR publickey.byname . +.SH SEE ALSO +.BR chkey (1), +.BR publickey (3R), +.BR newkey (8), +.BR ypupdated (8C) diff --git a/lib/libc/rpc/rpc.3 b/lib/libc/rpc/rpc.3 index b5a2b92fce76..dd55c228f140 100644 --- a/lib/libc/rpc/rpc.3 +++ b/lib/libc/rpc/rpc.3 @@ -1,5 +1,5 @@  .\" @(#)rpc.3n	2.4 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI -.TH RPC 3N "16 February 1988" +.TH RPC 3 "16 February 1988"  .SH NAME  rpc \- library routines for remote procedure calls  .SH SYNOPSIS AND DESCRIPTION @@ -13,7 +13,7 @@ reply.  Finally, the procedure call returns to the client.  .LP  Routines that are used for Secure RPC (DES authentication) are described in -.BR rpc_secure (3N). +.BR rpc_secure (3).  Secure RPC can be used only if DES encryption is available.  .LP  .ft B @@ -646,7 +646,7 @@ client for the remote program  .IR prognum ,  version  .IR versnum ; -the client uses use +the client uses  .SM UDP/IP  as a transport. The remote program is located at Internet  address @@ -700,7 +700,7 @@ client for the remote program  .IR prognum ,  on  .IR versnum ; -the client uses use +the client uses  .SM UDP/IP  as a transport. The remote program is located at Internet  address @@ -725,7 +725,7 @@ out.  The total time for the call to time out is specified by  .BR clnt_call(\|) .  .IP -This allows the user to specify the maximun packet size for sending and receiving  +This allows the user to specify the maximum packet size for sending and receiving   .SM UDP\s0-based  .SM RPC  messages. @@ -735,7 +735,7 @@ messages.  .ft B  .nf  .sp .5 -void +int  get_myaddress(addr)  struct sockaddr_in *addr;  .fi @@ -749,6 +749,7 @@ without consulting the library routines that deal with  .BR /etc/hosts .  The port number is always set to  .BR htons(\s-1PMAPPORT\s0) . +Returns zero on success, non-zero on failure.  .br  .if t .ne 10  .LP @@ -808,7 +809,7 @@ A return value of zero means that the mapping does not exist  or that  the  .SM RPC -system failured to contact the remote +system failed to contact the remote  .B portmap  service.  In the latter case, the global variable  .B rpc_createerr(\|) @@ -997,7 +998,7 @@ fd_set svc_fdset;  A global variable reflecting the  .SM RPC  service side's -read file descriptor bit mask; it is suitable as a parameter +read file descriptor bit mask; it is suitable as a template parameter  to the  .B select  system call. This is only of interest @@ -1010,6 +1011,13 @@ yet it may change after calls to  .B svc_getreqset(\|)  or any creation routines.  .br +As well, note that if the process has descriptor limits +which are extended beyond +.BR FD_SETSIZE , +this variable will only be usable for the first +.BR FD_SETSIZE +descriptors. +.br  .if t .ne 6  .LP  .ft B @@ -1487,7 +1495,7 @@ This routine returns  .SM NULL  if it fails.  .IP -This allows the user to specify the maximun packet size for sending and  +This allows the user to specify the maximum packet size for sending and   receiving  .SM UDP\s0-based  .SM RPC messages. @@ -1709,8 +1717,8 @@ This routine modifies the global variable  .BR svc_fds(\|) .  Service implementors usually do not need this routine.  .SH SEE ALSO -.BR rpc_secure (3N), -.BR xdr (3N) +.BR rpc_secure (3), +.BR xdr (3)  .br  The following manuals:  .RS diff --git a/lib/libc/rpc/rpc.5 b/lib/libc/rpc/rpc.5 index 324ecb153a83..d7b9d58bd1af 100644 --- a/lib/libc/rpc/rpc.5 +++ b/lib/libc/rpc/rpc.5 @@ -1,71 +1,34 @@  .\" @(#)rpc.5	2.2 88/08/03 4.0 RPCSRC; from 1.4 87/11/27 SMI; -.TH RPC 5  "26 September 1985" -.SH NAME -rpc \- rpc program number data base -.SH SYNOPSIS -.B /etc/rpc -.SH DESCRIPTION +.Dd "September 26, 1985" +.Dt RPC 5 +.Sh NAME +.Nm rpc +.Nd rpc program number data base +.Sh SYNOPSIS +/etc/rpc +.Sh DESCRIPTION  The -.I rpc +.Pa /etc/rpc  file contains user readable names that  can be used in place of rpc program numbers.  Each line has the following information: -.HP 10 +.Pp +.Bl -bullet -compact +.It  name of server for the rpc program -.br -.ns -.HP 10 +.It  rpc program number -.br -.ns -.HP 10 +.It  aliases -.LP +.El +.Pp  Items are separated by any number of blanks and/or  tab characters.  A ``#'' indicates the beginning of a comment; characters up to the end of  the line are not interpreted by routines which search the file. -.LP -Here is an example of the \fI/etc/rpc\fP file from the Sun RPC Source -distribution. -.nf -.ta 1.5i +0.5i +1.0i +1.0i -# -# rpc 88/08/01 4.0 RPCSRC; from 1.12   88/02/07 SMI -# -portmapper		100000	portmap sunrpc -rstatd		100001	rstat rstat_svc rup perfmeter -rusersd		100002	rusers -nfs		100003	nfsprog -ypserv		100004	ypprog -mountd		100005	mount showmount -ypbind		100007 -walld		100008	rwall shutdown -yppasswdd		100009	yppasswd -etherstatd		100010	etherstat -rquotad		100011	rquotaprog quota rquota -sprayd		100012	spray -3270_mapper		100013 -rje_mapper		100014 -selection_svc		100015	selnsvc -database_svc		100016 -rexd		100017	rex -alis		100018 -sched		100019 -llockmgr		100020 -nlockmgr		100021 -x25.inr		100022 -statmon		100023 -status		100024 -bootparam		100026 -ypupdated		100028	ypupdate -keyserv		100029	keyserver -tfsd		100037  -nsed		100038 -nsemntd		100039 -.fi -.DT -.SH FILES -/etc/rpc -.SH "SEE ALSO" -getrpcent(3N) +.Sh FILES +.Bl -tag -compact -width /etc/rpc +.Pa /etc/rpc +.El +.Sh "SEE ALSO" +.Xr getrpcent 3 diff --git a/lib/libc/rpc/rpc_callmsg.c b/lib/libc/rpc/rpc_callmsg.c index 4ec59dbc7855..af8e57309334 100644 --- a/lib/libc/rpc/rpc_callmsg.c +++ b/lib/libc/rpc/rpc_callmsg.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)rpc_callmsg.c 1.4 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)rpc_callmsg.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: rpc_callmsg.c,v 1.1 1993/10/27 05:40:46 paul Exp $"; +static char *rcsid = "$Id: rpc_callmsg.c,v 1.5 1996/12/30 14:55:38 peter Exp $";  #endif  /* @@ -41,7 +41,8 @@ static char *rcsid = "$Id: rpc_callmsg.c,v 1.1 1993/10/27 05:40:46 paul Exp $";   */  #include <sys/param.h> - +#include <stdlib.h> +#include <string.h>  #include <rpc/rpc.h>  /* @@ -52,7 +53,7 @@ xdr_callmsg(xdrs, cmsg)  	register XDR *xdrs;  	register struct rpc_msg *cmsg;  { -	register long *buf; +	register int32_t *buf;  	register struct opaque_auth *oa;  	if (xdrs->x_op == XDR_ENCODE) { @@ -83,16 +84,16 @@ xdr_callmsg(xdrs, cmsg)  			IXDR_PUT_ENUM(buf, oa->oa_flavor);  			IXDR_PUT_LONG(buf, oa->oa_length);  			if (oa->oa_length) { -				bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); -				buf += RNDUP(oa->oa_length) / sizeof (long); +				memcpy((caddr_t)buf, oa->oa_base, oa->oa_length); +				buf += RNDUP(oa->oa_length) / sizeof (int32_t);  			}  			oa = &cmsg->rm_call.cb_verf;  			IXDR_PUT_ENUM(buf, oa->oa_flavor);  			IXDR_PUT_LONG(buf, oa->oa_length);  			if (oa->oa_length) { -				bcopy(oa->oa_base, (caddr_t)buf, oa->oa_length); +				memcpy((caddr_t)buf, oa->oa_base, oa->oa_length);  				/* no real need.... -				buf += RNDUP(oa->oa_length) / sizeof (long); +				buf += RNDUP(oa->oa_length) / sizeof (int32_t);  				*/  			}  			return (TRUE); @@ -131,11 +132,11 @@ xdr_callmsg(xdrs, cmsg)  						return (FALSE);  					}  				} else { -					bcopy((caddr_t)buf, oa->oa_base, +					memcpy(oa->oa_base, (caddr_t)buf,  					    oa->oa_length);  					/* no real need....  					buf += RNDUP(oa->oa_length) / -						sizeof (long); +						sizeof (int32_t);  					*/  				}  			} @@ -165,11 +166,11 @@ xdr_callmsg(xdrs, cmsg)  						return (FALSE);  					}  				} else { -					bcopy((caddr_t)buf, oa->oa_base, +					memcpy(oa->oa_base, (caddr_t)buf,  					    oa->oa_length);  					/* no real need...  					buf += RNDUP(oa->oa_length) / -						sizeof (long); +						sizeof (int32_t);  					*/  				}  			} @@ -177,14 +178,14 @@ xdr_callmsg(xdrs, cmsg)  		}  	}  	if ( -	    xdr_u_long(xdrs, &(cmsg->rm_xid)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&  	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) &&  	    (cmsg->rm_direction == CALL) && -	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) &&  	    (cmsg->rm_call.cb_rpcvers == RPC_MSG_VERSION) && -	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) && -	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers)) && -	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_proc)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_proc)) &&  	    xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_cred)) )  	    return (xdr_opaque_auth(xdrs, &(cmsg->rm_call.cb_verf)));  	return (FALSE); diff --git a/lib/libc/rpc/rpc_commondata.c b/lib/libc/rpc/rpc_commondata.c index e870ab8dde7c..96407821794b 100644 --- a/lib/libc/rpc/rpc_commondata.c +++ b/lib/libc/rpc/rpc_commondata.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -29,18 +29,15 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)rpc_commondata.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: rpc_commondata.c,v 1.1 1993/10/27 05:40:47 paul Exp $"; +static char *rcsid = "$Id: rpc_commondata.c,v 1.3 1996/12/30 14:57:33 peter Exp $";  #endif  #include <rpc/rpc.h>  /*   * This file should only contain common data (global data) that is exported - * by public interfaces  + * by public interfaces   */  struct opaque_auth _null_auth; -#ifdef FD_SETSIZE  fd_set svc_fdset; -#else -int svc_fds; -#endif /* def FD_SETSIZE */ +int svc_maxfd = -1;  struct rpc_createerr rpc_createerr; diff --git a/lib/libc/rpc/rpc_dtablesize.c b/lib/libc/rpc/rpc_dtablesize.c index c4a2ac411b33..c2703fa3e6d4 100644 --- a/lib/libc/rpc/rpc_dtablesize.c +++ b/lib/libc/rpc/rpc_dtablesize.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,19 +30,32 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)rpc_dtablesize.c 1.2 87/08/11 Copyr 1987 Sun Micro";*/  /*static char *sccsid = "from: @(#)rpc_dtablesize.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: rpc_dtablesize.c,v 1.1 1993/10/27 05:40:48 paul Exp $"; +static char *rcsid = "$Id: rpc_dtablesize.c,v 1.6 1996/12/30 18:41:20 peter Exp $";  #endif +#include <sys/types.h> +#include <unistd.h> +  /*   * Cache the result of getdtablesize(), so we don't have to do an   * expensive system call every time.   */ -_rpc_dtablesize() +/* + * XXX In FreeBSD 2.x, you can have the maximum number of open file + * descriptors be greater than FD_SETSIZE (which us 256 by default). + * + * Since old programs tend to use this call to determine the first arg + * for select(), having this return > FD_SETSIZE is a Bad Idea(TM)! + */ +int +_rpc_dtablesize(void)  {  	static int size; -	 +  	if (size == 0) {  		size = getdtablesize(); +		if (size > FD_SETSIZE) +			size = FD_SETSIZE;  	}  	return (size);  } diff --git a/lib/libc/rpc/rpc_prot.c b/lib/libc/rpc/rpc_prot.c index 7fbb36fd7557..8debaf14ad6d 100644 --- a/lib/libc/rpc/rpc_prot.c +++ b/lib/libc/rpc/rpc_prot.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)rpc_prot.c 1.36 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)rpc_prot.c	2.3 88/08/07 4.0 RPCSRC";*/ -static char *rcsid = "$Id: rpc_prot.c,v 1.1 1993/10/27 05:40:50 paul Exp $"; +static char *rcsid = "$Id: rpc_prot.c,v 1.4 1996/12/30 15:00:53 peter Exp $";  #endif  /* @@ -86,9 +86,9 @@ xdr_des_block(xdrs, blkp)  /*   * XDR the MSG_ACCEPTED part of a reply message union   */ -bool_t  +bool_t  xdr_accepted_reply(xdrs, ar) -	register XDR *xdrs;    +	register XDR *xdrs;  	register struct accepted_reply *ar;  { @@ -103,9 +103,11 @@ xdr_accepted_reply(xdrs, ar)  		return ((*(ar->ar_results.proc))(xdrs, ar->ar_results.where));  	case PROG_MISMATCH: -		if (! xdr_u_long(xdrs, &(ar->ar_vers.low))) +		if (! xdr_u_int32_t(xdrs, &(ar->ar_vers.low)))  			return (FALSE); -		return (xdr_u_long(xdrs, &(ar->ar_vers.high))); +		return (xdr_u_int32_t(xdrs, &(ar->ar_vers.high))); +	default: +		break;  	}  	return (TRUE);  /* TRUE => open ended set of problems */  } @@ -113,7 +115,7 @@ xdr_accepted_reply(xdrs, ar)  /*   * XDR the MSG_DENIED part of a reply message union   */ -bool_t  +bool_t  xdr_rejected_reply(xdrs, rr)  	register XDR *xdrs;  	register struct rejected_reply *rr; @@ -125,9 +127,9 @@ xdr_rejected_reply(xdrs, rr)  	switch (rr->rj_stat) {  	case RPC_MISMATCH: -		if (! xdr_u_long(xdrs, &(rr->rj_vers.low))) +		if (! xdr_u_int32_t(xdrs, &(rr->rj_vers.low)))  			return (FALSE); -		return (xdr_u_long(xdrs, &(rr->rj_vers.high))); +		return (xdr_u_int32_t(xdrs, &(rr->rj_vers.high)));  	case AUTH_ERROR:  		return (xdr_enum(xdrs, (enum_t *)&(rr->rj_why))); @@ -149,7 +151,7 @@ xdr_replymsg(xdrs, rmsg)  	register struct rpc_msg *rmsg;  {  	if ( -	    xdr_u_long(xdrs, &(rmsg->rm_xid)) &&  +	    xdr_u_int32_t(xdrs, &(rmsg->rm_xid)) &&  	    xdr_enum(xdrs, (enum_t *)&(rmsg->rm_direction)) &&  	    (rmsg->rm_direction == REPLY) )  		return (xdr_union(xdrs, (enum_t *)&(rmsg->rm_reply.rp_stat), @@ -173,11 +175,11 @@ xdr_callhdr(xdrs, cmsg)  	cmsg->rm_call.cb_rpcvers = RPC_MSG_VERSION;  	if (  	    (xdrs->x_op == XDR_ENCODE) && -	    xdr_u_long(xdrs, &(cmsg->rm_xid)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_xid)) &&  	    xdr_enum(xdrs, (enum_t *)&(cmsg->rm_direction)) && -	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_rpcvers)) && -	    xdr_u_long(xdrs, &(cmsg->rm_call.cb_prog)) ) -	    return (xdr_u_long(xdrs, &(cmsg->rm_call.cb_vers))); +	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_rpcvers)) && +	    xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_prog)) ) +	    return (xdr_u_int32_t(xdrs, &(cmsg->rm_call.cb_vers)));  	return (FALSE);  } @@ -221,7 +223,7 @@ accepted(acpt_stat, error)  	error->re_lb.s2 = (long)acpt_stat;  } -static void  +static void  rejected(rjct_stat, error)  	register enum reject_stat rjct_stat;  	register struct rpc_err *error; @@ -236,6 +238,8 @@ rejected(rjct_stat, error)  	case AUTH_ERROR:  		error->re_status = RPC_AUTHERROR;  		return; +	default: +		break;  	}  	/* something's wrong, but we don't know what ... */  	error->re_status = RPC_FAILED; @@ -287,5 +291,7 @@ _seterr_reply(msg, error)  		error->re_vers.low = msg->acpted_rply.ar_vers.low;  		error->re_vers.high = msg->acpted_rply.ar_vers.high;  		break; +	default: +		break;  	}  } diff --git a/lib/libc/rpc/rpc_secure.3 b/lib/libc/rpc/rpc_secure.3 new file mode 100644 index 000000000000..6e9a2ee362f8 --- /dev/null +++ b/lib/libc/rpc/rpc_secure.3 @@ -0,0 +1,330 @@ +.\" @(#)rpc_secure.3n	2.1 88/08/08 4.0 RPCSRC; from 1.19 88/06/24 SMI +.TH RPC 3N "16 February 1988" +.SH NAME +rpc_secure \- library routines for secure remote procedure calls +.SH SYNOPSIS AND DESCRIPTION +These routines are part of the RPC library.  They implement DES +Authentication.  See +.BR rpc (3N) +for further details about RPC. +.LP +.ft B +.nf +.sp .5 +#include <rpc/rpc.h> +.fi +.ft R +.br +.if t .ne 22 +.LP +.ft B +.nf +.sp .5 +\s-1AUTH\s0 * +authdes_create(name, window, syncaddr, ckey) +char *name; +unsigned window; +struct sockaddr_in *addr; +des_block *ckey; +.fi +.ft R +.IP +.B authdes_create(\|) +is the first of two routines which interface to the +.SM RPC +secure authentication system, known as +.SM DES +authentication. +The second is +.BR authdes_getucred(\|) , +below. Note: the keyserver daemon +.BR keyserv (8C) +must be running for the +.SM DES +authentication system to work. +.IP +.BR authdes_create(\|) , +used on the client side, returns an authentication handle that +will enable the use of the secure authentication system. +The first parameter +.I name +is the network name, or +.IR netname , +of the owner of the server process. This field usually +represents a +.I hostname +derived from the utility routine +.BR host2netname , +but could also represent a user name using +.BR user2netname . +The second field is window on the validity of +the client credential, given in seconds.  A small +window is more secure than a large one, but choosing +too small of a window will increase the frequency of +resynchronizations because of clock drift. The third +parameter +.I syncaddr +is optional.  If it is +.SM NULL\s0, +then the authentication system will assume +that the local clock is always in sync with the server's +clock, and will not attempt resynchronizations. If an address +is supplied, however, then the system will use the address +for consulting the remote time service whenever +resynchronization +is required. This parameter is usually the +address of the +.SM RPC +server itself. The final parameter +.I ckey +is also optional.  If it is +.SM NULL\s0, +then the authentication system will +generate a random +.SM DES +key to be used for the encryption of credentials. +If it is supplied, however, then it will be used instead. +.br +.if t .ne 13 +.LP +.ft B +.nf +.sp .5 +authdes_getucred(adc, uid, gid, grouplen, groups) +struct authdes_cred *adc; +short *uid; +short *gid; +short *grouplen; +int *groups; +.fi +.ft R +.IP +.BR authdes_getucred(\|) , +the second of the two +.SM DES +authentication routines, +is used on the server side for converting a +.SM DES +credential, which is +operating system independent, into a +.UX +credential. This routine differs from utility routine +.B netname2user +in that +.B authdes_getucred(\|) +pulls its information from a cache, and does not have to do a +Yellow Pages lookup every time it is called to get its information. +.br +.ft .ne 8 +.LP +.ft B +.nf +.sp .5 +host2netname(name, host, domain) +char *name; +char *host; +char *domain; +.fi +.ft R +.IP +Convert from a domain-specific hostname to an +operating-system independent netname. Return +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR netname2host(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +key_decryptsession(remotename, deskey) +char *remotename; +des_block *deskey; +.fi +.ft R +.IP +.B key_decryptsession(\|) +is an interface to the keyserver daemon, which is associated +with +.SM RPC\s0's +secure authentication system (\s-1DES\s0 +authentication). +User programs rarely need to call it, or its associated routines +.BR key_encryptsession(\|) , +.B key_gendes(\|) +and +.BR key_setsecret(\|) . +System commands such as +.B login +and the +.SM RPC +library are the main clients of these four routines. +.IP +.B key_decryptsession(\|) +takes a server netname and a des key, and decrypts the key by +using the the public key of the the server and the secret key +associated with the effective uid of the calling process.  It +is the inverse of +.BR key_encryptsession(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +key_encryptsession(remotename, deskey) +char *remotename; +des_block *deskey; +.fi +.ft R +.IP +.B key_encryptsession(\|) +is a keyserver interface routine. It +takes a server netname and a des key, and encrypts +it using the public key of the the server and the secret key +associated with the effective uid of the calling process.  It +is the inverse of +.BR key_decryptsession(\|) . +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +key_gendes(deskey) +des_block *deskey; +.fi +.ft R +.IP +.B key_gendes(\|) +is a keyserver interface routine. It +is used to ask the keyserver for a secure conversation key. +Choosing one at \(lqrandom\(rq is usually not good enough, +because +the common ways of choosing random numbers, such as using the +current time, are very easy to guess. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +key_setsecret(key) +char *key; +.fi +.ft R +.IP +.B key_setsecret(\|) +is a keyserver interface routine. It is used to set the key for +the effective +.I uid +of the calling process. +.br +.if t .ne 7 +.LP +.ft B +.nf +.sp .5 +getnetname(name) +char name[\s-1MAXNETNAMELEN\s0]; +.fi +.ft R +.IP +.B getnetname(\|) +installs the unique, operating-system independent netname of +the +caller in the fixed-length array +.IR name . +Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. +.br +.if t .ne 6 +.LP +.ft B +.nf +.sp .5 +netname2host(name, host, hostlen) +char *name; +char *host; +int hostlen; +.fi +.ft R +.IP +Convert from an operating-system independent netname to a +domain-specific hostname. Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails.  Inverse of +.BR host2netname(\|) . +.br +.if t .ne 9 +.LP +.ft B +.nf +.sp .5 +netname2user(name, uidp, gidp, gidlenp, gidlist) +char *name; +int *uidp; +int *gidp; +int *gidlenp; +int *gidlist; +.fi +.ft R +.IP +Convert from an operating-system independent netname to a +domain-specific user +.SM ID. +Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR user2netname(\|) . +.br +.if t .ne 8 +.LP +.ft B +.nf +.sp .5 +user2netname(name, uid, domain) +char *name; +int uid; +char *domain; +.fi +.ft R +.IP +Convert from a domain-specific username to an operating-system +independent netname. Returns +.SM TRUE +if it succeeds and +.SM FALSE +if it fails. Inverse of +.BR netname2user(\|) . +.br +.SH SEE ALSO +.BR xdr (3N), +.BR keyserv (8C), +.BR rpc (3N) +.br +The following manuals: +.RS +.ft I +Remote Procedure Calls: Protocol Specification +.br +Remote Procedure Call Programming Guide +.br +rpcgen Programming Guide +.br +.ft R +.RE +.IR "\s-1RPC\s0: Remote Procedure Call Protocol Specification" , +.SM RFC1050, Sun Microsystems, Inc., +.SM USC-ISI\s0. + diff --git a/lib/libc/rpc/rpcdname.c b/lib/libc/rpc/rpcdname.c new file mode 100644 index 000000000000..f28b4fda9b8a --- /dev/null +++ b/lib/libc/rpc/rpcdname.c @@ -0,0 +1,77 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user or with the express written consent of + * Sun Microsystems, Inc. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)rpcdname.c 1.7 91/03/11 Copyr 1989 Sun Micro"; +#endif + +/* + * rpcdname.c + * Gets the default domain name + */ + +#include <stdlib.h> +#include <unistd.h> +#include <string.h> + +static char *default_domain = 0; + +static char * +get_default_domain() +{ +	char temp[256]; + +	if (default_domain) +		return (default_domain); +	if (getdomainname(temp, sizeof(temp)) < 0) +		return (0); +	if ((int) strlen(temp) > 0) { +		default_domain = (char *)malloc((strlen(temp)+(unsigned)1)); +		if (default_domain == 0) +			return (0); +		(void) strcpy(default_domain, temp); +		return (default_domain); +	} +	return (0); +} + +/* + * This is a wrapper for the system call getdomainname which returns a + * ypclnt.h error code in the failure case.  It also checks to see that + * the domain name is non-null, knowing that the null string is going to + * get rejected elsewhere in the NIS client package. + */ +int +_rpc_get_default_domain(domain) +	char **domain; +{ +	if ((*domain = get_default_domain()) != 0) +		return (0); +	return (-1); +} diff --git a/lib/libc/rpc/rstat.1 b/lib/libc/rpc/rstat.1 index 61d9999116f8..03c3a063b301 100644 --- a/lib/libc/rpc/rstat.1 +++ b/lib/libc/rpc/rstat.1 @@ -17,7 +17,7 @@ The load average numbers give the number of jobs in the run queue  averaged over 1, 5 and 15 minutes.  .PP  The -.B rstat_svc(8c) +.B rstat_svc(8)  daemon must be running on the remote host for this command to  work.  .B rstat @@ -50,8 +50,8 @@ daemon has terminated on the remote host.  rstat: RPC: Port mapper failure - RPC: Timed out  .IP  The remote host is not running the portmapper (see -.BR portmap(8c) ), -and cannot accomodate any RPC-based services.  The host may be down. +.BR portmap(8) ), +and cannot accommodate any RPC-based services.  The host may be down.  .SH "SEE ALSO" -.BR portmap (8c), -.BR rstat_svc (8c) +.BR portmap (8), +.BR rstat_svc (8) diff --git a/lib/libc/rpc/rstat_svc.8 b/lib/libc/rpc/rstat_svc.8 index a10b71dbacad..b7b438681ba9 100644 --- a/lib/libc/rpc/rstat_svc.8 +++ b/lib/libc/rpc/rstat_svc.8 @@ -1,5 +1,5 @@  .\" @(#)rstat_svc.8c	2.2 88/08/03 4.0 RPCSRC; from 1.10 87/09/09 SMI -.TH RSTAT_SVC 8C "24 November 1987" +.TH RSTAT_SVC 8 "24 November 1987"  .SH NAME  rstat_svc \- kernel statistics server  .SH SYNOPSIS @@ -17,5 +17,5 @@ daemon is normally invoked at boot time through /etc/rc.local.  .PP  .B rstat_svc  uses an RPC protocol defined in /usr/include/rpcsvc/rstat.x. -.SH "SEE ALSO" -.BR rstat (1), +.\" .SH "SEE ALSO" +.\" .BR rstat (1), diff --git a/lib/libc/rpc/rtime.3 b/lib/libc/rpc/rtime.3 new file mode 100644 index 000000000000..af0c1ca15960 --- /dev/null +++ b/lib/libc/rpc/rtime.3 @@ -0,0 +1,43 @@ +.\" @(#)rtime.3n	2.1 88/08/08 4.0 RPCSRC; from 1.5 88/02/08 SMI +.TH RTIME 3  "22 November 1987" +.SH NAME +rtime \- get remote time +.SH SYNOPSIS +.nf +.B #include <sys/types.h> +.B #include <sys/time.h> +.B #include <netinet/in.h> +.LP +.B int rtime(addrp, timep, timeout) +.B struct sockaddr_in \(**addrp; +.B struct timeval \(**timep; +.B struct timeval \(**timeout; +.fi +.SH DESCRIPTION +.B rtime(\|) +consults the Internet Time Server at the address pointed to by +.I addrp +and returns the remote time in the +.B timeval +struct pointed to by +.IR timep . +Normally, the +.SM UDP +protocol is used when consulting the Time Server. The +.I timeout +parameter specifies how long the +routine should wait before giving +up when waiting for a reply.  If +.I timeout +is specified as +.SM NULL\s0, +however, the routine will instead use +.SM TCP +and block until a reply is received from the time server. +.LP +The routine returns 0 if it is successful. Otherwise, +it returns \-1 and +.B errno +is set to reflect the cause of the error. +.SH "SEE ALSO" +.BR timed (8c) diff --git a/lib/libc/rpc/rtime.c b/lib/libc/rpc/rtime.c new file mode 100644 index 000000000000..fb2b4021f5f1 --- /dev/null +++ b/lib/libc/rpc/rtime.c @@ -0,0 +1,157 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + *  + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + *  + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + *  + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + + */ + +/* + * rtime - get time from remote machine + * + * gets time, obtaining value from host + * on the udp/time socket.  Since timeserver returns + * with time of day in seconds since Jan 1, 1900,  must + * subtract seconds before Jan 1, 1970 to get + * what unix uses. + */ +#include <stdlib.h> +#include <string.h> +#include <unistd.h> +#include <errno.h> +#include <sys/types.h> +#include <sys/socket.h> +#include <sys/time.h> +#include <netinet/in.h> +#include <stdio.h> +#include <netdb.h> + +#if defined(LIBC_SCCS) && !defined(lint) +/* from: static char sccsid[] = 	"@(#)rtime.c	2.2 88/08/10 4.0 RPCSRC; from 1.8 88/02/08 SMI"; */ +static const char rcsid[] = "$Id$"; +#endif + +extern int _rpc_dtablesize __P(( void )); + +#define NYEARS	(unsigned long)(1970 - 1900) +#define TOFFSET (unsigned long)(60*60*24*(365*NYEARS + (NYEARS/4))) + +static void do_close __P(( int )); + +int +rtime(addrp, timep, timeout) +	struct sockaddr_in *addrp; +	struct timeval *timep; +	struct timeval *timeout; +{ +	int s; +	fd_set readfds; +	int res; +	unsigned long thetime; +	struct sockaddr_in from; +	int fromlen; +	int type; +	struct servent *serv; + +	if (timeout == NULL) { +		type = SOCK_STREAM; +	} else { +		type = SOCK_DGRAM; +	} +	s = socket(AF_INET, type, 0); +	if (s < 0) { +		return(-1); +	} +	addrp->sin_family = AF_INET; + +	/* TCP and UDP port are the same in this case */ +	if ((serv = getservbyname("time", "tcp")) == NULL) { +		return(-1); +	} + +	addrp->sin_port = serv->s_port; + +	if (type == SOCK_DGRAM) { +		res = sendto(s, (char *)&thetime, sizeof(thetime), 0,  +			     (struct sockaddr *)addrp, sizeof(*addrp)); +		if (res < 0) { +			do_close(s); +			return(-1);	 +		} +		do { +			FD_ZERO(&readfds); +			FD_SET(s, &readfds); +			res = select(_rpc_dtablesize(), &readfds, +				     (fd_set *)NULL, (fd_set *)NULL, timeout); +		} while (res < 0 && errno == EINTR); +		if (res <= 0) { +			if (res == 0) { +				errno = ETIMEDOUT; +			} +			do_close(s); +			return(-1);	 +		} +		fromlen = sizeof(from); +		res = recvfrom(s, (char *)&thetime, sizeof(thetime), 0,  +			       (struct sockaddr *)&from, &fromlen); +		do_close(s); +		if (res < 0) { +			return(-1);	 +		} +	} else { +		if (connect(s, (struct sockaddr *)addrp, sizeof(*addrp)) < 0) { +			do_close(s); +			return(-1); +		} +		res = read(s, (char *)&thetime, sizeof(thetime)); +		do_close(s); +		if (res < 0) { +			return(-1); +		} +	} +	if (res != sizeof(thetime)) { +		errno = EIO; +		return(-1);	 +	} +	thetime = ntohl(thetime); +	timep->tv_sec = thetime - TOFFSET; +	timep->tv_usec = 0; +	return(0); +} + +static void +do_close(s) +	int s; +{ +	int save; + +	save = errno; +	(void) close(s); +	errno = save; +} diff --git a/lib/libc/rpc/svc.c b/lib/libc/rpc/svc.c index 55ad25e92ad0..ab0e8c164bcf 100644 --- a/lib/libc/rpc/svc.c +++ b/lib/libc/rpc/svc.c @@ -5,32 +5,32 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043   */ -#if defined(LIBC_SCCS) && !defined(lint)  +#if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc.c 1.44 88/02/08 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc.c	2.4 88/08/11 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc.c,v 1.1 1993/10/27 05:40:54 paul Exp $"; +static char *rcsid = "$Id: svc.c,v 1.7 1996/12/30 15:07:33 peter Exp $";  #endif  /* @@ -43,23 +43,20 @@ static char *rcsid = "$Id: svc.c,v 1.1 1993/10/27 05:40:54 paul Exp $";   * Copyright (C) 1984, Sun Microsystems, Inc.   */ +#include <string.h> +#include <stdlib.h>  #include <sys/errno.h>  #include <rpc/rpc.h>  #include <rpc/pmap_clnt.h> -extern int errno; - -#ifdef FD_SETSIZE  static SVCXPRT **xports; -#else -#define NOFILE 32 - -static SVCXPRT *xports[NOFILE]; -#endif /* def FD_SETSIZE */ +static int xportssize;  #define NULL_SVC ((struct svc_callout *)0)  #define	RQCRED_SIZE	400		/* this size is excessive */ +#define max(a, b) (a > b ? a : b) +  /*   * The services list   * Each entry represents a set of procedures (an rpc program). @@ -75,6 +72,9 @@ static struct svc_callout {  static struct svc_callout *svc_find(); +int __svc_fdsetsize; +fd_set *__svc_fdset; +  /* ***************  SVCXPRT related stuff **************** */  /* @@ -86,44 +86,68 @@ xprt_register(xprt)  {  	register int sock = xprt->xp_sock; -#ifdef FD_SETSIZE -	if (xports == NULL) { -		xports = (SVCXPRT **) -			mem_alloc(FD_SETSIZE * sizeof(SVCXPRT *)); +	if (sock + 1 > __svc_fdsetsize) { +		int bytes = howmany(sock + 1, NFDBITS) * sizeof(fd_mask); +		fd_set *fds; + +		fds = (fd_set *)malloc(bytes); +		memset(fds, 0, bytes); +		if (__svc_fdset) { +			memcpy(fds, __svc_fdset, howmany(__svc_fdsetsize, +				NFDBITS) * sizeof(fd_mask)); +			free(__svc_fdset); +		} +		__svc_fdset = fds; +		__svc_fdsetsize = howmany(sock+1, NFDBITS);  	} -	if (sock < _rpc_dtablesize()) { -		xports[sock] = xprt; + +	if (sock < FD_SETSIZE)  		FD_SET(sock, &svc_fdset); +	FD_SET(sock, __svc_fdset); + +	if (xports == NULL || sock + 1 > xportssize) { +		SVCXPRT **xp; +		int size = FD_SETSIZE; + +		if (sock + 1 > size) +			size = sock + 1; +		xp = (SVCXPRT **)mem_alloc(size * sizeof(SVCXPRT *)); +		memset(xp, 0, size * sizeof(SVCXPRT *)); +		if (xports) { +			memcpy(xp, xports, xportssize * sizeof(SVCXPRT *)); +			free(xports); +		} +		xportssize = size; +		xports = xp;  	} -#else -	if (sock < NOFILE) { -		xports[sock] = xprt; -		svc_fds |= (1 << sock); -	} -#endif /* def FD_SETSIZE */ - +	xports[sock] = xprt; +	svc_maxfd = max(svc_maxfd, sock);  }  /* - * De-activate a transport handle.  + * De-activate a transport handle.   */  void -xprt_unregister(xprt)  +xprt_unregister(xprt)  	SVCXPRT *xprt; -{  +{  	register int sock = xprt->xp_sock; -#ifdef FD_SETSIZE -	if ((sock < _rpc_dtablesize()) && (xports[sock] == xprt)) { +	if (xports[sock] == xprt) {  		xports[sock] = (SVCXPRT *)0; -		FD_CLR(sock, &svc_fdset); +		if (sock < FD_SETSIZE) +			FD_CLR(sock, &svc_fdset); +		FD_CLR(sock, __svc_fdset); +		if (sock == svc_maxfd) { +			for (svc_maxfd--; svc_maxfd >= 0; svc_maxfd--) +				if (xports[svc_maxfd]) +					break; +		} +		/* +		 * XXX could use svc_maxfd as a hint to +		 * decrease the size of __svc_fdset +		 */  	} -#else -	if ((sock < NOFILE) && (xports[sock] == xprt)) { -		xports[sock] = (SVCXPRT *)0; -		svc_fds &= ~(1 << sock); -	} -#endif /* def FD_SETSIZE */  } @@ -225,15 +249,15 @@ svc_sendreply(xprt, xdr_results, xdr_location)  	xdrproc_t xdr_results;  	caddr_t xdr_location;  { -	struct rpc_msg rply;  +	struct rpc_msg rply; -	rply.rm_direction = REPLY;   -	rply.rm_reply.rp_stat = MSG_ACCEPTED;  -	rply.acpted_rply.ar_verf = xprt->xp_verf;  +	rply.rm_direction = REPLY; +	rply.rm_reply.rp_stat = MSG_ACCEPTED; +	rply.acpted_rply.ar_verf = xprt->xp_verf;  	rply.acpted_rply.ar_stat = SUCCESS;  	rply.acpted_rply.ar_results.where = xdr_location;  	rply.acpted_rply.ar_results.proc = xdr_results; -	return (SVC_REPLY(xprt, &rply));  +	return (SVC_REPLY(xprt, &rply));  }  /* @@ -259,13 +283,13 @@ void  svcerr_decode(xprt)  	register SVCXPRT *xprt;  { -	struct rpc_msg rply;  +	struct rpc_msg rply; -	rply.rm_direction = REPLY;  -	rply.rm_reply.rp_stat = MSG_ACCEPTED;  +	rply.rm_direction = REPLY; +	rply.rm_reply.rp_stat = MSG_ACCEPTED;  	rply.acpted_rply.ar_verf = xprt->xp_verf;  	rply.acpted_rply.ar_stat = GARBAGE_ARGS; -	SVC_REPLY(xprt, &rply);  +	SVC_REPLY(xprt, &rply);  }  /* @@ -275,13 +299,13 @@ void  svcerr_systemerr(xprt)  	register SVCXPRT *xprt;  { -	struct rpc_msg rply;  +	struct rpc_msg rply; -	rply.rm_direction = REPLY;  -	rply.rm_reply.rp_stat = MSG_ACCEPTED;  +	rply.rm_direction = REPLY; +	rply.rm_reply.rp_stat = MSG_ACCEPTED;  	rply.acpted_rply.ar_verf = xprt->xp_verf;  	rply.acpted_rply.ar_stat = SYSTEM_ERR; -	SVC_REPLY(xprt, &rply);  +	SVC_REPLY(xprt, &rply);  }  /* @@ -315,15 +339,15 @@ svcerr_weakauth(xprt)  /*   * Program unavailable error reply   */ -void  +void  svcerr_noprog(xprt)  	register SVCXPRT *xprt;  { -	struct rpc_msg rply;   +	struct rpc_msg rply; -	rply.rm_direction = REPLY;    -	rply.rm_reply.rp_stat = MSG_ACCEPTED;   -	rply.acpted_rply.ar_verf = xprt->xp_verf;   +	rply.rm_direction = REPLY; +	rply.rm_reply.rp_stat = MSG_ACCEPTED; +	rply.acpted_rply.ar_verf = xprt->xp_verf;  	rply.acpted_rply.ar_stat = PROG_UNAVAIL;  	SVC_REPLY(xprt, &rply);  } @@ -331,9 +355,9 @@ svcerr_noprog(xprt)  /*   * Program version mismatch error reply   */ -void   +void  svcerr_progvers(xprt, low_vers, high_vers) -	register SVCXPRT *xprt;  +	register SVCXPRT *xprt;  	u_long low_vers;  	u_long high_vers;  { @@ -358,9 +382,9 @@ svcerr_progvers(xprt, low_vers, high_vers)   * the "raw" parameters (msg.rm_call.cb_cred and msg.rm_call.cb_verf) and   * the "cooked" credentials (rqst->rq_clntcred).   * However, this function does not know the structure of the cooked - * credentials, so it make the following assumptions:  + * credentials, so it make the following assumptions:   *   a) the structure is contiguous (no pointers), and - *   b) the cred structure size does not exceed RQCRED_SIZE bytes.  + *   b) the cred structure size does not exceed RQCRED_SIZE bytes.   * In all events, all three parameters are freed upon exit from this routine.   * The storage is trivially management on the call stack in user land, but   * is mallocated in kernel land. @@ -370,29 +394,25 @@ void  svc_getreq(rdfds)  	int rdfds;  { -#ifdef FD_SETSIZE  	fd_set readfds;  	FD_ZERO(&readfds);  	readfds.fds_bits[0] = rdfds;  	svc_getreqset(&readfds); -#else -	int readfds = rdfds & svc_fds; - -	svc_getreqset(&readfds); -#endif /* def FD_SETSIZE */  }  void  svc_getreqset(readfds) -#ifdef FD_SETSIZE  	fd_set *readfds;  { -#else -	int *readfds; +	svc_getreqset2(readfds, FD_SETSIZE); +} + +void +svc_getreqset2(readfds, width) +	fd_set *readfds; +	int width;  { -    int readfds_local = *readfds; -#endif /* def FD_SETSIZE */  	enum xprt_stat stat;  	struct rpc_msg msg;  	int prog_found; @@ -400,30 +420,23 @@ svc_getreqset(readfds)  	u_long high_vers;  	struct svc_req r;  	register SVCXPRT *xprt; -	register u_long mask;  	register int bit; -	register u_long *maskp; -	register int setsize;  	register int sock; +	register fd_mask mask, *maskp;  	char cred_area[2*MAX_AUTH_BYTES + RQCRED_SIZE];  	msg.rm_call.cb_cred.oa_base = cred_area;  	msg.rm_call.cb_verf.oa_base = &(cred_area[MAX_AUTH_BYTES]);  	r.rq_clntcred = &(cred_area[2*MAX_AUTH_BYTES]); -#ifdef FD_SETSIZE -	setsize = _rpc_dtablesize();	 -	maskp = (u_long *)readfds->fds_bits; -	for (sock = 0; sock < setsize; sock += NFDBITS) { -	    for (mask = *maskp++; bit = ffs(mask); mask ^= (1 << (bit - 1))) { +	maskp = readfds->fds_bits; +	for (sock = 0; sock < width; sock += NFDBITS) { +	    for (mask = *maskp++; (bit = ffs(mask)); mask ^= (1 << (bit - 1))) {  		/* sock has input waiting */  		xprt = xports[sock + bit - 1]; -#else -	for (sock = 0; readfds_local != 0; sock++, readfds_local >>= 1) { -	    if ((readfds_local & 1) != 0) { -		/* sock has input waiting */ -		xprt = xports[sock]; -#endif /* def FD_SETSIZE */ +		if (xprt == NULL) +			/* But do we control sock? */ +			continue;  		/* now receive msgs from xprtprt (support batch calls) */  		do {  			if (SVC_RECV(xprt, &msg)) { @@ -444,7 +457,7 @@ svc_getreqset(readfds)  				}  				/* now match message with a registered service*/  				prog_found = FALSE; -				low_vers = 0 - 1; +				low_vers = (u_long) - 1;  				high_vers = 0;  				for (s = svc_head; s != NULL_SVC; s = s->sc_next) {  					if (s->sc_prog == r.rq_prog) { diff --git a/lib/libc/rpc/svc_auth.c b/lib/libc/rpc/svc_auth.c index 0a9f2765bf6a..0063e750621a 100644 --- a/lib/libc/rpc/svc_auth.c +++ b/lib/libc/rpc/svc_auth.c @@ -13,63 +13,76 @@   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - * + *    * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - * + *    * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - * + *    * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043   */ +/* + * Copyright (c) 1986-1991 by Sun Microsystems Inc.  + */ + +#ident	"@(#)svc_auth.c	1.16	94/04/24 SMI" -#if defined(LIBC_SCCS) && !defined(lint) -/*static char *sccsid = "from: @(#)svc_auth.c 1.19 87/08/11 Copyr 1984 Sun Micro";*/ -/*static char *sccsid = "from: @(#)svc_auth.c	2.1 88/08/07 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_auth.c,v 1.1 1993/10/27 05:40:56 paul Exp $"; +#if !defined(lint) && defined(SCCSIDS) +static char sccsid[] = "@(#)svc_auth.c 1.26 89/02/07 Copyr 1984 Sun Micro";  #endif  /* - * svc_auth_nodes.c, Server-side rpc authenticator interface, - * *WITHOUT* DES authentication. + * svc_auth.c, Server-side rpc authenticator interface.   * - * Copyright (C) 1984, Sun Microsystems, Inc.   */ +#ifdef KERNEL +#include <sys/param.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/clnt.h> +#include <rpc/rpc_msg.h> +#include <rpc/svc.h> +#include <rpc/svc_auth.h> +#else +#include <stdlib.h>  #include <rpc/rpc.h> +#endif +#include <sys/types.h>  /* - * svcauthsw is the bdevsw of server side authentication.  - *  + * svcauthsw is the bdevsw of server side authentication. + *   * Server side authenticators are called from authenticate by   * using the client auth struct flavor field to index into svcauthsw. - * The server auth flavors must implement a routine that looks   - * like:  - *  + * The server auth flavors must implement a routine that looks + * like: + *   *	enum auth_stat   *	flavorx_auth(rqst, msg) - *		register struct svc_req *rqst;  + *		register struct svc_req *rqst;   *		register struct rpc_msg *msg;   *   */ -enum auth_stat _svcauth_null();		/* no authentication */ -enum auth_stat _svcauth_unix();		/* unix style (uid, gids) */ +enum auth_stat _svcauth_null();	/* no authentication */ +enum auth_stat _svcauth_unix();		/* (system) unix style (uid, gids) */  enum auth_stat _svcauth_short();	/* short hand unix style */ +enum auth_stat _svcauth_des();		/* des style */ -static struct { -	enum auth_stat (*authenticator)(); -} svcauthsw[] = { -	_svcauth_null,			/* AUTH_NULL */ -	_svcauth_unix,			/* AUTH_UNIX */ -	_svcauth_short,			/* AUTH_SHORT */ +/* declarations to allow servers to specify new authentication flavors */ +struct authsvc { +	int	flavor; +	enum	auth_stat (*handler)(); +	struct	authsvc	  *next;  }; -#define	AUTH_MAX	2		/* HIGHEST AUTH NUMBER */ - +static struct authsvc *Auths = NULL;  /*   * The call rpc message, msg has been obtained from the wire.  The msg contains @@ -95,23 +108,104 @@ _authenticate(rqst, msg)  	struct rpc_msg *msg;  {  	register int cred_flavor; +	register struct authsvc *asp;  	rqst->rq_cred = msg->rm_call.cb_cred;  	rqst->rq_xprt->xp_verf.oa_flavor = _null_auth.oa_flavor;  	rqst->rq_xprt->xp_verf.oa_length = 0;  	cred_flavor = rqst->rq_cred.oa_flavor; -	if ((cred_flavor <= AUTH_MAX) && (cred_flavor >= AUTH_NULL)) { -		return ((*(svcauthsw[cred_flavor].authenticator))(rqst, msg)); +	switch (cred_flavor) { +	case AUTH_NULL: +		return(_svcauth_null(rqst, msg)); +	case AUTH_UNIX: +		return(_svcauth_unix(rqst, msg)); +	case AUTH_SHORT: +		return(_svcauth_short(rqst, msg)); +	/* +	 * We leave AUTH_DES turned off by default because svcauth_des() +	 * needs getpublickey(), which is in librpcsvc, not libc. If we + 	 * included AUTH_DES as a built-in flavor, programs that don't +	 * have -lrpcsvc in their Makefiles wouldn't link correctly, even +	 * though they don't use AUTH_DES. And I'm too lazy to go through +	 * the tree looking for all of them. +	 */ +#ifdef DES_BUILTIN +	case AUTH_DES: +		return(_svcauth_des(rqst, msg)); +#endif +	} + +	/* flavor doesn't match any of the builtin types, so try new ones */ +	for (asp = Auths; asp; asp = asp->next) { +		if (asp->flavor == cred_flavor) { +			enum auth_stat as; + +			as = (*asp->handler)(rqst, msg); +			return (as); +		}  	}  	return (AUTH_REJECTEDCRED);  } +/*ARGSUSED*/  enum auth_stat -_svcauth_null(/*rqst, msg*/) -	/*struct svc_req *rqst; -	struct rpc_msg *msg;*/ +_svcauth_null(rqst, msg) +	struct svc_req *rqst; +	struct rpc_msg *msg;  { -  	return (AUTH_OK);  } + +/* + *  Allow the rpc service to register new authentication types that it is + *  prepared to handle.  When an authentication flavor is registered, + *  the flavor is checked against already registered values.  If not + *  registered, then a new Auths entry is added on the list. + * + *  There is no provision to delete a registration once registered. + * + *  This routine returns: + *	 0 if registration successful + *	 1 if flavor already registered + *	-1 if can't register (errno set) + */ + +int +svc_auth_reg(cred_flavor, handler) +	register int cred_flavor; +	enum auth_stat (*handler)(); +{ +	register struct authsvc *asp; + +	switch (cred_flavor) { +	    case AUTH_NULL: +	    case AUTH_UNIX: +	    case AUTH_SHORT: +#ifdef DES_BUILTIN +	    case AUTH_DES: +#endif +		/* already registered */ +		return (1); + +	    default: +		for (asp = Auths; asp; asp = asp->next) { +			if (asp->flavor == cred_flavor) { +				/* already registered */ +				return (1); +			} +		} + +		/* this is a new one, so go ahead and register it */ +		asp = (struct authsvc *)mem_alloc(sizeof (*asp)); +		if (asp == NULL) { +			return (-1); +		} +		asp->flavor = cred_flavor; +		asp->handler = handler; +		asp->next = Auths; +		Auths = asp; +		break; +	} +	return (0); +} diff --git a/lib/libc/rpc/svc_auth_des.c b/lib/libc/rpc/svc_auth_des.c new file mode 100644 index 000000000000..889182e6992f --- /dev/null +++ b/lib/libc/rpc/svc_auth_des.c @@ -0,0 +1,531 @@ + +/* + * Copyright (c) 1988 by Sun Microsystems, Inc. + */ + +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + *  + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + *  + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ + +/* + * svcauth_des.c, server-side des authentication + * + * We insure for the service the following: + * (1) The timestamp microseconds do not exceed 1 million. + * (2) The timestamp plus the window is less than the current time. + * (3) The timestamp is not less than the one previously + *     seen in the current session. + * + * It is up to the server to determine if the window size is + * too small . + * + */ + +#include <string.h> +#include <stdlib.h> +#include <unistd.h> +#include <rpc/des_crypt.h> +#include <sys/param.h> +#include <netinet/in.h> +#include <rpc/types.h> +#include <rpc/xdr.h> +#include <rpc/auth.h> +#include <rpc/auth_des.h> +#include <rpc/svc.h> +#include <rpc/rpc_msg.h> +#include <rpc/svc_auth.h> + +#if defined(LIBC_SCCS) && !defined(lint) +/* from: static char sccsid[] = 	"@(#)svcauth_des.c	2.3 89/07/11 4.0 RPCSRC; from 1.15 88/02/08 SMI"; */ +static const char rcsid[] = "$Id$"; +#endif + +#define debug(msg)	 printf("svcauth_des: %s\n", msg)  + +#define USEC_PER_SEC ((u_long) 1000000L) +#define BEFORE(t1, t2) timercmp(t1, t2, <) + +/* + * LRU cache of conversation keys and some other useful items. + */ +#define AUTHDES_CACHESZ 64 +struct cache_entry { +	des_block key;		/* conversation key */ +	char *rname;		/* client's name */ +	u_int window;		/* credential lifetime window */ +	struct timeval laststamp;	/* detect replays of creds */ +	char *localcred;	/* generic local credential */ +}; +static struct cache_entry *authdes_cache/* [AUTHDES_CACHESZ] */; +static short *authdes_lru/* [AUTHDES_CACHESZ] */; + +static void cache_init();	/* initialize the cache */ +static short cache_spot();	/* find an entry in the cache */ +static void cache_ref(/*short sid*/);	/* note that sid was ref'd */ + +static void invalidate();	/* invalidate entry in cache */ + +/* + * cache statistics  + */ +static struct { +	u_long ncachehits;	/* times cache hit, and is not replay */ +	u_long ncachereplays;	/* times cache hit, and is replay */ +	u_long ncachemisses;	/* times cache missed */ +} svcauthdes_stats; + +/* + * Service side authenticator for AUTH_DES + */ +enum auth_stat +_svcauth_des(rqst, msg) +	register struct svc_req *rqst; +	register struct rpc_msg *msg; +{ + +	register long *ixdr; +	des_block cryptbuf[2]; +	register struct authdes_cred *cred; +	struct authdes_verf verf; +	int status; +	register struct cache_entry *entry; +	short sid = 0; +	des_block *sessionkey; +	des_block ivec; +	u_int window; +	struct timeval timestamp; +	u_long namelen; +	struct area { +		struct authdes_cred area_cred; +		char area_netname[MAXNETNAMELEN+1]; +	} *area; + +	if (authdes_cache == NULL) { +		cache_init(); +	} + +	area = (struct area *)rqst->rq_clntcred; +	cred = (struct authdes_cred *)&area->area_cred; + +	/* +	 * Get the credential +	 */ +	ixdr = (long *)msg->rm_call.cb_cred.oa_base; +	cred->adc_namekind = IXDR_GET_ENUM(ixdr, enum authdes_namekind); +	switch (cred->adc_namekind) { +	case ADN_FULLNAME: +		namelen = IXDR_GET_U_LONG(ixdr); +		if (namelen > MAXNETNAMELEN) { +			return (AUTH_BADCRED); +		} +		cred->adc_fullname.name = area->area_netname; +		bcopy((char *)ixdr, cred->adc_fullname.name,  +			(u_int)namelen); +		cred->adc_fullname.name[namelen] = 0; +		ixdr += (RNDUP(namelen) / BYTES_PER_XDR_UNIT); +		cred->adc_fullname.key.key.high = (u_long)*ixdr++; +		cred->adc_fullname.key.key.low = (u_long)*ixdr++; +		cred->adc_fullname.window = (u_long)*ixdr++; +		break; +	case ADN_NICKNAME: +		cred->adc_nickname = (u_long)*ixdr++; +		break; +	default: +		return (AUTH_BADCRED);	 +	} + +	/* +	 * Get the verifier +	 */ +	ixdr = (long *)msg->rm_call.cb_verf.oa_base; +	verf.adv_xtimestamp.key.high = (u_long)*ixdr++; +	verf.adv_xtimestamp.key.low =  (u_long)*ixdr++; +	verf.adv_int_u = (u_long)*ixdr++; + + +	/* +	 * Get the conversation key + 	 */ +	if (cred->adc_namekind == ADN_FULLNAME) { +		netobj pkey; +		char pkey_data[1024]; + +		sessionkey = &cred->adc_fullname.key; +		if (! getpublickey(cred->adc_fullname.name, pkey_data)) { +			debug("getpublickey"); +			return(AUTH_BADCRED); +		} +		pkey.n_bytes = pkey_data; +		pkey.n_len = strlen(pkey_data) + 1; +		if (key_decryptsession_pk(cred->adc_fullname.name, &pkey, +				       sessionkey) < 0) { +			debug("decryptsessionkey"); +			return (AUTH_BADCRED); /* key not found */ +		} +	} else { /* ADN_NICKNAME */	 +		sid = (short)cred->adc_nickname; +		if (sid >= AUTHDES_CACHESZ) { +			debug("bad nickname"); +			return (AUTH_BADCRED);	/* garbled credential */ +		} +		sessionkey = &authdes_cache[sid].key; +	} + + +	/* +	 * Decrypt the timestamp +	 */ +	cryptbuf[0] = verf.adv_xtimestamp;  +	if (cred->adc_namekind == ADN_FULLNAME) { +		cryptbuf[1].key.high = cred->adc_fullname.window; +		cryptbuf[1].key.low = verf.adv_winverf; +		ivec.key.high = ivec.key.low = 0;	 +		status = cbc_crypt((char *)sessionkey, (char *)cryptbuf, +			2*sizeof(des_block), DES_DECRYPT | DES_HW,  +			(char *)&ivec); +	} else { +		status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, +			sizeof(des_block), DES_DECRYPT | DES_HW); +	} +	if (DES_FAILED(status)) { +		debug("decryption failure"); +		return (AUTH_FAILED);	/* system error */ +	} + +	/* +	 * XDR the decrypted timestamp +	 */ +	ixdr = (long *)cryptbuf; +	timestamp.tv_sec = IXDR_GET_LONG(ixdr); +	timestamp.tv_usec = IXDR_GET_LONG(ixdr); + +	/* + 	 * Check for valid credentials and verifiers. +	 * They could be invalid because the key was flushed +	 * out of the cache, and so a new session should begin. +	 * Be sure and send AUTH_REJECTED{CRED, VERF} if this is the case. +	 */ +	{ +		struct timeval current; +		int nick; +		int winverf; + +		if (cred->adc_namekind == ADN_FULLNAME) { +			window = IXDR_GET_U_LONG(ixdr); +			winverf = IXDR_GET_U_LONG(ixdr); +			if (winverf != window - 1) { +				debug("window verifier mismatch"); +				return (AUTH_BADCRED);	/* garbled credential */ +			} +			sid = cache_spot(sessionkey, cred->adc_fullname.name,  +			    ×tamp); +			if (sid < 0) { +				debug("replayed credential"); +				return (AUTH_REJECTEDCRED);	/* replay */ +			} +			nick = 0; +		} else {	/* ADN_NICKNAME */ +			window = authdes_cache[sid].window; +			nick = 1; +		} + +		if ((u_long)timestamp.tv_usec >= USEC_PER_SEC) { +			debug("invalid usecs"); +			/* cached out (bad key), or garbled verifier */ +			return (nick ? AUTH_REJECTEDVERF : AUTH_BADVERF); +		} +		if (nick && BEFORE(×tamp,  +				   &authdes_cache[sid].laststamp)) { +			debug("timestamp before last seen"); +			return (AUTH_REJECTEDVERF);	/* replay */ +		} +		(void) gettimeofday(¤t, (struct timezone *)NULL); +		current.tv_sec -= window;	/* allow for expiration */ +		if (!BEFORE(¤t, ×tamp)) { +			debug("timestamp expired"); +			/* replay, or garbled credential */ +			return (nick ? AUTH_REJECTEDVERF : AUTH_BADCRED); +		} +	} + +	/* +	 * Set up the reply verifier +	 */ +	verf.adv_nickname = (u_long)sid; + +	/* +	 * xdr the timestamp before encrypting +	 */ +	ixdr = (long *)cryptbuf; +	IXDR_PUT_LONG(ixdr, timestamp.tv_sec - 1); +	IXDR_PUT_LONG(ixdr, timestamp.tv_usec); + +	/*	  +	 * encrypt the timestamp +	 */ +	status = ecb_crypt((char *)sessionkey, (char *)cryptbuf, +	    sizeof(des_block), DES_ENCRYPT | DES_HW); +	if (DES_FAILED(status)) { +		debug("encryption failure"); +		return (AUTH_FAILED);	/* system error */ +	} +	verf.adv_xtimestamp = cryptbuf[0]; + +	/* +	 * Serialize the reply verifier, and update rqst +	 */ +	ixdr = (long *)msg->rm_call.cb_verf.oa_base; +	*ixdr++ = (long)verf.adv_xtimestamp.key.high; +	*ixdr++ = (long)verf.adv_xtimestamp.key.low; +	*ixdr++ = (long)verf.adv_int_u; + +	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_DES; +	rqst->rq_xprt->xp_verf.oa_base = msg->rm_call.cb_verf.oa_base; +	rqst->rq_xprt->xp_verf.oa_length =  +		(char *)ixdr - msg->rm_call.cb_verf.oa_base; + +	/* +	 * We succeeded, commit the data to the cache now and +	 * finish cooking the credential. +	 */ +	entry = &authdes_cache[sid]; +	entry->laststamp = timestamp; +	cache_ref(sid); +	if (cred->adc_namekind == ADN_FULLNAME) { +		cred->adc_fullname.window = window; +		cred->adc_nickname = (u_long)sid;	/* save nickname */ +		if (entry->rname != NULL) { +			mem_free(entry->rname, strlen(entry->rname) + 1); +		} +		entry->rname = (char *)mem_alloc((u_int)strlen(cred->adc_fullname.name) +					 + 1); +		if (entry->rname != NULL) { +			(void) strcpy(entry->rname, cred->adc_fullname.name); +		} else { +			debug("out of memory"); +		} +		entry->key = *sessionkey; +		entry->window = window; +		invalidate(entry->localcred); /* mark any cached cred invalid */ +	} else { /* ADN_NICKNAME */ +		/* +		 * nicknames are cooked into fullnames +		 */	 +		cred->adc_namekind = ADN_FULLNAME; +		cred->adc_fullname.name = entry->rname; +		cred->adc_fullname.key = entry->key; +		cred->adc_fullname.window = entry->window; +	} +	return (AUTH_OK);	/* we made it!*/ +} + + +/* + * Initialize the cache + */ +static void +cache_init() +{ +	register int i; + +	authdes_cache = (struct cache_entry *) +		mem_alloc(sizeof(struct cache_entry) * AUTHDES_CACHESZ);	 +	bzero((char *)authdes_cache,  +		sizeof(struct cache_entry) * AUTHDES_CACHESZ); + +	authdes_lru = (short *)mem_alloc(sizeof(short) * AUTHDES_CACHESZ); +	/* +	 * Initialize the lru list +	 */ +	for (i = 0; i < AUTHDES_CACHESZ; i++) { +		authdes_lru[i] = i; +	} +} + + +/* + * Find the lru victim + */ +static short +cache_victim() +{ +	return (authdes_lru[AUTHDES_CACHESZ-1]); +} + +/* + * Note that sid was referenced + */ +static void +cache_ref(sid) +	register short sid; +{ +	register int i; +	register short curr; +	register short prev; + +	prev = authdes_lru[0]; +	authdes_lru[0] = sid; +	for (i = 1; prev != sid; i++) { +		curr = authdes_lru[i]; +		authdes_lru[i] = prev; +		prev = curr; +	} +} + + +/* + * Find a spot in the cache for a credential containing + * the items given.  Return -1 if a replay is detected, otherwise + * return the spot in the cache. + */ +static short +cache_spot(key, name, timestamp) +	register des_block *key; +	char *name; +	struct timeval *timestamp; +{ +	register struct cache_entry *cp; +	register int i; +	register u_long hi; + +	hi = key->key.high; +	for (cp = authdes_cache, i = 0; i < AUTHDES_CACHESZ; i++, cp++) { +		if (cp->key.key.high == hi &&  +		    cp->key.key.low == key->key.low && +		    cp->rname != NULL && +		    bcmp(cp->rname, name, strlen(name) + 1) == 0) { +			if (BEFORE(timestamp, &cp->laststamp)) { +				svcauthdes_stats.ncachereplays++; +				return (-1); /* replay */ +			} +			svcauthdes_stats.ncachehits++; +			return (i);	/* refresh */ +		} +	} +	svcauthdes_stats.ncachemisses++; +	return (cache_victim());	/* new credential */ +} + + +#if (defined(sun) || defined(vax) || defined(__FreeBSD__)) +/* + * Local credential handling stuff. + * NOTE: bsd unix dependent. + * Other operating systems should put something else here. + */ +#define UNKNOWN 	-2	/* grouplen, if cached cred is unknown user */ +#define INVALID		-1 	/* grouplen, if cache entry is invalid */ + +struct bsdcred { +	short uid;		/* cached uid */ +	short gid;		/* cached gid */ +	short grouplen;	/* length of cached groups */ +	short groups[NGROUPS];	/* cached groups */ +}; + +/* + * Map a des credential into a unix cred. + * We cache the credential here so the application does + * not have to make an rpc call every time to interpret + * the credential. + */ +int +authdes_getucred(adc, uid, gid, grouplen, groups) +	struct authdes_cred *adc; +	uid_t *uid; +	gid_t *gid; +	int *grouplen; +	register gid_t *groups; +{ +	unsigned sid; +	register int i; +	uid_t i_uid;	 +	gid_t i_gid; +	int i_grouplen; +	struct bsdcred *cred; + +	sid = adc->adc_nickname; +	if (sid >= AUTHDES_CACHESZ) { +		debug("invalid nickname"); +		return (0); +	} +	cred = (struct bsdcred *)authdes_cache[sid].localcred; +	if (cred == NULL) { +		cred = (struct bsdcred *)mem_alloc(sizeof(struct bsdcred)); +		authdes_cache[sid].localcred = (char *)cred; +		cred->grouplen = INVALID; +	} +	if (cred->grouplen == INVALID) { +		/* +		 * not in cache: lookup +		 */ +		if (!netname2user(adc->adc_fullname.name, &i_uid, &i_gid,  +			&i_grouplen, groups)) +		{ +			debug("unknown netname"); +			cred->grouplen = UNKNOWN;	/* mark as lookup up, but not found */ +			return (0); +		} +		debug("missed ucred cache"); +		*uid = cred->uid = i_uid; +		*gid = cred->gid = i_gid; +		*grouplen = cred->grouplen = i_grouplen; +		for (i = i_grouplen - 1; i >= 0; i--) { +			cred->groups[i] = groups[i]; /* int to short */ +		} +		return (1); +	} else if (cred->grouplen == UNKNOWN) { +		/* +		 * Already lookup up, but no match found +		 */	 +		return (0); +	} + +	/* +	 * cached credentials +	 */ +	*uid = cred->uid; +	*gid = cred->gid; +	*grouplen = cred->grouplen; +	for (i = cred->grouplen - 1; i >= 0; i--) { +		groups[i] = cred->groups[i];	/* short to int */ +	} +	return (1); +} + +static void +invalidate(cred) +	char *cred; +{ +	if (cred == NULL) { +		return; +	} +	((struct bsdcred *)cred)->grouplen = INVALID; +} +#endif + diff --git a/lib/libc/rpc/svc_auth_unix.c b/lib/libc/rpc/svc_auth_unix.c index 5cf825f6f8ab..959cb7363887 100644 --- a/lib/libc/rpc/svc_auth_unix.c +++ b/lib/libc/rpc/svc_auth_unix.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc_auth_unix.c 1.28 88/02/08 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc_auth_unix.c	2.3 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_auth_unix.c,v 1.1 1993/10/27 05:40:58 paul Exp $"; +static char *rcsid = "$Id: svc_auth_unix.c,v 1.4 1996/12/30 15:10:14 peter Exp $";  #endif  /* @@ -45,6 +45,7 @@ static char *rcsid = "$Id: svc_auth_unix.c,v 1.1 1993/10/27 05:40:58 paul Exp $"   */  #include <stdio.h> +#include <string.h>  #include <rpc/rpc.h>  /* @@ -58,7 +59,7 @@ _svcauth_unix(rqst, msg)  	register enum auth_stat stat;  	XDR xdrs;  	register struct authunix_parms *aup; -	register long *buf; +	register int32_t *buf;  	struct area {  		struct authunix_parms area_aup;  		char area_machname[MAX_MACHINE_NAME+1]; @@ -82,10 +83,10 @@ _svcauth_unix(rqst, msg)  			stat = AUTH_BADCRED;  			goto done;  		} -		bcopy((caddr_t)buf, aup->aup_machname, (u_int)str_len); +		memcpy(aup->aup_machname, (caddr_t)buf, (u_int)str_len);  		aup->aup_machname[str_len] = 0;  		str_len = RNDUP(str_len); -		buf += str_len / sizeof (long); +		buf += str_len / sizeof (int32_t);  		aup->aup_uid = IXDR_GET_LONG(buf);  		aup->aup_gid = IXDR_GET_LONG(buf);  		gid_len = IXDR_GET_U_LONG(buf); @@ -113,8 +114,19 @@ _svcauth_unix(rqst, msg)  		stat = AUTH_BADCRED;  		goto done;  	} -	rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; -	rqst->rq_xprt->xp_verf.oa_length = 0; + +	/* get the verifier */ +	if ((u_int)msg->rm_call.cb_verf.oa_length) { +		rqst->rq_xprt->xp_verf.oa_flavor =  +			msg->rm_call.cb_verf.oa_flavor; +		rqst->rq_xprt->xp_verf.oa_base =  +			msg->rm_call.cb_verf.oa_base; +		rqst->rq_xprt->xp_verf.oa_length =  +			msg->rm_call.cb_verf.oa_length; +	} else { +		rqst->rq_xprt->xp_verf.oa_flavor = AUTH_NULL; +		rqst->rq_xprt->xp_verf.oa_length = 0; +	}  	stat = AUTH_OK;  done:  	XDR_DESTROY(&xdrs); @@ -127,7 +139,7 @@ done:   * Looks up longhand in a cache.   */  /*ARGSUSED*/ -enum auth_stat  +enum auth_stat  _svcauth_short(rqst, msg)  	struct svc_req *rqst;  	struct rpc_msg *msg; diff --git a/lib/libc/rpc/svc_raw.c b/lib/libc/rpc/svc_raw.c index e34ea9e32608..3a5bcb3cf47c 100644 --- a/lib/libc/rpc/svc_raw.c +++ b/lib/libc/rpc/svc_raw.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc_raw.c 1.15 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc_raw.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_raw.c,v 1.1 1993/10/27 05:40:59 paul Exp $"; +static char *rcsid = "$Id: svc_raw.c,v 1.3 1995/10/22 14:51:36 phk Exp $";  #endif  /* @@ -43,7 +43,7 @@ static char *rcsid = "$Id: svc_raw.c,v 1.1 1993/10/27 05:40:59 paul Exp $";   */  #include <rpc/rpc.h> - +#include <stdlib.h>  /*   * This is the "network" that we will be moving data over @@ -151,7 +151,7 @@ svcraw_freeargs(xprt, xdr_args, args_ptr)  	SVCXPRT *xprt;  	xdrproc_t xdr_args;  	caddr_t args_ptr; -{  +{  	register struct svcraw_private *srp = svcraw_private;  	register XDR *xdrs; @@ -160,7 +160,7 @@ svcraw_freeargs(xprt, xdr_args, args_ptr)  	xdrs = &srp->xdr_stream;  	xdrs->x_op = XDR_FREE;  	return ((*xdr_args)(xdrs, args_ptr)); -}  +}  static void  svcraw_destroy() diff --git a/lib/libc/rpc/svc_run.c b/lib/libc/rpc/svc_run.c index 52fddf226382..896aa124a9ad 100644 --- a/lib/libc/rpc/svc_run.c +++ b/lib/libc/rpc/svc_run.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc_run.c 1.1 87/10/13 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc_run.c	2.1 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_run.c,v 1.1 1993/10/27 05:41:00 paul Exp $"; +static char *rcsid = "$Id: svc_run.c,v 1.4 1996/12/30 15:14:29 peter Exp $";  #endif  /* @@ -38,36 +38,50 @@ static char *rcsid = "$Id: svc_run.c,v 1.1 1993/10/27 05:41:00 paul Exp $";   * Wait for input, call server program.   */  #include <rpc/rpc.h> +#include <stdio.h>  #include <sys/errno.h> +#include <sys/types.h> +#include <sys/time.h> +#include <unistd.h> +#include <stdlib.h> +#include <string.h> + +extern int __svc_fdsetsize; +extern fd_set *__svc_fdset;  void  svc_run()  { -#ifdef FD_SETSIZE -	fd_set readfds; -#else -      int readfds; -#endif /* def FD_SETSIZE */ -	extern int errno; +	fd_set *fds;  	for (;;) { -#ifdef FD_SETSIZE -		readfds = svc_fdset; -#else -		readfds = svc_fds; -#endif /* def FD_SETSIZE */ -		switch (select(_rpc_dtablesize(), &readfds, (int *)0, (int *)0, -			       (struct timeval *)0)) { +		if (__svc_fdset) { +			int bytes = howmany(__svc_fdsetsize, NFDBITS) * +				sizeof(fd_mask); +			fds = (fd_set *)malloc(bytes); +			memcpy(fds, __svc_fdset, bytes); +		} else +			fds = NULL; +		switch (select(svc_maxfd + 1, fds, NULL, NULL, +				(struct timeval *)0)) {  		case -1:  			if (errno == EINTR) { +				if (fds) +					free(fds);  				continue;  			}  			perror("svc_run: - select failed"); +			if (fds) +				free(fds);  			return;  		case 0: +			if (fds) +				free(fds);  			continue;  		default: -			svc_getreqset(&readfds); +			/* XXX What the hell?? what if fds == NULL?? */ +			svc_getreqset2(fds, svc_maxfd + 1); +			free(fds);  		}  	}  } diff --git a/lib/libc/rpc/svc_simple.c b/lib/libc/rpc/svc_simple.c index eacf859f5ca9..032467568ec5 100644 --- a/lib/libc/rpc/svc_simple.c +++ b/lib/libc/rpc/svc_simple.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,10 +30,10 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc_simple.c 1.18 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc_simple.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_simple.c,v 1.1 1993/10/27 05:41:01 paul Exp $"; +static char *rcsid = "$Id: svc_simple.c,v 1.5 1996/12/30 15:16:22 peter Exp $";  #endif -/*  +/*   * svc_simple.c   * Simplified front end to rpc.   * @@ -41,7 +41,10 @@ static char *rcsid = "$Id: svc_simple.c,v 1.1 1993/10/27 05:41:01 paul Exp $";   */  #include <stdio.h> +#include <stdlib.h> +#include <string.h>  #include <rpc/rpc.h> +#include <rpc/pmap_clnt.h>  #include <sys/socket.h>  #include <netdb.h> @@ -56,14 +59,16 @@ static void universal();  static SVCXPRT *transp;  struct proglst *pl; +int  registerrpc(prognum, versnum, procnum, progname, inproc, outproc) +	int prognum, versnum, procnum;  	char *(*progname)();  	xdrproc_t inproc, outproc;  { -	 +  	if (procnum == NULLPROC) {  		(void) fprintf(stderr, -		    "can't reassign procedure number %d\n", NULLPROC); +		    "can't reassign procedure number %ld\n", NULLPROC);  		return (-1);  	}  	if (transp == 0) { @@ -74,7 +79,7 @@ registerrpc(prognum, versnum, procnum, progname, inproc, outproc)  		}  	}  	(void) pmap_unset((u_long)prognum, (u_long)versnum); -	if (!svc_register(transp, (u_long)prognum, (u_long)versnum,  +	if (!svc_register(transp, (u_long)prognum, (u_long)versnum,  	    universal, IPPROTO_UDP)) {  	    	(void) fprintf(stderr, "couldn't register prog %d vers %d\n",  		    prognum, versnum); @@ -105,11 +110,11 @@ universal(rqstp, transp)  	char xdrbuf[UDPMSGSIZE];  	struct proglst *pl; -	/*  +	/*  	 * enforce "procnum 0 is echo" convention  	 */  	if (rqstp->rq_proc == NULLPROC) { -		if (svc_sendreply(transp, xdr_void, (char *)NULL) == FALSE) { +		if (svc_sendreply(transp, xdr_void, NULL) == FALSE) {  			(void) fprintf(stderr, "xxx\n");  			exit(1);  		} @@ -120,7 +125,7 @@ universal(rqstp, transp)  	for (pl = proglst; pl != NULL; pl = pl->p_nxt)  		if (pl->p_prognum == prog && pl->p_procnum == proc) {  			/* decode arguments into a CLEAN buffer */ -			bzero(xdrbuf, sizeof(xdrbuf)); /* required ! */ +			memset(xdrbuf, 0, sizeof(xdrbuf)); /* required ! */  			if (!svc_getargs(transp, pl->p_inproc, xdrbuf)) {  				svcerr_decode(transp);  				return; diff --git a/lib/libc/rpc/svc_tcp.c b/lib/libc/rpc/svc_tcp.c index 9d19504858fb..1387ee126620 100644 --- a/lib/libc/rpc/svc_tcp.c +++ b/lib/libc/rpc/svc_tcp.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,11 +30,11 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc_tcp.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc_tcp.c	2.2 88/08/01 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_tcp.c,v 1.1 1993/10/27 05:41:02 paul Exp $"; +static char *rcsid = "$Id: svc_tcp.c,v 1.8 1996/12/30 15:19:08 peter Exp $";  #endif  /* - * svc_tcp.c, Server side for TCP/IP based RPC.  + * svc_tcp.c, Server side for TCP/IP based RPC.   *   * Copyright (C) 1984, Sun Microsystems, Inc.   * @@ -44,11 +44,12 @@ static char *rcsid = "$Id: svc_tcp.c,v 1.1 1993/10/27 05:41:02 paul Exp $";   */  #include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h>  #include <rpc/rpc.h>  #include <sys/socket.h>  #include <errno.h> -extern bool_t abort(); -extern errno;  /*   * Ops vector for TCP/IP based rpc service handle @@ -78,9 +79,9 @@ static enum xprt_stat	rendezvous_stat();  static struct xp_ops svctcp_rendezvous_op = {  	rendezvous_request,  	rendezvous_stat, -	abort, -	abort, -	abort, +	(bool_t (*)())abort, +	(bool_t (*)())abort, +	(bool_t (*)())abort,  	svctcp_destroy  }; @@ -138,7 +139,8 @@ svctcp_create(sock, sendsize, recvsize)  		}  		madesock = TRUE;  	} -	bzero((char *)&addr, sizeof (addr)); +	memset(&addr, 0, sizeof (addr)); +	addr.sin_len = sizeof(struct sockaddr_in);  	addr.sin_family = AF_INET;  	if (bindresvport(sock, &addr)) {  		addr.sin_port = 0; @@ -195,7 +197,7 @@ makefd_xprt(fd, sendsize, recvsize)  {  	register SVCXPRT *xprt;  	register struct tcp_conn *cd; -  +  	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT));  	if (xprt == (SVCXPRT *)NULL) {  		(void) fprintf(stderr, "svc_tcp: makefd_xprt: out of memory\n"); @@ -242,6 +244,14 @@ rendezvous_request(xprt)  	       return (FALSE);  	}  	/* +	 * XXX careful for ftp bounce attacks. If discovered, close the +	 * socket and look for another connection. +	 */ +	if (addr.sin_port == htons(20)) { +		close(sock); +		goto again; +	} +	/*  	 * make a new transporter (re-uses xprt)  	 */  	xprt = makefd_xprt(sock, r->sendsize, r->recvsize); @@ -294,35 +304,52 @@ readtcp(xprt, buf, len)  	register int len;  {  	register int sock = xprt->xp_sock; -#ifdef FD_SETSIZE -	fd_set mask; -	fd_set readfds; - -	FD_ZERO(&mask); -	FD_SET(sock, &mask); -#else -	register int mask = 1 << sock; -	int readfds; -#endif /* def FD_SETSIZE */ +	struct timeval start, delta, tv; +	struct timeval tmp1, tmp2; +	fd_set *fds, readfds; + +	if (sock + 1 > FD_SETSIZE) { +		int bytes = howmany(sock+1, NFDBITS) * sizeof(fd_mask); +		fds = (fd_set *)malloc(bytes); + +		if (fds == NULL) +			goto fatal_err; +		memset(fds, 0, bytes); +	} else { +		fds = &readfds; +		FD_ZERO(fds); +	} + +	delta = wait_per_try; +	gettimeofday(&start, NULL);  	do { -		readfds = mask; -		if (select(_rpc_dtablesize(), &readfds, (int*)NULL, (int*)NULL,  -			   &wait_per_try) <= 0) { -			if (errno == EINTR) { -				continue; -			} +		/* XXX we know the other bits are still clear */ +		FD_SET(sock, fds); +		tv = delta;	/* in case select() implements writeback */ +		switch (select(sock + 1, fds, NULL, NULL, &tv)) { +		case -1: +			if (errno != EINTR) +				goto fatal_err; +			gettimeofday(&tmp1, NULL); +			timersub(&tmp1, &start, &tmp2); +			timersub(&delta, &tmp2, &tmp1); +			if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) +				goto fatal_err; +			delta = tmp1; +			continue; +		case 0:  			goto fatal_err;  		} -#ifdef FD_SETSIZE -	} while (!FD_ISSET(sock, &readfds)); -#else -	} while (readfds != mask); -#endif /* def FD_SETSIZE */ +	} while (!FD_ISSET(sock, fds));  	if ((len = read(sock, buf, len)) > 0) { +		if (fds != &readfds) +			free(fds);  		return (len);  	}  fatal_err:  	((struct tcp_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; +	if (fds != &readfds) +		free(fds);  	return (-1);  } diff --git a/lib/libc/rpc/svc_udp.c b/lib/libc/rpc/svc_udp.c index d7c7bb2dd825..6622de2871cd 100644 --- a/lib/libc/rpc/svc_udp.c +++ b/lib/libc/rpc/svc_udp.c @@ -5,23 +5,23 @@   * may copy or modify Sun RPC without charge, but are not authorized   * to license or distribute it to anyone else except as part of a product or   * program developed by the user. - *  + *   * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE   * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR   * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. - *  + *   * Sun RPC is provided with no support and without any obligation on the   * part of Sun Microsystems, Inc. to assist in its use, correction,   * modification or enhancement. - *  + *   * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE   * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC   * OR ANY PART THEREOF. - *  + *   * In no event will Sun Microsystems, Inc. be liable for any lost revenue   * or profits or other special, indirect and consequential damages, even if   * Sun has been advised of the possibility of such damages. - *  + *   * Sun Microsystems, Inc.   * 2550 Garcia Avenue   * Mountain View, California  94043 @@ -30,7 +30,7 @@  #if defined(LIBC_SCCS) && !defined(lint)  /*static char *sccsid = "from: @(#)svc_udp.c 1.24 87/08/11 Copyr 1984 Sun Micro";*/  /*static char *sccsid = "from: @(#)svc_udp.c	2.2 88/07/29 4.0 RPCSRC";*/ -static char *rcsid = "$Id: svc_udp.c,v 1.1 1993/10/27 05:41:03 paul Exp $"; +static char *rcsid = "$Id: svc_udp.c,v 1.7 1996/12/30 15:21:19 peter Exp $";  #endif  /* @@ -43,11 +43,12 @@ static char *rcsid = "$Id: svc_udp.c,v 1.1 1993/10/27 05:41:03 paul Exp $";  #include <stdio.h>  #include <stdlib.h> +#include <unistd.h> +#include <string.h>  #include <rpc/rpc.h>  #include <sys/socket.h>  #include <errno.h> -  #define rpc_buffer(xprt) ((xprt)->xp_p1)  #define MAX(a, b)     ((a > b) ? a : b) @@ -57,6 +58,8 @@ static enum xprt_stat	svcudp_stat();  static bool_t		svcudp_getargs();  static bool_t		svcudp_freeargs();  static void		svcudp_destroy(); +static void		cache_set __P((SVCXPRT *, u_long)); +static int		cache_get __P((SVCXPRT *, struct rpc_msg *, char **, u_long *));  static struct xp_ops svcudp_op = {  	svcudp_recv, @@ -67,8 +70,6 @@ static struct xp_ops svcudp_op = {  	svcudp_destroy  }; -extern int errno; -  /*   * kept in xprt->xp_p2   */ @@ -112,7 +113,8 @@ svcudp_bufcreate(sock, sendsz, recvsz)  		}  		madesock = TRUE;  	} -	bzero((char *)&addr, sizeof (addr)); +	memset((char *)&addr, 0, sizeof (addr)); +	addr.sin_len = sizeof(struct sockaddr_in);  	addr.sin_family = AF_INET;  	if (bindresvport(sock, &addr)) {  		addr.sin_port = 0; @@ -164,7 +166,7 @@ svcudp_stat(xprt)  	SVCXPRT *xprt;  { -	return (XPRT_IDLE);  +	return (XPRT_IDLE);  }  static bool_t @@ -177,7 +179,6 @@ svcudp_recv(xprt, msg)  	register int rlen;  	char *reply;  	u_long replylen; -	static int cache_get();      again:  	xprt->xp_addrlen = sizeof(struct sockaddr_in); @@ -185,7 +186,7 @@ svcudp_recv(xprt, msg)  	    0, (struct sockaddr *)&(xprt->xp_raddr), &(xprt->xp_addrlen));  	if (rlen == -1 && errno == EINTR)  		goto again; -	if (rlen < 4*sizeof(u_long)) +	if (rlen == -1 || rlen < 4*sizeof(u_int32_t))  		return (FALSE);  	xdrs->x_op = XDR_DECODE;  	XDR_SETPOS(xdrs, 0); @@ -204,14 +205,13 @@ svcudp_recv(xprt, msg)  static bool_t  svcudp_reply(xprt, msg) -	register SVCXPRT *xprt;  -	struct rpc_msg *msg;  +	register SVCXPRT *xprt; +	struct rpc_msg *msg;  {  	register struct svcudp_data *su = su_data(xprt);  	register XDR *xdrs = &(su->su_xdrs);  	register int slen;  	register bool_t stat = FALSE; -	static void cache_set();  	xdrs->x_op = XDR_ENCODE;  	XDR_SETPOS(xdrs, 0); @@ -284,7 +284,7 @@ svcudp_destroy(xprt)  	(type *) mem_alloc((unsigned) (sizeof(type) * (size)))  #define BZERO(addr, type, size)	 \ -	bzero((char *) addr, sizeof(type) * (int) (size))  +	memset((char *) addr, 0, sizeof(type) * (int) (size))  /*   * An entry in the cache @@ -307,7 +307,7 @@ struct cache_node {  	/*   	 * Next node on the list, if there is a collision  	 */ -	cache_ptr cache_next;	 +	cache_ptr cache_next;  }; @@ -331,14 +331,14 @@ struct udp_cache {   * the hashing function   */  #define CACHE_LOC(transp, xid)	\ - (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))	 + (xid % (SPARSENESS*((struct udp_cache *) su_data(transp)->su_cache)->uc_size))  /* - * Enable use of the cache.  + * Enable use of the cache.   * Note: there is no disable.   */ -svcudp_enablecache(transp, size) +int svcudp_enablecache(transp, size)  	SVCXPRT *transp;  	u_long size;  { @@ -347,7 +347,7 @@ svcudp_enablecache(transp, size)  	if (su->su_cache != NULL) {  		CACHE_PERROR("enablecache: cache already enabled"); -		return(0);	 +		return(0);  	}  	uc = ALLOC(struct udp_cache, 1);  	if (uc == NULL) { @@ -379,9 +379,9 @@ svcudp_enablecache(transp, size)  static void  cache_set(xprt, replylen)  	SVCXPRT *xprt; -	u_long replylen;	 +	u_long replylen;  { -	register cache_ptr victim;	 +	register cache_ptr victim;  	register cache_ptr *vicp;  	register struct svcudp_data *su = su_data(xprt);  	struct udp_cache *uc = (struct udp_cache *) su->su_cache; @@ -395,9 +395,9 @@ cache_set(xprt, replylen)  	victim = uc->uc_fifo[uc->uc_nextvictim];  	if (victim != NULL) {  		loc = CACHE_LOC(xprt, victim->cache_xid); -		for (vicp = &uc->uc_entries[loc];  -		  *vicp != NULL && *vicp != victim;  -		  vicp = &(*vicp)->cache_next)  +		for (vicp = &uc->uc_entries[loc]; +		  *vicp != NULL && *vicp != victim; +		  vicp = &(*vicp)->cache_next)  				;  		if (*vicp == NULL) {  			CACHE_PERROR("cache_set: victim not found"); @@ -431,7 +431,7 @@ cache_set(xprt, replylen)  	victim->cache_prog = uc->uc_prog;  	victim->cache_addr = uc->uc_addr;  	loc = CACHE_LOC(xprt, victim->cache_xid); -	victim->cache_next = uc->uc_entries[loc];	 +	victim->cache_next = uc->uc_entries[loc];  	uc->uc_entries[loc] = victim;  	uc->uc_fifo[uc->uc_nextvictim++] = victim;  	uc->uc_nextvictim %= uc->uc_size; @@ -441,7 +441,7 @@ cache_set(xprt, replylen)   * Try to get an entry from the cache   * return 1 if found, 0 if not found   */ -static +static int  cache_get(xprt, msg, replyp, replylenp)  	SVCXPRT *xprt;  	struct rpc_msg *msg; @@ -453,7 +453,7 @@ cache_get(xprt, msg, replyp, replylenp)  	register struct svcudp_data *su = su_data(xprt);  	register struct udp_cache *uc = (struct udp_cache *) su->su_cache; -#	define EQADDR(a1, a2)	(bcmp((char*)&a1, (char*)&a2, sizeof(a1)) == 0) +#	define EQADDR(a1, a2)	(memcmp(&a1, &a2, sizeof(a1)) == 0)  	loc = CACHE_LOC(xprt, su->su_xid);  	for (ent = uc->uc_entries[loc]; ent != NULL; ent = ent->cache_next) { diff --git a/lib/libc/rpc/svc_unix.c b/lib/libc/rpc/svc_unix.c new file mode 100644 index 000000000000..04e3223d2eeb --- /dev/null +++ b/lib/libc/rpc/svc_unix.c @@ -0,0 +1,511 @@ +/* + * Sun RPC is a product of Sun Microsystems, Inc. and is provided for + * unrestricted use provided that this legend is included on all tape + * media and as a part of the software program in whole or part.  Users + * may copy or modify Sun RPC without charge, but are not authorized + * to license or distribute it to anyone else except as part of a product or + * program developed by the user. + * + * SUN RPC IS PROVIDED AS IS WITH NO WARRANTIES OF ANY KIND INCLUDING THE + * WARRANTIES OF DESIGN, MERCHANTIBILITY AND FITNESS FOR A PARTICULAR + * PURPOSE, OR ARISING FROM A COURSE OF DEALING, USAGE OR TRADE PRACTICE. + * + * Sun RPC is provided with no support and without any obligation on the + * part of Sun Microsystems, Inc. to assist in its use, correction, + * modification or enhancement. + * + * SUN MICROSYSTEMS, INC. SHALL HAVE NO LIABILITY WITH RESPECT TO THE + * INFRINGEMENT OF COPYRIGHTS, TRADE SECRETS OR ANY PATENTS BY SUN RPC + * OR ANY PART THEREOF. + * + * In no event will Sun Microsystems, Inc. be liable for any lost revenue + * or profits or other special, indirect and consequential damages, even if + * Sun has been advised of the possibility of such damages. + * + * Sun Microsystems, Inc. + * 2550 Garcia Avenue + * Mountain View, California  94043 + */ + +#if defined(LIBC_SCCS) && !defined(lint) +/*static char *sccsid = "from: @(#)svc_unix.c 1.21 87/08/11 Copyr 1984 Sun Micro";*/ +/*static char *sccsid = "from: @(#)svc_unix.c	2.2 88/08/01 4.0 RPCSRC";*/ +static char *rcsid = "$Id: svc_unix.c,v 1.8 1996/12/30 15:19:08 peter Exp $"; +#endif + +/* + * svc_unix.c, Server side for TCP/IP based RPC. + * + * Copyright (C) 1984, Sun Microsystems, Inc. + * + * Actually implements two flavors of transporter - + * a unix rendezvouser (a listner and connection establisher) + * and a record/unix stream. + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <rpc/rpc.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <sys/uio.h> +#include <errno.h> + +/* + * Ops vector for AF_UNIX based rpc service handle + */ +static bool_t		svcunix_recv(); +static enum xprt_stat	svcunix_stat(); +static bool_t		svcunix_getargs(); +static bool_t		svcunix_reply(); +static bool_t		svcunix_freeargs(); +static void		svcunix_destroy(); + +static struct xp_ops svcunix_op = { +	svcunix_recv, +	svcunix_stat, +	svcunix_getargs, +	svcunix_reply, +	svcunix_freeargs, +	svcunix_destroy +}; + +/* + * Ops vector for TCP/IP rendezvous handler + */ +static bool_t		rendezvous_request(); +static enum xprt_stat	rendezvous_stat(); + +static struct xp_ops svcunix_rendezvous_op = { +	rendezvous_request, +	rendezvous_stat, +	(bool_t (*)())abort, +	(bool_t (*)())abort, +	(bool_t (*)())abort, +	svcunix_destroy +}; + +static int readunix(), writeunix(); +static SVCXPRT *makefd_xprt(); + +struct unix_rendezvous { /* kept in xprt->xp_p1 */ +	u_int sendsize; +	u_int recvsize; +}; + +struct unix_conn {  /* kept in xprt->xp_p1 */ +	enum xprt_stat strm_stat; +	u_long x_id; +	XDR xdrs; +	char verf_body[MAX_AUTH_BYTES]; +}; + + +struct cmessage { +	struct cmsghdr cmsg; +	struct cmsgcred cmcred; +}; + +static struct cmessage cm; + +static int __msgread(sock, buf, cnt) +	int sock; +	void *buf; +	size_t cnt; +{ +	struct iovec iov[1]; +	struct msghdr msg; + +	bzero((char *)&cm, sizeof(cm)); +	iov[0].iov_base = buf; +	iov[0].iov_len = cnt; + +	msg.msg_iov = iov; +	msg.msg_iovlen = 1; +	msg.msg_name = NULL; +	msg.msg_namelen = 0; +	msg.msg_control = (caddr_t)&cm; +	msg.msg_controllen = sizeof(struct cmessage); +	msg.msg_flags = 0; + +	return(recvmsg(sock, &msg, 0)); +} + +static int __msgwrite(sock, buf, cnt) +	int sock; +	void *buf; +	size_t cnt; +{ +	struct iovec iov[1]; +	struct msghdr msg; + +	bzero((char *)&cm, sizeof(cm)); +	iov[0].iov_base = buf; +	iov[0].iov_len = cnt; + +	cm.cmsg.cmsg_type = SCM_CREDS; +	cm.cmsg.cmsg_level = SOL_SOCKET; +	cm.cmsg.cmsg_len = sizeof(struct cmessage); + +	msg.msg_iov = iov; +	msg.msg_iovlen = 1; +	msg.msg_name = NULL; +	msg.msg_namelen = 0; +	msg.msg_control = (caddr_t)&cm; +	msg.msg_controllen = sizeof(struct cmessage); +	msg.msg_flags = 0; + +	return(sendmsg(sock, &msg, 0)); +} + +/* + * Usage: + *	xprt = svcunix_create(sock, send_buf_size, recv_buf_size); + * + * Creates, registers, and returns a (rpc) unix based transporter. + * Once *xprt is initialized, it is registered as a transporter + * see (svc.h, xprt_register).  This routine returns + * a NULL if a problem occurred. + * + * If sock<0 then a socket is created, else sock is used. + * If the socket, sock is not bound to a port then svcunix_create + * binds it to an arbitrary port.  The routine then starts a unix + * listener on the socket's associated port.  In any (successful) case, + * xprt->xp_sock is the registered socket number and xprt->xp_port is the + * associated port number. + * + * Since unix streams do buffered io similar to stdio, the caller can specify + * how big the send and receive buffers are via the second and third parms; + * 0 => use the system default. + */ +SVCXPRT * +svcunix_create(sock, sendsize, recvsize, path) +	register int sock; +	u_int sendsize; +	u_int recvsize; +	char *path; +{ +	bool_t madesock = FALSE; +	register SVCXPRT *xprt; +	register struct unix_rendezvous *r; +	struct sockaddr_un addr; +	int len = sizeof(struct sockaddr_un); + +	if (sock == RPC_ANYSOCK) { +		if ((sock = socket(AF_UNIX, SOCK_STREAM, 0)) < 0) { +			perror("svc_unix.c - AF_UNIX socket creation problem"); +			return ((SVCXPRT *)NULL); +		} +		madesock = TRUE; +	} +	memset(&addr, 0, sizeof (addr)); +	addr.sun_family = AF_UNIX; +	strcpy(addr.sun_path, path); +	len = strlen(addr.sun_path) + sizeof(addr.sun_family) + +		sizeof(addr.sun_len) + 1; +	addr.sun_len = len; + +	bind(sock, (struct sockaddr *)&addr, len); + +	if ((getsockname(sock, (struct sockaddr *)&addr, &len) != 0)  || +	    (listen(sock, 2) != 0)) { +		perror("svc_unix.c - cannot getsockname or listen"); +		if (madesock) +		       (void)close(sock); +		return ((SVCXPRT *)NULL); +	} +	r = (struct unix_rendezvous *)mem_alloc(sizeof(*r)); +	if (r == NULL) { +		(void) fprintf(stderr, "svcunix_create: out of memory\n"); +		return (NULL); +	} +	r->sendsize = sendsize; +	r->recvsize = recvsize; +	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); +	if (xprt == NULL) { +		(void) fprintf(stderr, "svcunix_create: out of memory\n"); +		return (NULL); +	} +	xprt->xp_p2 = NULL; +	xprt->xp_p1 = (caddr_t)r; +	xprt->xp_verf = _null_auth; +	xprt->xp_ops = &svcunix_rendezvous_op; +	xprt->xp_port = -1 /*ntohs(addr.sin_port)*/; +	xprt->xp_sock = sock; +	xprt_register(xprt); +	return (xprt); +} + +/* + * Like svunix_create(), except the routine takes any *open* UNIX file + * descriptor as its first input. + */ +SVCXPRT * +svcunixfd_create(fd, sendsize, recvsize) +	int fd; +	u_int sendsize; +	u_int recvsize; +{ + +	return (makefd_xprt(fd, sendsize, recvsize)); +} + +static SVCXPRT * +makefd_xprt(fd, sendsize, recvsize) +	int fd; +	u_int sendsize; +	u_int recvsize; +{ +	register SVCXPRT *xprt; +	register struct unix_conn *cd; + +	xprt = (SVCXPRT *)mem_alloc(sizeof(SVCXPRT)); +	if (xprt == (SVCXPRT *)NULL) { +		(void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n"); +		goto done; +	} +	cd = (struct unix_conn *)mem_alloc(sizeof(struct unix_conn)); +	if (cd == (struct unix_conn *)NULL) { +		(void) fprintf(stderr, "svc_unix: makefd_xprt: out of memory\n"); +		mem_free((char *) xprt, sizeof(SVCXPRT)); +		xprt = (SVCXPRT *)NULL; +		goto done; +	} +	cd->strm_stat = XPRT_IDLE; +	xdrrec_create(&(cd->xdrs), sendsize, recvsize, +	    (caddr_t)xprt, readunix, writeunix); +	xprt->xp_p2 = NULL; +	xprt->xp_p1 = (caddr_t)cd; +	xprt->xp_verf.oa_base = cd->verf_body; +	xprt->xp_addrlen = 0; +	xprt->xp_ops = &svcunix_op;  /* truely deals with calls */ +	xprt->xp_port = 0;  /* this is a connection, not a rendezvouser */ +	xprt->xp_sock = fd; +	xprt_register(xprt); +    done: +	return (xprt); +} + +static bool_t +rendezvous_request(xprt) +	register SVCXPRT *xprt; +{ +	int sock; +	struct unix_rendezvous *r; +	struct sockaddr_un addr; +	struct sockaddr_in in_addr; +	int len; + +	r = (struct unix_rendezvous *)xprt->xp_p1; +    again: +	len = sizeof(struct sockaddr_in); +	if ((sock = accept(xprt->xp_sock, (struct sockaddr *)&addr, +	    &len)) < 0) { +		if (errno == EINTR) +			goto again; +	       return (FALSE); +	} + +	/* +	 * make a new transporter (re-uses xprt) +	 */ +	bzero((char *)&in_addr, sizeof(in_addr)); +	in_addr.sin_family = AF_UNIX; +	xprt = makefd_xprt(sock, r->sendsize, r->recvsize); +	xprt->xp_raddr = in_addr; +	xprt->xp_addrlen = len; +	return (FALSE); /* there is never an rpc msg to be processed */ +} + +static enum xprt_stat +rendezvous_stat() +{ + +	return (XPRT_IDLE); +} + +static void +svcunix_destroy(xprt) +	register SVCXPRT *xprt; +{ +	register struct unix_conn *cd = (struct unix_conn *)xprt->xp_p1; + +	xprt_unregister(xprt); +	(void)close(xprt->xp_sock); +	if (xprt->xp_port != 0) { +		/* a rendezvouser socket */ +		xprt->xp_port = 0; +	} else { +		/* an actual connection socket */ +		XDR_DESTROY(&(cd->xdrs)); +	} +	mem_free((caddr_t)cd, sizeof(struct unix_conn)); +	mem_free((caddr_t)xprt, sizeof(SVCXPRT)); +} + +/* + * All read operations timeout after 35 seconds. + * A timeout is fatal for the connection. + */ +static struct timeval wait_per_try = { 35, 0 }; + +/* + * reads data from the unix conection. + * any error is fatal and the connection is closed. + * (And a read of zero bytes is a half closed stream => error.) + */ +static int +readunix(xprt, buf, len) +	register SVCXPRT *xprt; +	caddr_t buf; +	register int len; +{ +	register int sock = xprt->xp_sock; +	struct timeval start, delta, tv; +	struct timeval tmp1, tmp2; +	fd_set *fds, readfds; + +	if (sock + 1 > FD_SETSIZE) { +		int bytes = howmany(sock+1, NFDBITS) * sizeof(fd_mask); +		fds = (fd_set *)malloc(bytes); + +		if (fds == NULL) +			goto fatal_err; +		memset(fds, 0, bytes); +	} else { +		fds = &readfds; +		FD_ZERO(fds); +	} + +	delta = wait_per_try; +	gettimeofday(&start, NULL); +	do { +		/* XXX we know the other bits are still clear */ +		FD_SET(sock, fds); +		tv = delta;	/* in case select() implements writeback */ +		switch (select(sock + 1, fds, NULL, NULL, &tv)) { +		case -1: +			if (errno != EINTR) +				goto fatal_err; +			gettimeofday(&tmp1, NULL); +			timersub(&tmp1, &start, &tmp2); +			timersub(&delta, &tmp2, &tmp1); +			if (tmp1.tv_sec < 0 || !timerisset(&tmp1)) +				goto fatal_err; +			delta = tmp1; +			continue; +		case 0: +			goto fatal_err; +		} +	} while (!FD_ISSET(sock, fds)); +	if ((len = __msgread(sock, buf, len)) > 0) { +		if (fds != &readfds) +			free(fds); +		return (len); +	} +fatal_err: +	((struct unix_conn *)(xprt->xp_p1))->strm_stat = XPRT_DIED; +	if (fds != &readfds) +		free(fds); +	return (-1); +} + +/* + * writes data to the unix connection. + * Any error is fatal and the connection is closed. + */ +static int +writeunix(xprt, buf, len) +	register SVCXPRT *xprt; +	caddr_t buf; +	int len; +{ +	register int i, cnt; + +	for (cnt = len; cnt > 0; cnt -= i, buf += i) { +		if ((i = __msgwrite(xprt->xp_sock, buf, cnt)) < 0) { +			((struct unix_conn *)(xprt->xp_p1))->strm_stat = +			    XPRT_DIED; +			return (-1); +		} +	} +	return (len); +} + +static enum xprt_stat +svcunix_stat(xprt) +	SVCXPRT *xprt; +{ +	register struct unix_conn *cd = +	    (struct unix_conn *)(xprt->xp_p1); + +	if (cd->strm_stat == XPRT_DIED) +		return (XPRT_DIED); +	if (! xdrrec_eof(&(cd->xdrs))) +		return (XPRT_MOREREQS); +	return (XPRT_IDLE); +} + +static bool_t +svcunix_recv(xprt, msg) +	SVCXPRT *xprt; +	register struct rpc_msg *msg; +{ +	register struct unix_conn *cd = +	    (struct unix_conn *)(xprt->xp_p1); +	register XDR *xdrs = &(cd->xdrs); + +	xdrs->x_op = XDR_DECODE; +	(void)xdrrec_skiprecord(xdrs); +	if (xdr_callmsg(xdrs, msg)) { +		cd->x_id = msg->rm_xid; +		/* set up verifiers */ +		msg->rm_call.cb_verf.oa_flavor = AUTH_UNIX; +		msg->rm_call.cb_verf.oa_base = (caddr_t)&cm; +		msg->rm_call.cb_verf.oa_length = sizeof(cm); +		return (TRUE); +	} +	return (FALSE); +} + +static bool_t +svcunix_getargs(xprt, xdr_args, args_ptr) +	SVCXPRT *xprt; +	xdrproc_t xdr_args; +	caddr_t args_ptr; +{ + +	return ((*xdr_args)(&(((struct unix_conn *)(xprt->xp_p1))->xdrs), args_ptr)); +} + +static bool_t +svcunix_freeargs(xprt, xdr_args, args_ptr) +	SVCXPRT *xprt; +	xdrproc_t xdr_args; +	caddr_t args_ptr; +{ +	register XDR *xdrs = +	    &(((struct unix_conn *)(xprt->xp_p1))->xdrs); + +	xdrs->x_op = XDR_FREE; +	return ((*xdr_args)(xdrs, args_ptr)); +} + +static bool_t +svcunix_reply(xprt, msg) +	SVCXPRT *xprt; +	register struct rpc_msg *msg; +{ +	register struct unix_conn *cd = +	    (struct unix_conn *)(xprt->xp_p1); +	register XDR *xdrs = &(cd->xdrs); +	register bool_t stat; + +	xdrs->x_op = XDR_ENCODE; +	msg->rm_xid = cd->x_id; +	stat = xdr_replymsg(xdrs, msg); +	(void)xdrrec_endofrecord(xdrs, TRUE); +	return (stat); +} | 
