#ifndef lint
#if 0
static char sccsid[] = "@(#) pmap_check.c 1.6 93/11/21 20:58:59";
#endif
static const char rcsid[] =
"$FreeBSD: src/usr.sbin/portmap/pmap_check.c,v 1.6 2000/01/15 23:08:28 brian Exp $";
#endif
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <rpc/rpc.h>
#include <rpc/pmap_prot.h>
#include <syslog.h>
#include <netdb.h>
#include <sys/signal.h>
#include "pmap_check.h"
#define NFSPROG ((u_long) 100003)
#define MOUNTPROG ((u_long) 100005)
#define YPXPROG ((u_long) 100069)
#define YPPROG ((u_long) 100004)
#define YPPROC_DOMAIN_NONACK ((u_long) 2)
#define MOUNTPROC_MNT ((u_long) 1)
static void logit __P((int, struct sockaddr_in *, u_long, u_long, const char *));
static void toggle_verboselog __P((int));
int verboselog = 0;
int allow_severity = LOG_INFO;
int deny_severity = LOG_WARNING;
#define good_client(a) hosts_ctl("portmap", "", inet_ntoa(a->sin_addr), "")
#define legal_port(a,p) \
(ntohs((a)->sin_port) < IPPORT_RESERVED || (p) >= IPPORT_RESERVED)
#define log_bad_port(addr, proc, prog) \
logit(deny_severity, addr, proc, prog, ": request from unprivileged port")
#define log_bad_host(addr, proc, prog) \
logit(deny_severity, addr, proc, prog, ": request from unauthorized host")
#define log_bad_owner(addr, proc, prog) \
logit(deny_severity, addr, proc, prog, ": request from non-local host")
#define log_no_forward(addr, proc, prog) \
logit(deny_severity, addr, proc, prog, ": request not forwarded")
#define log_client(addr, proc, prog) \
logit(allow_severity, addr, proc, prog, "")
void
check_startup()
{
if (setuid(1) == -1) {
syslog(LOG_ERR, "setuid(1) failed: %m");
exit(1);
}
(void) signal(SIGINT, toggle_verboselog);
}
int
check_default(addr, proc, prog)
struct sockaddr_in *addr;
u_long proc, prog;
{
#ifdef HOSTS_ACCESS
if (!(from_local(addr) || good_client(addr))) {
log_bad_host(addr, proc, prog);
return (FALSE);
}
#endif
if (verboselog)
log_client(addr, proc, prog);
return (TRUE);
}
int
check_privileged_port(addr, proc, prog, port)
struct sockaddr_in *addr;
u_long proc, prog, port;
{
#ifdef CHECK_PORT
if (!legal_port(addr, port)) {
log_bad_port(addr, proc, prog);
return (FALSE);
}
#endif
return (TRUE);
}
int
check_setunset(addr, proc, prog, port)
struct sockaddr_in *addr;
u_long proc, prog, port;
{
if (!from_local(addr)) {
#ifdef HOSTS_ACCESS
(void) good_client(addr);
#endif
log_bad_owner(addr, proc, prog);
return (FALSE);
}
if (port && !check_privileged_port(addr, proc, prog, port))
return (FALSE);
if (verboselog)
log_client(addr, proc, prog);
return (TRUE);
}
int
check_callit(addr, proc, prog, aproc)
struct sockaddr_in *addr;
u_long proc, prog, aproc;
{
#ifdef HOSTS_ACCESS
if (!(from_local(addr) || good_client(addr))) {
log_bad_host(addr, proc, prog);
return (FALSE);
}
#endif
if (prog == PMAPPROG || prog == NFSPROG || prog == YPXPROG ||
(prog == MOUNTPROG && aproc == MOUNTPROC_MNT) ||
(prog == YPPROG && aproc != YPPROC_DOMAIN_NONACK)) {
log_no_forward(addr, proc, prog);
return (FALSE);
}
if (verboselog)
log_client(addr, proc, prog);
return (TRUE);
}
static void
toggle_verboselog(sig)
int sig;
{
(void) signal(sig, toggle_verboselog);
verboselog = !verboselog;
}
static void
logit(severity, addr, procnum, prognum, text)
int severity;
struct sockaddr_in *addr;
u_long procnum, prognum;
const char *text;
{
const char *procname;
char procbuf[4 * sizeof(u_long)];
const char *progname;
char progbuf[4 * sizeof(u_long)];
struct rpcent *rpc;
struct proc_map {
u_long code;
const char *proc;
};
struct proc_map *procp;
static struct proc_map procmap[] = {
{PMAPPROC_CALLIT, "callit"},
{PMAPPROC_DUMP, "dump"},
{PMAPPROC_GETPORT, "getport"},
{PMAPPROC_NULL, "null"},
{PMAPPROC_SET, "set"},
{PMAPPROC_UNSET, "unset"},
{0, 0},
};
if (fork() == 0) {
if (prognum == 0) {
progname = "";
} else if ((rpc = getrpcbynumber((int) prognum))) {
progname = rpc->r_name;
} else {
sprintf(progbuf, "%lu", prognum);
progname = progbuf;
}
for (procp = procmap; procp->proc && procp->code != procnum; procp++)
;
if ((procname = procp->proc) == 0) {
sprintf(procbuf, "%lu", (u_long) procnum);
procname = procbuf;
}
syslog(severity, "connect from %s to %s(%s)%s",
inet_ntoa(addr->sin_addr), procname, progname, text);
exit(0);
}
}