summaryrefslogtreecommitdiffstats
path: root/src/plugin.c
diff options
context:
space:
mode:
authorNalin Dahyabhai <nalin.dahyabhai@pobox.com>2007-11-29 13:15:47 -0500
committerNalin Dahyabhai <nalin.dahyabhai@pobox.com>2007-11-29 13:15:47 -0500
commitf82215df2d4af8456d7228628ea5a6678ed908dd (patch)
tree941619407c77e54e88d6649918278fb9e218840b /src/plugin.c
parentaf4e31549b09a6cfb9774649c69c8ab769bee4ae (diff)
downloadslapi-nis-f82215df2d4af8456d7228628ea5a6678ed908dd.tar.gz
slapi-nis-f82215df2d4af8456d7228628ea5a6678ed908dd.tar.xz
slapi-nis-f82215df2d4af8456d7228628ea5a6678ed908dd.zip
- split up some more
Diffstat (limited to 'src/plugin.c')
-rw-r--r--src/plugin.c475
1 files changed, 54 insertions, 421 deletions
diff --git a/src/plugin.c b/src/plugin.c
index 0b58862..da40b06 100644
--- a/src/plugin.c
+++ b/src/plugin.c
@@ -22,11 +22,13 @@
#include <plarenas.h>
#include <dirsrv/slapi-plugin.h>
+#include "nis.h"
+#include "plugin.h"
#include "portmap.h"
#include "schema.h"
+#include "stream.h"
#define PACKAGE_VERSION "0.0"
-#define PORT 388
/* the module initialization function */
static Slapi_PluginDesc
@@ -37,19 +39,6 @@ plugin_description = {
.spd_description = "NIS Service Plugin",
};
-struct plugin_state {
- PLArenaPool *arena;
- pthread_t tid;
- Slapi_ComponentId *plugin_identity;
- Slapi_PluginDesc *plugin_desc;
- int resvport;
- int n_listeners;
- int listenfd[4];
- int listenport[4];
- int sock_pf[4];
- int sock_type[4];
-};
-
struct search_stream_data {
struct plugin_state *state;
int client;
@@ -114,20 +103,10 @@ cb_stream_referral(char *referral, void *callback_data)
return 0;
}
-static void
-handle_stream_client(struct plugin_state *state, int client)
-{
- Slapi_PBlock *pblock;
- int i;
- char *attrs[] = {
- "ou",
- NULL,
- };
- struct search_stream_data data;
- memset(&data, 0, sizeof(data));
- data.state = state;
- data.client = client;
+#if 0
pblock = slapi_pblock_new();
+ slapi_pblock_set(pblock, SLAPI_CONN_DN, "");
+ slapi_pblock_set(pblock, SLAPI_CONN_AUTHMETHOD, SLAPD_AUTH_NONE);
slapi_search_internal_set_pb(pblock,
"dc=boston,dc=redhat,dc=com",
LDAP_SCOPE_ONE,
@@ -143,377 +122,19 @@ handle_stream_client(struct plugin_state *state, int client)
cb_stream_referral);
slapi_pblock_destroy(pblock);
close(client);
-}
-
-static void
-handle_dgram_client(struct plugin_state *state, int sockfd,
- char *dgram, int dgram_size,
- struct sockaddr *client_addr, socklen_t client_addrlen)
-{
- XDR request_xdrs, reply_xdrs, auth_xdrs;
- AUTH *request_auth, *reply_auth;
- char reply_buf[64000], auth_buf[64000];
- struct rpc_msg request, reply;
- int superuser, send_reply, auth_flavor, auth_len;
- memset(&request_xdrs, 0, sizeof(request_xdrs));
- memset(&reply_xdrs, 0, sizeof(reply_xdrs));
- memset(&request, 0, sizeof(request));
- memset(&reply, 0, sizeof(reply));
- xdrmem_create(&request_xdrs, dgram, dgram_size, XDR_DECODE);
- if (xdr_callmsg(&request_xdrs, &request) &&
- (request.rm_direction == CALL)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "client request prog=%d,ver=%d,proc=%d\n",
- request.rm_call.cb_prog,
- request.rm_call.cb_vers,
- request.rm_call.cb_proc);
- /* verify the client's creds */
- auth_flavor = request.rm_call.cb_cred.oa_flavor;
- switch (auth_flavor) {
- case AUTH_SYS:
- request_auth = authunix_create_default();
- break;
- case AUTH_NONE:
- default:
- request_auth = authnone_create();
- break;
- }
- if (auth_validate(request_auth, &request.rm_call.cb_cred)) {
- switch (auth_flavor) {
- case AUTH_SYS:
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "validated auth_sys creds\n");
- superuser = 0;
- break;
- default:
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "validated other creds\n");
- superuser = 0;
- break;
- }
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "failed to validate client creds\n");
- superuser = 0;
- }
- auth_destroy(request_auth);
- /* setup authentication for our reply */
- xdrmem_create(&auth_xdrs, auth_buf, sizeof(auth_buf),
- XDR_ENCODE);
- switch (auth_flavor) {
- case AUTH_SYS:
- reply_auth = authunix_create_default();
- break;
- case AUTH_NONE:
- default:
- reply_auth = authnone_create();
- break;
- }
- auth_marshall(reply_auth, &auth_xdrs);
- auth_destroy(reply_auth);
- auth_len = xdr_getpos(&auth_xdrs);
- xdr_destroy(&auth_xdrs);
- /* fill out the common fields */
- reply.rm_xid = request.rm_xid;
- reply.rm_direction = REPLY;
- send_reply = 1;
- xdrmem_create(&reply_xdrs, reply_buf, sizeof(reply_buf),
- XDR_ENCODE);
- /* check if the request is meant for us */
- if ((request.rm_direction != CALL) ||
- (request.rm_call.cb_rpcvers != 2) ||
- (request.rm_call.cb_prog != YPPROG) ||
- (request.rm_call.cb_vers != YPVERS)) {
- reply.rm_reply.rp_stat = MSG_DENIED;
- reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH;
- xdr_replymsg(&reply_xdrs, &reply);
- } else {
- char domainname[YPMAXDOMAIN], *p = domainname;
- bool_t bool_ret = 1;
- struct ypreq_key req_key;
- struct ypreq_nokey req_nokey;
- struct ypresp_val resp_val;
- struct ypresp_key_val resp_key_val;
- struct ypresp_master resp_master;
- struct ypresp_order resp_order;
- struct ypresp_all resp_all;
- switch (request.rm_call.cb_proc) {
- case YPPROC_NULL:
- case YPPROC_XFR:
- case YPPROC_CLEAR:
- /* do nothing */
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- case YPPROC_DOMAIN:
- case YPPROC_DOMAIN_NONACK:
- /* indicate whether or not we support a
- * specified domain */
- if (xdr_string(&request_xdrs,
- &p, sizeof(domainname))) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "domain(%s)? ", p);
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- bool_ret = schema_supports_domain(p);
- reply.rm_reply.rp_acpt.ar_results.where = &bool_ret;
- reply.rm_reply.rp_acpt.ar_results.proc = xdr_bool;
- if ((request.rm_call.cb_proc == YPPROC_DOMAIN_NONACK) &&
- (bool_ret == 0)) {
- send_reply = 0;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "-> %d\n", bool_ret);
- }
- break;
- case YPPROC_MATCH:
- /* match one key */
- if (xdr_ypreq_key(&request_xdrs, &req_key)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "match(%s/%s/%.*s)? ",
- req_key.domain,
- req_key.map,
- (int) req_key.keydat.keydat_len,
- req_key.keydat.keydat_val);
- memset(&resp_val, 0, sizeof(resp_val));
- resp_val.status = YP_TRUE;
- resp_val.valdat.valdat_val = "jimbo:*K*:1234:5678:Leeroy Jenkins:/home/leeroy:/bin/bash";
- resp_val.valdat.valdat_len = strlen(resp_val.valdat.valdat_val);
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- reply.rm_reply.rp_acpt.ar_results.where = &resp_val;
- reply.rm_reply.rp_acpt.ar_results.proc = xdr_ypresp_val;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "-> %d\n",
- resp_val.status);
- }
- break;
- case YPPROC_FIRST:
- /* get first key/val */
- if (xdr_ypreq_nokey(&request_xdrs, &req_nokey)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "first(%s/%s)? ",
- req_nokey.domain,
- req_nokey.map);
- memset(&resp_val, 0, sizeof(resp_val));
- resp_key_val.status = YP_TRUE;
- resp_key_val.keydat.keydat_val = "jimbo";
- resp_key_val.keydat.keydat_len = strlen(resp_key_val.keydat.keydat_val);
- resp_key_val.valdat.valdat_val = "jimbo:*K*:1234:5678:Leeroy Jenkins:/home/leeroy:/bin/bash";
- resp_key_val.valdat.valdat_len = strlen(resp_key_val.valdat.valdat_val);
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- reply.rm_reply.rp_acpt.ar_results.where = &resp_key_val;
- reply.rm_reply.rp_acpt.ar_results.proc = xdr_ypresp_key_val;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "-> %d\n",
- resp_key_val.status);
- }
- break;
- case YPPROC_NEXT:
- /* XXX */
- break;
- case YPPROC_ALL:
- /* get all keys/vals */
- if (xdr_ypreq_nokey(&request_xdrs, &req_nokey)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "all(%s/%s)? ",
- req_nokey.domain,
- req_nokey.map);
- bool_ret = 1;
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- reply.rm_reply.rp_acpt.ar_results.where = NULL;
- reply.rm_reply.rp_acpt.ar_results.proc = xdr_void;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "-> %d\n",
- bool_ret);
- }
- break;
- case YPPROC_MASTER:
- /* get the master */
- if (xdr_ypreq_nokey(&request_xdrs, &req_nokey)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "master(%s/%s)? ",
- req_nokey.domain,
- req_nokey.map);
- memset(&resp_val, 0, sizeof(resp_val));
- resp_master.status = YP_TRUE;
- resp_master.master = "";
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- reply.rm_reply.rp_acpt.ar_results.where = &resp_master;
- reply.rm_reply.rp_acpt.ar_results.proc = xdr_ypresp_master;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "-> %d\n",
- resp_master.status);
- }
- break;
- case YPPROC_ORDER:
- /* get the order */
- if (xdr_ypreq_nokey(&request_xdrs, &req_nokey)) {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "all(%s/%s)? ",
- req_nokey.domain,
- req_nokey.map);
- memset(&resp_val, 0, sizeof(resp_val));
- resp_order.status = YP_TRUE;
- resp_order.ordernum = 0;
- reply.rm_reply.rp_stat = MSG_ACCEPTED;
- reply.rm_reply.rp_acpt.ar_stat = SUCCESS;
- reply.rm_reply.rp_acpt.ar_results.where = &resp_order;
- reply.rm_reply.rp_acpt.ar_results.proc = xdr_ypresp_order;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "-> %d\n", resp_order.status);
- }
- break;
- case YPPROC_MAPLIST:
- break;
- default:
- reply.rm_reply.rp_stat = MSG_DENIED;
- reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH;
- break;
- }
- if (send_reply) {
- if (reply.rm_reply.rp_stat == MSG_ACCEPTED) {
- struct opaque_auth oa;
- oa.oa_flavor = auth_flavor;
- oa.oa_base = auth_buf;
- oa.oa_length = auth_len;
- reply.rm_reply.rp_acpt.ar_verf = oa;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "encoding reply\n");
- if (client_addr != NULL) {
- xdr_replymsg(&reply_xdrs, &reply);
- sendto(sockfd,
- reply_buf,
- xdr_getpos(&reply_xdrs),
- 0, client_addr, client_addrlen);
- } else {
- uint32_t len;
- if (request.rm_call.cb_proc == YPPROC_ALL) {
- resp_key_val.status = YP_TRUE;
- resp_key_val.keydat.keydat_val = "jimbo";
- resp_key_val.keydat.keydat_len = strlen(resp_key_val.keydat.keydat_val);
- resp_key_val.valdat.valdat_val = "jimbo:*K*:1234:5678:Leeroy Jenkins:/home/leeroy:/bin/bash";
- resp_key_val.valdat.valdat_len = strlen(resp_key_val.valdat.valdat_val);
-
- xdr_setpos(&reply_xdrs, 4);
- xdr_replymsg(&reply_xdrs, &reply);
- bool_ret = 1;
- xdr_bool(&reply_xdrs, &bool_ret);
- xdr_ypresp_key_val(&reply_xdrs,
- &resp_key_val);
- xdr_bool(&reply_xdrs, &bool_ret);
- xdr_ypresp_key_val(&reply_xdrs,
- &resp_key_val);
- len = htonl(xdr_getpos(&reply_xdrs) - 4);
- memcpy(reply_buf, &len, 4);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "sending %d bytes\n",
- xdr_getpos(&reply_xdrs));
- send(sockfd, reply_buf,
- xdr_getpos(&reply_xdrs), 0);
- xdr_setpos(&reply_xdrs, 4);
- bool_ret = 1;
- xdr_bool(&reply_xdrs, &bool_ret);
- xdr_ypresp_key_val(&reply_xdrs,
- &resp_key_val);
- bool_ret = 0;
- xdr_bool(&reply_xdrs, &bool_ret);
- len = htonl((xdr_getpos(&reply_xdrs) - 4) | 0x80000000);
- memcpy(reply_buf, &len, 4);
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "sending %d bytes\n",
- xdr_getpos(&reply_xdrs));
- send(sockfd, reply_buf,
- xdr_getpos(&reply_xdrs), 0);
- }
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "sent reply\n");
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "suppressed reply\n");
- }
- }
- xdr_destroy(&reply_xdrs);
- }
- xdr_destroy(&request_xdrs);
-}
-
-static void
-handle_stream_client_new(struct plugin_state *state, int client)
-{
- int i, last, ret;
- int32_t len;
- char buf[LINE_MAX];
- do {
- i = read(client, &len, sizeof(len));
- if (i == 4) {
- len = htonl(len);
- last = ((len >> 31) == 1);
- len &= 0x7fffffff;
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "client request has %d bytes\n",
- len);
- i = 0;
- while (i < len) {
- ret = read(client, buf + i, len - i);
- if (ret <= 0) {
- close(client);
- return;
- }
- i += ret;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "processing %d byte request %s\n",
- len, last ? "(last)" : "(more)");
- handle_dgram_client(state, client, buf, len, NULL, 0);
- } else {
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "read %d bytes, expected 4, closing\n",
- i);
- last = 1;
- }
- } while (!last);
- close(client);
-}
+#endif
static void *
-process_requests(void *p)
+listener_thread(void *p)
{
struct plugin_state *state = p;
struct pollfd fds[4];
- int client, i;
+ int client, reqsize, i;
char dgram[65536];
struct sockaddr_storage client_addr;
socklen_t client_addrlen;
for (;;) {
+ /* Set up for polling. */
memset(&fds, 0, sizeof(fds));
for (i = 0; i < state->n_listeners; i++) {
fds[i].fd = state->listenfd[i];
@@ -526,40 +147,44 @@ process_requests(void *p)
case 0:
continue;
default:
+ /* Iterate over listening sockets with work for us. */
for (i = 0; i < state->n_listeners; i++) {
if ((fds[i].revents & POLLIN) == 0) {
continue;
}
- client = -1;
- if (state->sock_type[i] == SOCK_STREAM){
- client = accept(fds[i].fd,
- NULL,
- NULL);
- }
- if (state->sock_type [i]== SOCK_DGRAM) {
+ switch (state->sock_type[i]) {
+ case SOCK_DGRAM:
client_addrlen = sizeof(client_addr);
- client = recvfrom(fds[i].fd,
- dgram,
- sizeof(dgram),
- 0,
- (struct sockaddr *) &client_addr,
- &client_addrlen);
- }
- if (client == -1) {
- continue;
- }
- slapi_log_error(SLAPI_LOG_PLUGIN,
- plugin_description.spd_id,
- "answering client request\n");
- if (state->sock_type[i] == SOCK_STREAM) {
- handle_stream_client_new(state, client);
- }
- if (state->sock_type[i] == SOCK_DGRAM) {
- handle_dgram_client(state, fds[i].fd,
- dgram, client,
+ reqsize = recvfrom(fds[i].fd,
+ dgram,
+ sizeof(dgram),
+ 0,
+ (struct sockaddr *) &client_addr,
+ &client_addrlen);
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ plugin_description.spd_id,
+ "datagram request\n");
+ nis_process_request(state, fds[i].fd,
(struct sockaddr *)
&client_addr,
- client_addrlen);
+ client_addrlen,
+ dgram, reqsize);
+ break;
+ case SOCK_STREAM:
+ client = accept(fds[i].fd, NULL, NULL);
+ if (client != -1) {
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ plugin_description.spd_id,
+ "new stream request\n");
+ stream_client_start(state,
+ client);
+ }
+ break;
+ default:
+ slapi_log_error(SLAPI_LOG_PLUGIN,
+ plugin_description.spd_id,
+ "unknown request\n");
+ break;
}
}
}
@@ -577,6 +202,7 @@ plugin_start(Slapi_PBlock *pb)
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
slapi_log_error(SLAPI_LOG_PLUGIN, "plugin_start",
"plugin starting\n");
+ /* Register the listener sockets with the portmapper. */
if (state->resvport != -1) {
for (i = 0; i < state->n_listeners; i++) {
switch (state->sock_type[i]) {
@@ -606,14 +232,16 @@ plugin_start(Slapi_PBlock *pb)
}
}
}
- if (pthread_create(&state->tid, NULL, &process_requests, state) != 0) {
+ /* Start a new listening thread to handle incoming traffic. FIXME:
+ * switch to using NSPR's threading facilities. */
+ if (pthread_create(&state->tid, NULL, &listener_thread, state) != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN,
plugin_description.spd_id,
"error starting listener thread\n");
return -1;
}
- slapi_log_error(SLAPI_LOG_PLUGIN, "my_init_function",
- "plugin started\n");
+ slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id,
+ "plugin startup completed\n");
return 0;
}
@@ -624,6 +252,7 @@ plugin_close(Slapi_PBlock *pb)
struct plugin_state *state;
slapi_pblock_get(pb, SLAPI_PLUGIN_PRIVATE, &state);
if (state->resvport != -1) {
+ /* Clear our registration with the portmapper. */
portmap_unregister(state->resvport, YPPROG, YPVERS);
close(state->resvport);
}
@@ -631,7 +260,7 @@ plugin_close(Slapi_PBlock *pb)
}
static int
-setup_listeners(struct plugin_state **lstate)
+setup_listener_sockets(struct plugin_state **lstate)
{
int sockfd = -1, err, i;
struct plugin_state *state;
@@ -647,6 +276,9 @@ setup_listeners(struct plugin_state **lstate)
}
state->arena = arena;
+ /* Bind to a privileged port so that the portmapper will let us
+ * register after we've dropped to a non-root account. We could reuse
+ * the datagram listening socket we'll create later. */
state->resvport = socket(PF_INET, SOCK_DGRAM, 0);
if (bindresvport(state->resvport, NULL) != 0) {
slapi_log_error(SLAPI_LOG_PLUGIN,
@@ -657,6 +289,7 @@ setup_listeners(struct plugin_state **lstate)
state->resvport = -1;
}
+ /* Privileged port, datagram and stream, IPv4 and IPv6. */
for (i = 0; i < 4; i++) {
int sock_pf, sock_type, one = 1;
struct sockaddr *addr;
@@ -763,7 +396,7 @@ int
nis_plugin_init(Slapi_PBlock *pb)
{
struct plugin_state *state = NULL;
- if (setup_listeners(&state) == -1) {
+ if (setup_listener_sockets(&state) == -1) {
slapi_log_error(SLAPI_LOG_PLUGIN, plugin_description.spd_id,
"error setting up listening sockets\n");
return -1;