138494Sobrien/*
2174294Sobrien * Copyright (c) 1997-2006 Erez Zadok
338494Sobrien * Copyright (c) 1990 Jan-Simon Pendry
438494Sobrien * Copyright (c) 1990 Imperial College of Science, Technology & Medicine
538494Sobrien * Copyright (c) 1990 The Regents of the University of California.
638494Sobrien * All rights reserved.
738494Sobrien *
838494Sobrien * This code is derived from software contributed to Berkeley by
938494Sobrien * Jan-Simon Pendry at Imperial College, London.
1038494Sobrien *
1138494Sobrien * Redistribution and use in source and binary forms, with or without
1238494Sobrien * modification, are permitted provided that the following conditions
1338494Sobrien * are met:
1438494Sobrien * 1. Redistributions of source code must retain the above copyright
1538494Sobrien *    notice, this list of conditions and the following disclaimer.
1638494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer in the
1838494Sobrien *    documentation and/or other materials provided with the distribution.
1938494Sobrien * 3. All advertising materials mentioning features or use of this software
2042629Sobrien *    must display the following acknowledgment:
2138494Sobrien *      This product includes software developed by the University of
2238494Sobrien *      California, Berkeley and its contributors.
2338494Sobrien * 4. Neither the name of the University nor the names of its contributors
2438494Sobrien *    may be used to endorse or promote products derived from this software
2538494Sobrien *    without specific prior written permission.
2638494Sobrien *
2738494Sobrien * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
2838494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2938494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
3038494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
3138494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
3238494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
3338494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
3438494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3538494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3638494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3738494Sobrien * SUCH DAMAGE.
3838494Sobrien *
3938494Sobrien *
40174294Sobrien * File: am-utils/libamu/misc_rpc.c
4138494Sobrien *
4238494Sobrien */
4338494Sobrien
4438494Sobrien/*
4538494Sobrien * Additions to Sun RPC.
4638494Sobrien */
4738494Sobrien
4838494Sobrien#ifdef HAVE_CONFIG_H
4938494Sobrien# include <config.h>
5038494Sobrien#endif /* HAVE_CONFIG_H */
5138494Sobrien#include <am_defs.h>
5238494Sobrien#include <amu.h>
5338494Sobrien
5438494Sobrien/*
5538494Sobrien * Some systems renamed _seterr_reply to __seterr_reply (with two
5638494Sobrien * leading underscores)
5738494Sobrien */
5838494Sobrien#if !defined(HAVE__SETERR_REPLY) && defined(HAVE___SETERR_REPLY)
5938494Sobrien# define _seterr_reply	__seterr_reply
6038494Sobrien#endif /* !defined(HAVE__SETERR_REPLY) && defined(HAVE___SETERR_REPLY) */
6138494Sobrien
6238494Sobrien
6338494Sobrienvoid
6438494Sobrienrpc_msg_init(struct rpc_msg *mp, u_long prog, u_long vers, u_long proc)
6538494Sobrien{
6638494Sobrien  /*
6742629Sobrien   * Initialize the message
6838494Sobrien   */
6938494Sobrien  memset((voidp) mp, 0, sizeof(*mp));
7038494Sobrien  mp->rm_xid = 0;
7138494Sobrien  mp->rm_direction = CALL;
7238494Sobrien  mp->rm_call.cb_rpcvers = RPC_MSG_VERSION;
7338494Sobrien  mp->rm_call.cb_prog = prog;
7438494Sobrien  mp->rm_call.cb_vers = vers;
7538494Sobrien  mp->rm_call.cb_proc = proc;
7638494Sobrien}
7738494Sobrien
7838494Sobrien
7938494Sobrien/*
8038494Sobrien * Field reply to call to mountd
8138494Sobrien */
8238494Sobrienint
8338494Sobrienpickup_rpc_reply(voidp pkt, int len, voidp where, XDRPROC_T_TYPE where_xdr)
8438494Sobrien{
8538494Sobrien  XDR reply_xdr;
8638494Sobrien  int ok;
8738494Sobrien  struct rpc_err err;
8838494Sobrien  struct rpc_msg reply_msg;
8938494Sobrien  int error = 0;
9038494Sobrien
9138494Sobrien  /* memset((voidp) &err, 0, sizeof(err)); */
9238494Sobrien  memset((voidp) &reply_msg, 0, sizeof(reply_msg));
9338494Sobrien  memset((voidp) &reply_xdr, 0, sizeof(reply_xdr));
9438494Sobrien
95174294Sobrien  reply_msg.acpted_rply.ar_results.where = where;
9638494Sobrien  reply_msg.acpted_rply.ar_results.proc = where_xdr;
9738494Sobrien
9838494Sobrien  xdrmem_create(&reply_xdr, pkt, len, XDR_DECODE);
9938494Sobrien
10038494Sobrien  ok = xdr_replymsg(&reply_xdr, &reply_msg);
10138494Sobrien  if (!ok) {
10238494Sobrien    error = EIO;
10338494Sobrien    goto drop;
10438494Sobrien  }
10538494Sobrien  _seterr_reply(&reply_msg, &err);
10638494Sobrien  if (err.re_status != RPC_SUCCESS) {
10738494Sobrien    error = EIO;
10838494Sobrien    goto drop;
10938494Sobrien  }
11038494Sobrien
11138494Sobriendrop:
11238494Sobrien  if (reply_msg.rm_reply.rp_stat == MSG_ACCEPTED &&
11338494Sobrien      reply_msg.acpted_rply.ar_verf.oa_base) {
11438494Sobrien    reply_xdr.x_op = XDR_FREE;
11538494Sobrien    (void) xdr_opaque_auth(&reply_xdr,
11638494Sobrien			   &reply_msg.acpted_rply.ar_verf);
11738494Sobrien  }
11838494Sobrien  xdr_destroy(&reply_xdr);
11938494Sobrien
12038494Sobrien  return error;
12138494Sobrien}
12238494Sobrien
12338494Sobrien
12438494Sobrienint
12538494Sobrienmake_rpc_packet(char *buf, int buflen, u_long proc, struct rpc_msg *mp, voidp arg, XDRPROC_T_TYPE arg_xdr, AUTH *auth)
12638494Sobrien{
12738494Sobrien  XDR msg_xdr;
12838494Sobrien  int len;
129119679Smbr  /*
130119679Smbr   * Never cast pointers between different integer types, it breaks badly
131119679Smbr   * on big-endian platforms if those types have different sizes.
132119679Smbr   *
133119679Smbr   * Cast to a local variable instead, and use that variable's address.
134119679Smbr   */
135119679Smbr  enum_t local_proc = (enum_t) proc;
13638494Sobrien
13738494Sobrien  xdrmem_create(&msg_xdr, buf, buflen, XDR_ENCODE);
13838494Sobrien
13938494Sobrien  /*
14038494Sobrien   * Basic protocol header
14138494Sobrien   */
14238494Sobrien  if (!xdr_callhdr(&msg_xdr, mp))
14338494Sobrien    return -EIO;
14438494Sobrien
14538494Sobrien  /*
14638494Sobrien   * Called procedure number
14738494Sobrien   */
148119679Smbr  if (!xdr_enum(&msg_xdr, &local_proc))
14938494Sobrien    return -EIO;
15038494Sobrien
15138494Sobrien  /*
15238494Sobrien   * Authorization
15338494Sobrien   */
15438494Sobrien  if (!AUTH_MARSHALL(auth, &msg_xdr))
15538494Sobrien    return -EIO;
15638494Sobrien
15738494Sobrien  /*
15838494Sobrien   * Arguments
15938494Sobrien   */
16038494Sobrien  if (!(*arg_xdr) (&msg_xdr, arg))
16138494Sobrien    return -EIO;
16238494Sobrien
16338494Sobrien  /*
16438494Sobrien   * Determine length
16538494Sobrien   */
16638494Sobrien  len = xdr_getpos(&msg_xdr);
16738494Sobrien
16838494Sobrien  /*
16938494Sobrien   * Throw away xdr
17038494Sobrien   */
17138494Sobrien  xdr_destroy(&msg_xdr);
17238494Sobrien
17338494Sobrien  return len;
17438494Sobrien}
17582794Sobrien
17682794Sobrien
17782794Sobrien/* get uid/gid from RPC credentials */
17882794Sobrienint
17982794Sobriengetcreds(struct svc_req *rp, uid_t *u, gid_t *g, SVCXPRT *nfsxprt)
18082794Sobrien{
18182794Sobrien  struct authunix_parms *aup = (struct authunix_parms *) NULL;
18282794Sobrien#ifdef HAVE_RPC_AUTH_DES_H
18382794Sobrien  struct authdes_cred *adp;
18482794Sobrien#endif /* HAVE_RPC_AUTH_DES_H */
18582794Sobrien
18682794Sobrien  switch (rp->rq_cred.oa_flavor) {
18782794Sobrien
18882794Sobrien  case AUTH_UNIX:
18982794Sobrien    aup = (struct authunix_parms *) rp->rq_clntcred;
19082794Sobrien    *u = aup->aup_uid;
19182794Sobrien    *g = aup->aup_gid;
19282794Sobrien    break;
19382794Sobrien
19482794Sobrien#ifdef HAVE_RPC_AUTH_DES_H
19582794Sobrien  case AUTH_DES:
19682794Sobrien    adp = (struct authdes_cred *) rp->rq_clntcred;
19782794Sobrien    *g = INVALIDID;		/* some unknown group id */
19882794Sobrien    if (sscanf(adp->adc_fullname.name, "unix.%lu@", (u_long *) u) == 1)
19982794Sobrien        break;
20082794Sobrien    /* fall through */
20182794Sobrien#endif /* HAVE_RPC_AUTH_DES_H */
20282794Sobrien
20382794Sobrien  default:
20482794Sobrien    *u = *g = INVALIDID;	/* just in case */
20582794Sobrien    svcerr_weakauth(nfsxprt);
20682794Sobrien    return -1;
20782794Sobrien  }
20882794Sobrien
20982794Sobrien  return 0;			/* everything is ok */
21082794Sobrien}
211