From dc98dc5095c7f08ae4bf0adbe87e9de8e7586d19 Mon Sep 17 00:00:00 2001 From: wpaul Date: Wed, 28 May 1997 05:00:11 +0000 Subject: Now the biggest step: import the changes to the main RPC code. Note: you'll need to rinstalkl all your includes before compiling libc the next time you update your sources in order for all this to work. Reviewed by: Mark Murray --- dist/lib/libc/rpc/Makefile.inc | 117 +++++-- dist/lib/libc/rpc/auth_des.c | 554 ++++++++++++++++++++++++++++++++ dist/lib/libc/rpc/auth_none.c | 23 +- dist/lib/libc/rpc/auth_time.c | 500 +++++++++++++++++++++++++++++ dist/lib/libc/rpc/auth_unix.c | 59 +++- dist/lib/libc/rpc/authdes_prot.c | 82 +++++ dist/lib/libc/rpc/authunix_prot.c | 12 +- dist/lib/libc/rpc/bindresvport.3 | 41 +-- dist/lib/libc/rpc/bindresvport.c | 75 +++-- dist/lib/libc/rpc/clnt_generic.c | 48 ++- dist/lib/libc/rpc/clnt_perror.c | 193 +++++------ dist/lib/libc/rpc/clnt_raw.c | 18 +- dist/lib/libc/rpc/clnt_simple.c | 31 +- dist/lib/libc/rpc/clnt_tcp.c | 178 +++++++++-- dist/lib/libc/rpc/clnt_udp.c | 239 ++++++++++---- dist/lib/libc/rpc/clnt_unix.c | 635 +++++++++++++++++++++++++++++++++++++ dist/lib/libc/rpc/crypt_client.c | 89 ++++++ dist/lib/libc/rpc/des_crypt.3 | 126 ++++++++ dist/lib/libc/rpc/des_crypt.c | 153 +++++++++ dist/lib/libc/rpc/des_soft.c | 67 ++++ dist/lib/libc/rpc/get_myaddress.c | 60 ++-- dist/lib/libc/rpc/getrpcent.3 | 147 ++++----- dist/lib/libc/rpc/getrpcent.c | 35 +- dist/lib/libc/rpc/getrpcport.3 | 38 ++- dist/lib/libc/rpc/getrpcport.c | 20 +- dist/lib/libc/rpc/key_call.c | 425 +++++++++++++++++++++++++ dist/lib/libc/rpc/key_prot_xdr.c | 166 ++++++++++ dist/lib/libc/rpc/netname.c | 136 ++++++++ dist/lib/libc/rpc/netnamer.c | 326 +++++++++++++++++++ dist/lib/libc/rpc/pmap_clnt.c | 60 +++- dist/lib/libc/rpc/pmap_getmaps.c | 18 +- dist/lib/libc/rpc/pmap_getport.c | 16 +- dist/lib/libc/rpc/pmap_prot.c | 16 +- dist/lib/libc/rpc/pmap_prot2.c | 26 +- dist/lib/libc/rpc/pmap_rmt.c | 112 ++++--- dist/lib/libc/rpc/publickey.3 | 44 +++ dist/lib/libc/rpc/publickey.5 | 37 +++ dist/lib/libc/rpc/rpc.3 | 30 +- dist/lib/libc/rpc/rpc.5 | 81 ++--- dist/lib/libc/rpc/rpc_callmsg.c | 43 +-- dist/lib/libc/rpc/rpc_commondata.c | 19 +- dist/lib/libc/rpc/rpc_dtablesize.c | 29 +- dist/lib/libc/rpc/rpc_prot.c | 44 +-- dist/lib/libc/rpc/rpc_secure.3 | 330 +++++++++++++++++++ dist/lib/libc/rpc/rpcdname.c | 77 +++++ dist/lib/libc/rpc/rstat.1 | 10 +- dist/lib/libc/rpc/rstat_svc.8 | 6 +- dist/lib/libc/rpc/rtime.3 | 43 +++ dist/lib/libc/rpc/rtime.c | 157 +++++++++ dist/lib/libc/rpc/svc.c | 189 ++++++----- dist/lib/libc/rpc/svc_auth.c | 158 +++++++-- dist/lib/libc/rpc/svc_auth_des.c | 531 +++++++++++++++++++++++++++++++ dist/lib/libc/rpc/svc_auth_unix.c | 36 ++- dist/lib/libc/rpc/svc_raw.c | 18 +- dist/lib/libc/rpc/svc_run.c | 54 ++-- dist/lib/libc/rpc/svc_simple.c | 31 +- dist/lib/libc/rpc/svc_tcp.c | 97 ++++-- dist/lib/libc/rpc/svc_udp.c | 60 ++-- dist/lib/libc/rpc/svc_unix.c | 511 +++++++++++++++++++++++++++++ 59 files changed, 6508 insertions(+), 968 deletions(-) create mode 100644 dist/lib/libc/rpc/auth_des.c create mode 100644 dist/lib/libc/rpc/auth_time.c create mode 100644 dist/lib/libc/rpc/authdes_prot.c create mode 100644 dist/lib/libc/rpc/clnt_unix.c create mode 100644 dist/lib/libc/rpc/crypt_client.c create mode 100644 dist/lib/libc/rpc/des_crypt.3 create mode 100644 dist/lib/libc/rpc/des_crypt.c create mode 100644 dist/lib/libc/rpc/des_soft.c create mode 100644 dist/lib/libc/rpc/key_call.c create mode 100644 dist/lib/libc/rpc/key_prot_xdr.c create mode 100644 dist/lib/libc/rpc/netname.c create mode 100644 dist/lib/libc/rpc/netnamer.c create mode 100644 dist/lib/libc/rpc/publickey.3 create mode 100644 dist/lib/libc/rpc/publickey.5 create mode 100644 dist/lib/libc/rpc/rpc_secure.3 create mode 100644 dist/lib/libc/rpc/rpcdname.c create mode 100644 dist/lib/libc/rpc/rtime.3 create mode 100644 dist/lib/libc/rpc/rtime.c create mode 100644 dist/lib/libc/rpc/svc_auth_des.c create mode 100644 dist/lib/libc/rpc/svc_unix.c diff --git a/dist/lib/libc/rpc/Makefile.inc b/dist/lib/libc/rpc/Makefile.inc index 8776d9d..5c96968 100644 --- a/dist/lib/libc/rpc/Makefile.inc +++ b/dist/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/dist/lib/libc/rpc/auth_des.c b/dist/lib/libc/rpc/auth_des.c new file mode 100644 index 0000000..3fd2bfe --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include /* XXX: just to get htonl() and ntohl() */ +#include +#undef NIS +#include + +#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/dist/lib/libc/rpc/auth_none.c b/dist/lib/libc/rpc/auth_none.c index 9c5a664..b2e2995 100644 --- a/dist/lib/libc/rpc/auth_none.c +++ b/dist/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 #include #include #include @@ -110,7 +111,7 @@ authnone_marshal(client, xdrs) ap->marshalled_client, ap->mcnt)); } -static void +static void authnone_verf() { } diff --git a/dist/lib/libc/rpc/auth_time.c b/dist/lib/libc/rpc/auth_time.c new file mode 100644 index 0000000..2b9a5a9 --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#undef NIS +#include + +/* + * 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/dist/lib/libc/rpc/auth_unix.c b/dist/lib/libc/rpc/auth_unix.c index 334dc56..32200c2 100644 --- a/dist/lib/libc/rpc/auth_unix.c +++ b/dist/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 #include +#include +#include +#include #include #include #include @@ -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/dist/lib/libc/rpc/authdes_prot.c b/dist/lib/libc/rpc/authdes_prot.c new file mode 100644 index 0000000..14679c0 --- /dev/null +++ b/dist/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 +#include +#include +#include + +#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/dist/lib/libc/rpc/authunix_prot.c b/dist/lib/libc/rpc/authunix_prot.c index 15faf18..c818ba0 100644 --- a/dist/lib/libc/rpc/authunix_prot.c +++ b/dist/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/dist/lib/libc/rpc/bindresvport.3 b/dist/lib/libc/rpc/bindresvport.3 index 1fb1f9a..5dd71e3 100644 --- a/dist/lib/libc/rpc/bindresvport.3 +++ b/dist/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 -.B #include -.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 +.Fd #include +.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/dist/lib/libc/rpc/bindresvport.c b/dist/lib/libc/rpc/bindresvport.c index a085c91..dea8705 100644 --- a/dist/lib/libc/rpc/bindresvport.c +++ b/dist/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 #include #include #include +#include +#include /* * 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/dist/lib/libc/rpc/clnt_generic.c b/dist/lib/libc/rpc/clnt_generic.c index ad9c22b..ed754ea 100644 --- a/dist/lib/libc/rpc/clnt_generic.c +++ b/dist/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 #include #include +#include /* * 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/dist/lib/libc/rpc/clnt_perror.c b/dist/lib/libc/rpc/clnt_perror.c index 9a7d76c..79baac2 100644 --- a/dist/lib/libc/rpc/clnt_perror.c +++ b/dist/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 +#include #include #include #include @@ -47,6 +48,7 @@ static char *rcsid = "$Id: clnt_perror.c,v 1.1 1993/10/27 05:40:20 paul Exp $"; #include 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/dist/lib/libc/rpc/clnt_raw.c b/dist/lib/libc/rpc/clnt_raw.c index 9ee87b2..c715ef69 100644 --- a/dist/lib/libc/rpc/clnt_raw.c +++ b/dist/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 +#include +#include #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/dist/lib/libc/rpc/clnt_simple.c b/dist/lib/libc/rpc/clnt_simple.c index 671e2eb..5bcfd47 100644 --- a/dist/lib/libc/rpc/clnt_simple.c +++ b/dist/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 #include #include +#include #include #include #include @@ -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/dist/lib/libc/rpc/clnt_tcp.c b/dist/lib/libc/rpc/clnt_tcp.c index efc041a..cfb3746 100644 --- a/dist/lib/libc/rpc/clnt_tcp.c +++ b/dist/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 +#include +#include +#include #include #include #include @@ -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/dist/lib/libc/rpc/clnt_udp.c b/dist/lib/libc/rpc/clnt_udp.c index 4df4631..035ce96 100644 --- a/dist/lib/libc/rpc/clnt_udp.c +++ b/dist/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 +#include +#include +#include #include #include #include @@ -47,8 +50,6 @@ static char *rcsid = "$Id: clnt_udp.c,v 1.1 1993/10/27 05:40:25 paul Exp $"; #include #include -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/dist/lib/libc/rpc/clnt_unix.c b/dist/lib/libc/rpc/clnt_unix.c new file mode 100644 index 0000000..e4c4309 --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/dist/lib/libc/rpc/crypt_client.c b/dist/lib/libc/rpc/crypt_client.c new file mode 100644 index 0000000..cdc0c06 --- /dev/null +++ b/dist/lib/libc/rpc/crypt_client.c @@ -0,0 +1,89 @@ +/* + * Copyright (c) 1996 + * Bill Paul . 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 +#include +#include +#include +#include + +#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/dist/lib/libc/rpc/des_crypt.3 b/dist/lib/libc/rpc/des_crypt.3 new file mode 100644 index 0000000..ca0a33e --- /dev/null +++ b/dist/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 +.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/dist/lib/libc/rpc/des_crypt.c b/dist/lib/libc/rpc/des_crypt.c new file mode 100644 index 0000000..18c9972 --- /dev/null +++ b/dist/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 +#include +#include + +#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/dist/lib/libc/rpc/des_soft.c b/dist/lib/libc/rpc/des_soft.c new file mode 100644 index 0000000..01dd7f2 --- /dev/null +++ b/dist/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/dist/lib/libc/rpc/get_myaddress.c b/dist/lib/libc/rpc/get_myaddress.c index 2b0b20d..f8bfa7c 100644 --- a/dist/lib/libc/rpc/get_myaddress.c +++ b/dist/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 #include #include +#include #include #include #include #include -/* +/* * 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/dist/lib/libc/rpc/getrpcent.3 b/dist/lib/libc/rpc/getrpcent.3 index f500c01..5d70079 100644 --- a/dist/lib/libc/rpc/getrpcent.3 +++ b/dist/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 -.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 +.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/dist/lib/libc/rpc/getrpcent.c b/dist/lib/libc/rpc/getrpcent.c index a495278..8266285 100644 --- a/dist/lib/libc/rpc/getrpcent.c +++ b/dist/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 +#include #include #include #include @@ -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/dist/lib/libc/rpc/getrpcport.3 b/dist/lib/libc/rpc/getrpcport.3 index 0323d34..f9c3cb4 100644 --- a/dist/lib/libc/rpc/getrpcport.3 +++ b/dist/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/dist/lib/libc/rpc/getrpcport.c b/dist/lib/libc/rpc/getrpcport.c index f1d58f9..04a8de2 100644 --- a/dist/lib/libc/rpc/getrpcport.c +++ b/dist/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 +#include #include +#include #include #include +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/dist/lib/libc/rpc/key_call.c b/dist/lib/libc/rpc/key_call.c new file mode 100644 index 0000000..bcef22e --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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/dist/lib/libc/rpc/key_prot_xdr.c b/dist/lib/libc/rpc/key_prot_xdr.c new file mode 100644 index 0000000..8cd6b6b --- /dev/null +++ b/dist/lib/libc/rpc/key_prot_xdr.c @@ -0,0 +1,166 @@ +/* + * Please do not edit this file. + * It was generated using rpcgen. + */ + +#include +/* + * 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/dist/lib/libc/rpc/netname.c b/dist/lib/libc/rpc/netname.c new file mode 100644 index 0000000..3a3942b --- /dev/null +++ b/dist/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 +#include +#include +#ifdef YP +#include +#include +#endif +#include +#include +#include +#include +#include + +#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/dist/lib/libc/rpc/netnamer.c b/dist/lib/libc/rpc/netnamer.c new file mode 100644 index 0000000..391cc20 --- /dev/null +++ b/dist/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 +#include +#include +#ifdef YP +#include +#include +#endif +#include +#include +#include +#include +#include +#include +#include + +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/dist/lib/libc/rpc/pmap_clnt.c b/dist/lib/libc/rpc/pmap_clnt.c index 4ef44ec..9901d81 100644 --- a/dist/lib/libc/rpc/pmap_clnt.c +++ b/dist/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 +#include +#include #include #include #include +#include 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/dist/lib/libc/rpc/pmap_getmaps.c b/dist/lib/libc/rpc/pmap_getmaps.c index 5af5210..d4f2774 100644 --- a/dist/lib/libc/rpc/pmap_getmaps.c +++ b/dist/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 #include #include +#include #include #include #include #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/dist/lib/libc/rpc/pmap_getport.c b/dist/lib/libc/rpc/pmap_getport.c index 06ed4d4..3d4c48a 100644 --- a/dist/lib/libc/rpc/pmap_getport.c +++ b/dist/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 #include #include +#include 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/dist/lib/libc/rpc/pmap_prot.c b/dist/lib/libc/rpc/pmap_prot.c index ea0a20d..fcb9c99 100644 --- a/dist/lib/libc/rpc/pmap_prot.c +++ b/dist/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/dist/lib/libc/rpc/pmap_prot2.c b/dist/lib/libc/rpc/pmap_prot2.c index 71ab21a..d81f612 100644 --- a/dist/lib/libc/rpc/pmap_prot2.c +++ b/dist/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 -/* +/* * 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/dist/lib/libc/rpc/pmap_rmt.c b/dist/lib/libc/rpc/pmap_rmt.c index 339860c..07a81e2 100644 --- a/dist/lib/libc/rpc/pmap_rmt.c +++ b/dist/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 #include #include +#include +#include #include +#include #include #include #include #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/dist/lib/libc/rpc/publickey.3 b/dist/lib/libc/rpc/publickey.3 new file mode 100644 index 0000000..7063e8a --- /dev/null +++ b/dist/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 +.B #include +.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/dist/lib/libc/rpc/publickey.5 b/dist/lib/libc/rpc/publickey.5 new file mode 100644 index 0000000..de3c1e9 --- /dev/null +++ b/dist/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/dist/lib/libc/rpc/rpc.3 b/dist/lib/libc/rpc/rpc.3 index b5a2b92..dd55c22 100644 --- a/dist/lib/libc/rpc/rpc.3 +++ b/dist/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/dist/lib/libc/rpc/rpc.5 b/dist/lib/libc/rpc/rpc.5 index 324ecb1..d7b9d58 100644 --- a/dist/lib/libc/rpc/rpc.5 +++ b/dist/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/dist/lib/libc/rpc/rpc_callmsg.c b/dist/lib/libc/rpc/rpc_callmsg.c index 4ec59db..af8e573 100644 --- a/dist/lib/libc/rpc/rpc_callmsg.c +++ b/dist/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 - +#include +#include #include /* @@ -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/dist/lib/libc/rpc/rpc_commondata.c b/dist/lib/libc/rpc/rpc_commondata.c index e870ab8..9640782 100644 --- a/dist/lib/libc/rpc/rpc_commondata.c +++ b/dist/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 /* * 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/dist/lib/libc/rpc/rpc_dtablesize.c b/dist/lib/libc/rpc/rpc_dtablesize.c index c4a2ac4..c2703fa 100644 --- a/dist/lib/libc/rpc/rpc_dtablesize.c +++ b/dist/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 +#include + /* * 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/dist/lib/libc/rpc/rpc_prot.c b/dist/lib/libc/rpc/rpc_prot.c index 7fbb36f..8debaf1 100644 --- a/dist/lib/libc/rpc/rpc_prot.c +++ b/dist/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/dist/lib/libc/rpc/rpc_secure.3 b/dist/lib/libc/rpc/rpc_secure.3 new file mode 100644 index 0000000..6e9a2ee --- /dev/null +++ b/dist/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 +.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/dist/lib/libc/rpc/rpcdname.c b/dist/lib/libc/rpc/rpcdname.c new file mode 100644 index 0000000..f28b4fd --- /dev/null +++ b/dist/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 +#include +#include + +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/dist/lib/libc/rpc/rstat.1 b/dist/lib/libc/rpc/rstat.1 index 61d9999..03c3a06 100644 --- a/dist/lib/libc/rpc/rstat.1 +++ b/dist/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/dist/lib/libc/rpc/rstat_svc.8 b/dist/lib/libc/rpc/rstat_svc.8 index a10b71d..b7b4386 100644 --- a/dist/lib/libc/rpc/rstat_svc.8 +++ b/dist/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/dist/lib/libc/rpc/rtime.3 b/dist/lib/libc/rpc/rtime.3 new file mode 100644 index 0000000..af0c1ca --- /dev/null +++ b/dist/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 +.B #include +.B #include +.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/dist/lib/libc/rpc/rtime.c b/dist/lib/libc/rpc/rtime.c new file mode 100644 index 0000000..fb2b402 --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/dist/lib/libc/rpc/svc.c b/dist/lib/libc/rpc/svc.c index 55ad25e..ab0e8c1 100644 --- a/dist/lib/libc/rpc/svc.c +++ b/dist/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 +#include #include #include #include -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/dist/lib/libc/rpc/svc_auth.c b/dist/lib/libc/rpc/svc_auth.c index 0a9f276..0063e75 100644 --- a/dist/lib/libc/rpc/svc_auth.c +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#else +#include #include +#endif +#include /* - * 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/dist/lib/libc/rpc/svc_auth_des.c b/dist/lib/libc/rpc/svc_auth_des.c new file mode 100644 index 0000000..889182e --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#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/dist/lib/libc/rpc/svc_auth_unix.c b/dist/lib/libc/rpc/svc_auth_unix.c index 5cf825f..959cb73 100644 --- a/dist/lib/libc/rpc/svc_auth_unix.c +++ b/dist/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 +#include #include /* @@ -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/dist/lib/libc/rpc/svc_raw.c b/dist/lib/libc/rpc/svc_raw.c index e34ea9e..3a5bcb3 100644 --- a/dist/lib/libc/rpc/svc_raw.c +++ b/dist/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 - +#include /* * 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/dist/lib/libc/rpc/svc_run.c b/dist/lib/libc/rpc/svc_run.c index 52fddf2..896aa12 100644 --- a/dist/lib/libc/rpc/svc_run.c +++ b/dist/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 +#include #include +#include +#include +#include +#include +#include + +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/dist/lib/libc/rpc/svc_simple.c b/dist/lib/libc/rpc/svc_simple.c index eacf859..0324675 100644 --- a/dist/lib/libc/rpc/svc_simple.c +++ b/dist/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 +#include +#include #include +#include #include #include @@ -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/dist/lib/libc/rpc/svc_tcp.c b/dist/lib/libc/rpc/svc_tcp.c index 9d19504..1387ee1 100644 --- a/dist/lib/libc/rpc/svc_tcp.c +++ b/dist/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 +#include +#include +#include #include #include #include -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/dist/lib/libc/rpc/svc_udp.c b/dist/lib/libc/rpc/svc_udp.c index d7c7bb2..6622de2 100644 --- a/dist/lib/libc/rpc/svc_udp.c +++ b/dist/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 #include +#include +#include #include #include #include - #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/dist/lib/libc/rpc/svc_unix.c b/dist/lib/libc/rpc/svc_unix.c new file mode 100644 index 0000000..04e3223 --- /dev/null +++ b/dist/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 +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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); +} -- cgit v1.1