summaryrefslogtreecommitdiffstats
path: root/src/portmap.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2007-11-20 15:56:25 -0500
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2007-11-20 15:56:25 -0500
commitfea069c89092d2854f3c7dc192f47a5960fa879b (patch)
tree3bad7bda1cd9f0ad3ab7d03315c388852063f603 /src/portmap.c
parent1c3bfde9c0a8b1990ff3be15f0abf397f4df82e7 (diff)
downloadslapi-nis-fea069c89092d2854f3c7dc192f47a5960fa879b.tar.gz
slapi-nis-fea069c89092d2854f3c7dc192f47a5960fa879b.tar.xz
slapi-nis-fea069c89092d2854f3c7dc192f47a5960fa879b.zip
- working on splitting out the portmap registration/unregistration
- beginning to break out schema management
Diffstat (limited to 'src/portmap.c')
-rw-r--r--src/portmap.c211
1 files changed, 211 insertions, 0 deletions
diff --git a/src/portmap.c b/src/portmap.c
new file mode 100644
index 0000000..ff0aa62
--- /dev/null
+++ b/src/portmap.c
@@ -0,0 +1,211 @@
+#ifdef HAVE_CONFIG_H
+#include "../config.h"
+#endif
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <rpc/xdr.h>
+#include <rpc/rpc_msg.h>
+#include <rpc/pmap_prot.h>
+#include <errno.h>
+#include <poll.h>
+#include <time.h>
+
+#include <dirsrv/slapi-plugin.h>
+
+static bool_t
+portmap_register_work(int resv_sock,
+ int program, int version, int protocol, int port,
+ int proc)
+{
+ char portmap_buf[4000], auth_buf[4000], reply_buf[8000];
+ uint32_t length;
+ int portmap_length, reply_length;
+ AUTH *auth;
+ XDR portmap_xdrs, auth_xdrs;
+ struct rpc_msg msg;
+ struct pmap map;
+ bool_t ret;
+ struct sockaddr addr;
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+ union {
+ struct sockaddr_in addr4;
+ struct sockaddr_in6 addr6;
+ } client_addr;
+ socklen_t client_addrlen;
+ struct pollfd pollfd;
+ int i;
+ u_long xid;
+ gid_t gid = 0;
+
+ memset(&addr, 0, sizeof(addr));
+ memset(&addr4, 0, sizeof(addr4));
+ memset(&addr6, 0, sizeof(addr6));
+ addr.sa_family = AF_UNSPEC;
+ addr4.sin_family = AF_INET;
+ addr4.sin_port = ntohs(PMAPPORT);
+ addr6.sin6_family = AF_INET6;
+ addr6.sin6_port = ntohs(PMAPPORT);
+
+ memset(&msg, 0, sizeof(msg));
+ msg.rm_xid = xid = time(NULL);
+ msg.rm_direction = CALL;
+ msg.rm_call.cb_rpcvers = 2;
+ msg.rm_call.cb_prog = PMAPPROG;
+ msg.rm_call.cb_vers = PMAPVERS;
+ msg.rm_call.cb_proc = proc;
+
+ xdrmem_create(&auth_xdrs, auth_buf, sizeof(auth_buf), XDR_ENCODE);
+ auth = authunix_create("localhost", 0, 0, 1, &gid);
+ auth_marshall(auth, &auth_xdrs);
+ msg.rm_call.cb_cred.oa_flavor = AUTH_SYS;
+ msg.rm_call.cb_cred.oa_base = auth_buf;
+ msg.rm_call.cb_cred.oa_length = xdr_getpos(&auth_xdrs);
+ auth_destroy(auth);
+ xdr_destroy(&auth_xdrs);
+
+ map.pm_prog = program;
+ map.pm_vers = version;
+ map.pm_prot = protocol;
+ map.pm_port = port;
+
+ xdrmem_create(&portmap_xdrs, portmap_buf, sizeof(portmap_buf),
+ XDR_ENCODE);
+ xdr_callmsg(&portmap_xdrs, &msg);
+ xdr_pmap(&portmap_xdrs, &map);
+ portmap_length = xdr_getpos(&portmap_xdrs);
+ xdr_destroy(&portmap_xdrs);
+
+ client_addrlen = 0;
+ connect(resv_sock, (struct sockaddr*) &addr4, sizeof(addr4));
+ for (i = 1; i < 32; i *= 2) {
+ if (send(resv_sock, &portmap_buf, portmap_length,
+ 0) != portmap_length) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "error sending request to portmap\n");
+ continue;
+ }
+ pollfd.fd = resv_sock;
+ pollfd.events = POLLIN | POLLERR;
+ if ((poll(&pollfd, 1, i * 1000) > 0) &&
+ (pollfd.revents & POLLIN)) {
+ client_addrlen = sizeof(client_addr);
+ reply_length = recvfrom(resv_sock,
+ reply_buf, sizeof(reply_buf), 0,
+ (struct sockaddr *)&client_addr,
+ &client_addrlen);
+ if (reply_length > 0) {
+ xdrmem_create(&portmap_xdrs,
+ reply_buf, reply_length,
+ XDR_DECODE);
+ if (xdr_replymsg(&portmap_xdrs, &msg)) {
+ if ((msg.rm_direction == REPLY) &&
+ (msg.rm_xid == xid)) {
+ break;
+ }
+ }
+ xdr_destroy(&portmap_xdrs);
+ }
+ }
+ }
+ connect(resv_sock, &addr, sizeof(addr));
+ if (i == 32) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "timeout registering with portmap service\n");
+ return FALSE;
+ }
+
+ if (msg.rm_reply.rp_stat != MSG_ACCEPTED) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap request not accepted\n");
+ switch (msg.rm_reply.rp_rjct.rj_stat) {
+ const char *auth_status;
+ case AUTH_ERROR:
+ switch (msg.rm_reply.rp_rjct.rj_why) {
+ case AUTH_OK:
+ auth_status = "ok";
+ break;
+ case AUTH_BADCRED:
+ auth_status = "bad credentials";
+ break;
+ case AUTH_REJECTEDCRED:
+ auth_status = "rejected credentials";
+ break;
+ case AUTH_BADVERF:
+ auth_status = "bad verifier";
+ break;
+ case AUTH_REJECTEDVERF:
+ auth_status = "rejected verifier";
+ break;
+ case AUTH_TOOWEAK:
+ auth_status = "too weak";
+ break;
+ case AUTH_INVALIDRESP:
+ auth_status = "invalid response";
+ break;
+ case AUTH_FAILED:
+ default:
+ auth_status = "unknown error";
+ break;
+ }
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap request rejected: "
+ "authentication failed: %s\n",
+ auth_status);
+ break;
+ case RPC_MISMATCH:
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap request rejected: "
+ "RPC mismatch\n");
+ break;
+ }
+ xdr_destroy(&portmap_xdrs);
+ return FALSE;
+ }
+
+ auth = authunix_create_default();
+ if (auth_validate(auth, &msg.rm_reply.rp_acpt.ar_verf)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap reply authenticated\n");
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap reply failed authentication\n");
+ }
+ auth_destroy(auth);
+
+ if (msg.rm_reply.rp_acpt.ar_stat != SUCCESS) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap request not processed\n");
+ xdr_destroy(&portmap_xdrs);
+ return FALSE;
+ }
+
+ if (xdr_bool(&portmap_xdrs, &ret)) {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap request succeeded\n");
+ } else {
+ slapi_log_error(SLAPI_LOG_PLUGIN, "XXX",
+ "portmap response did not include a reply\n");
+ ret = FALSE;
+ }
+
+ xdr_destroy(&portmap_xdrs);
+
+ return ret;
+}
+
+bool_t
+portmap_register(int resv_sock,
+ int program, int version, int protocol, int port)
+{
+ return portmap_register_work(resv_sock, program, version,
+ protocol, port, PMAPPROC_UNSET);
+}
+
+bool_t
+portmap_unregister(int resv_sock, int program, int version)
+{
+ return portmap_register_work(resv_sock, program, version,
+ 0, 0, PMAPPROC_UNSET);
+}