summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/plug-nis.c124
-rw-r--r--src/plug-sch.c1
-rw-r--r--src/portmap.c36
-rw-r--r--src/portmap.h7
4 files changed, 108 insertions, 60 deletions
diff --git a/src/plug-nis.c b/src/plug-nis.c
index ae01984..19ff1dc 100644
--- a/src/plug-nis.c
+++ b/src/plug-nis.c
@@ -36,7 +36,6 @@
#include <unistd.h>
#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
#include <rpcsvc/yp_prot.h>
#ifdef HAVE_TCPD_H
@@ -98,9 +97,12 @@ plugin_startup(Slapi_PBlock *pb)
/* Kick off any other NIS servers on the local box. */
portmap_unregister(plugin_description.spd_id,
state->pmap_client_socket,
- YPPROG, YPVERS);
+ YPPROG, YPVERS, AF_INET);
/* Register our listening ports. */
for (i = 0; i < state->n_listeners; i++) {
+ if (state->listener[i].pf != PF_INET) {
+ continue;
+ }
switch (state->listener[i].type) {
case SOCK_DGRAM:
protocol = IPPROTO_UDP;
@@ -120,12 +122,18 @@ plugin_startup(Slapi_PBlock *pb)
}
if (!portmap_register(plugin_description.spd_id,
state->pmap_client_socket,
- YPPROG, YPVERS, protocol,
+ YPPROG, YPVERS,
+ AF_INET, protocol,
state->listener[i].port)) {
slapi_log_error(SLAPI_LOG_PLUGIN,
plugin_description.spd_id,
"error registering %s service "
"with portmap\n", pname);
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ plugin_description.spd_id,
+ "registered %s service "
+ "with portmap\n", pname);
}
}
}
@@ -143,12 +151,14 @@ plugin_shutdown(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
for (i = 0; i < state->n_listeners; i++) {
close(state->listener[i].fd);
+ state->listener[i].fd = -1;
}
state->n_listeners = 0;
if (state->pmap_client_socket != -1) {
/* Clear our registration with the portmapper. */
portmap_unregister(plugin_description.spd_id,
- state->pmap_client_socket, YPPROG, YPVERS);
+ state->pmap_client_socket,
+ YPPROG, YPVERS, AF_INET);
}
wrap_stop_thread(state->tid);
map_done(state);
@@ -186,6 +196,53 @@ plugin_read_config(Slapi_PBlock *plugin_pb, int *port)
}
}
+/* Bind to a privileged port. We don't much care which one at this point. */
+static int
+plugin_bind_resvport(int fd, int family, int but_not)
+{
+ int i, offset, port;
+ struct sockaddr_in sin;
+ struct sockaddr_in6 sin6;
+ switch (family) {
+ case AF_INET:
+ memset(&sin, 0, sizeof(sin));
+ sin.sin_family = AF_INET;
+ break;
+ case AF_INET6:
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ break;
+ default:
+ return -1;
+ }
+ offset = getpid() % 512;
+ for (i = 512; i < 1024; i++) {
+ port = ((offset + i) % 512) + 512;
+ if (port == but_not) {
+ continue;
+ }
+ switch (family) {
+ case AF_INET:
+ sin.sin_port = htons(port);
+ if (bind(fd, (struct sockaddr*) &sin,
+ sizeof(sin)) == 0) {
+ return port;
+ }
+ break;
+ case AF_INET6:
+ sin6.sin6_port = htons(port);
+ if (bind(fd, (struct sockaddr*) &sin6,
+ sizeof(sin6)) == 0) {
+ return port;
+ }
+ break;
+ default:
+ return -1;
+ }
+ }
+ return 0;
+}
+
/* Handle the part of startup that needs to be done before we drop privileges:
* bind to listening ports and one more for talking to the local portmapper. */
static int
@@ -238,9 +295,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
"error allocating portmap client socket\n");
goto failed;
}
- memset(&sin, 0, sizeof(sin));
- sin.sin_family = AF_INET;
- if (bindresvport(sockfd, &sin) != 0) {
+ if (plugin_bind_resvport(sockfd, AF_INET, port) <= 0) {
if ((getenv(NIS_PLUGIN_CONTINUE_WITHOUT_PORTMAP_ENV) == NULL) ||
!atol(getenv(NIS_PLUGIN_CONTINUE_WITHOUT_PORTMAP_ENV))) {
slapi_log_error(SLAPI_LOG_FATAL,
@@ -248,6 +303,7 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
"error binding portmap client socket "
"to a privileged port\n");
close(sockfd);
+ sockfd = -1;
goto failed;
} else {
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -268,10 +324,10 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
const char *sock_desc;
/* Figure out what kind of socket we need, and a textual
* term to use in log messages. */
- pf = (i & 2) ? PF_INET6 : PF_INET;
+ pf = (i & 2) ? PF_INET : PF_INET6;
type = (i & 1) ? SOCK_STREAM : SOCK_DGRAM;
- sock_desc = (i & 2) ? ((i & 1) ? "tcp6" : "udp6") :
- ((i & 1) ? "tcp" : "udp");
+ sock_desc = (i & 2) ? ((i & 1) ? "tcp" : "udp") :
+ ((i & 1) ? "tcp6" : "udp6");
/* Allocate the socket. */
sockfd = socket(pf, type, 0);
if (sockfd == -1) {
@@ -290,19 +346,22 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
"error marking %s socket for reuse, "
"continuing\n", sock_desc);
close(sockfd);
- goto failed;
+ continue;
}
- /* Bind to the server port, if one was specified, otherwise let
- * libc try to find an unused one for us. */
+ /* Bind to the server port, if one was specified, otherwise try
+ * to find an unused one. */
memset(&sin, 0, sizeof(sin));
memset(&sin6, 0, sizeof(sin6));
sin.sin_family = AF_INET;
sin6.sin6_family = AF_INET6;
if (port == 0) {
- ret = (pf == PF_INET6) ? bindresvport(sockfd,
- (struct sockaddr_in*) &sin6) :
- bindresvport(sockfd,
- &sin);
+ port = (pf == PF_INET6) ? plugin_bind_resvport(sockfd,
+ AF_INET6,
+ 0) :
+ plugin_bind_resvport(sockfd,
+ AF_INET,
+ 0);
+ ret = (port > 0) ? 0 : -1;
} else {
sin.sin_port = htons(port);
sin6.sin6_port = htons(port);
@@ -340,39 +399,12 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
strerror(errno));
continue;
}
- } else {
- /* Try to read back the bound address. */
- socklen_t socklen;
- if (getsockname(sockfd,
- (pf == PF_INET6) ?
- (struct sockaddr*) &sin6 :
- (struct sockaddr*) &sin,
- &socklen) != 0) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "error retrieving local "
- "socket address: %s\n",
- strerror(errno));
- }
- if (socklen !=
- (pf == PF_INET6) ? sizeof(sin6) : sizeof(sin)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "error retrieving local "
- "socket address: %s\n",
- strerror(errno));
- }
-
}
flags = fcntl(sockfd, F_GETFL);
if ((flags & O_NONBLOCK) == 0) {
fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
}
- /* Read the port number that we ended up using, in case we used
- * bindresvport[6]. */
- port = (pf == PF_INET6) ? ntohs(sin6.sin6_port) :
- ntohs(sin.sin_port);
- /* If it's a listening socket, let the kernel know that we're
+ /* If it's a stream socket, let the kernel know that we're
* ready to accept client connections. */
if (type == SOCK_STREAM) {
if (listen(sockfd, 128) == -1) {
@@ -406,9 +438,11 @@ plugin_state_init(Slapi_PBlock *pb, struct plugin_state **lstate)
failed:
for (i = 0; i < state->n_listeners; i++) {
close(state->listener[i].fd);
+ state->listener[i].fd = -1;
}
if (state->pmap_client_socket != -1) {
close(state->pmap_client_socket);
+ state->pmap_client_socket = -1;
}
err = errno;
free(state);
diff --git a/src/plug-sch.c b/src/plug-sch.c
index f5fdbf4..34dfa74 100644
--- a/src/plug-sch.c
+++ b/src/plug-sch.c
@@ -37,7 +37,6 @@
#include <unistd.h>
#include <rpc/rpc.h>
-#include <rpc/pmap_clnt.h>
#include <rpcsvc/yp_prot.h>
#ifdef HAVE_TCPD_H
diff --git a/src/portmap.c b/src/portmap.c
index 8963bbf..bb5051f 100644
--- a/src/portmap.c
+++ b/src/portmap.c
@@ -37,9 +37,13 @@
#include <slapi-plugin.h>
#endif
+#include <rpcsvc/yp_prot.h>
#include <rpc/xdr.h>
+#ifdef HAVE_LIBTIRPC
+#include <rpc/rpcb_prot.h>
+#else
#include <rpc/pmap_prot.h>
-#include <rpcsvc/yp_prot.h>
+#endif
#include "portmap.h"
@@ -67,8 +71,8 @@ main(int argc, char **argv)
printf("error binding to reserved port\n");
}
setreuid(2510, 2510);
- portmap_unregister("portmap", s, YPPROG, YPVERS);
- portmap_register("portmap", s, YPPROG, YPVERS, IPPROTO_UDP,
+ portmap_unregister("portmap", s, YPPROG, YPVERS, AF_INET);
+ portmap_register("portmap", s, YPPROG, YPVERS, AF_INET, IPPROTO_UDP,
ntohs(sin.sin_port));
return 0;
}
@@ -76,7 +80,8 @@ main(int argc, char **argv)
static bool_t
portmap_register_work(const char *module, int resv_sock,
- int program, int version, int protocol, int port,
+ int program, int version,
+ int family, int protocol, int port,
int proc)
{
char portmap_buf[4000], auth_buf[4000], reply_buf[8000], *log_id;
@@ -138,7 +143,13 @@ portmap_register_work(const char *module, int resv_sock,
addr4.sin_family = AF_INET;
addr4.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
addr4.sin_port = htons(PMAPPORT);
- connect(resv_sock, (struct sockaddr*) &addr4, sizeof(addr4));
+ i = connect(resv_sock, (struct sockaddr*) &addr4, sizeof(addr4));
+ if (i != 0) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, log_id,
+ "error targeting portmap with sock %d: %s\n",
+ resv_sock, strerror(errno));
+ return FALSE;
+ }
/* Transmit our request. Retry a few times if it doesn't go through. */
for (i = 1; i < 32; i *= 2) {
@@ -170,8 +181,10 @@ portmap_register_work(const char *module, int resv_sock,
xdrmem_create(&portmap_xdrs,
reply_buf, reply_length,
XDR_DECODE);
- msg.rm_reply.rp_acpt.ar_results.where = (caddr_t) &ret;
- msg.rm_reply.rp_acpt.ar_results.proc = (xdrproc_t) xdr_bool;
+ msg.rm_reply.rp_acpt.ar_results.where =
+ (caddr_t) &ret;
+ msg.rm_reply.rp_acpt.ar_results.proc =
+ (xdrproc_t) xdr_bool;
if (xdr_replymsg(&portmap_xdrs, &msg)) {
if ((msg.rm_direction == REPLY) &&
(msg.rm_xid == xid)) {
@@ -278,15 +291,16 @@ portmap_register_work(const char *module, int resv_sock,
bool_t
portmap_register(const char *log_id, int resv_sock,
- int program, int version, int protocol, int port)
+ int program, int version, int family, int protocol, int port)
{
return portmap_register_work(log_id, resv_sock, program, version,
- protocol, port, PMAPPROC_SET);
+ family, protocol, port, PMAPPROC_SET);
}
bool_t
-portmap_unregister(const char *log_id, int resv_sock, int program, int version)
+portmap_unregister(const char *log_id, int resv_sock,
+ int program, int version, int family)
{
return portmap_register_work(log_id, resv_sock, program, version,
- 0, 0, PMAPPROC_UNSET);
+ family, 0, 0, PMAPPROC_UNSET);
}
diff --git a/src/portmap.h b/src/portmap.h
index 0312188..ed59b67 100644
--- a/src/portmap.h
+++ b/src/portmap.h
@@ -23,8 +23,9 @@
#define portmap_h
bool_t portmap_register(const char *log_id, int resv_sock,
- int program, int version, int protocol, int port);
-bool_t portmap_unregister(const char *log_id,
- int resv_sock, int program, int version);
+ int program, int version,
+ int family, int protocol, int port);
+bool_t portmap_unregister(const char *log_id, int resv_sock,
+ int program, int version, int family);
#endif