diff options
author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2007-11-20 15:56:25 -0500 |
---|---|---|
committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2007-11-20 15:56:25 -0500 |
commit | fea069c89092d2854f3c7dc192f47a5960fa879b (patch) | |
tree | 3bad7bda1cd9f0ad3ab7d03315c388852063f603 /src/portmap.c | |
parent | 1c3bfde9c0a8b1990ff3be15f0abf397f4df82e7 (diff) | |
download | slapi-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.c | 211 |
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); +} |