diff options
| author | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2007-11-29 13:15:47 -0500 |
|---|---|---|
| committer | Nalin Dahyabhai <nalin.dahyabhai@pobox.com> | 2007-11-29 13:15:47 -0500 |
| commit | f82215df2d4af8456d7228628ea5a6678ed908dd (patch) | |
| tree | 941619407c77e54e88d6649918278fb9e218840b /src | |
| parent | af4e31549b09a6cfb9774649c69c8ab769bee4ae (diff) | |
- split up some more
Diffstat (limited to 'src')
| -rw-r--r-- | src/Makefile | 2 | ||||
| -rw-r--r-- | src/nis.c | 337 | ||||
| -rw-r--r-- | src/nis.h | 12 | ||||
| -rw-r--r-- | src/plugin.c | 475 | ||||
| -rw-r--r-- | src/stream.c | 86 | ||||
| -rw-r--r-- | src/stream.h | 2 |
6 files changed, 464 insertions, 450 deletions
diff --git a/src/Makefile b/src/Makefile index d54f2dd..ee93e37 100644 --- a/src/Makefile +++ b/src/Makefile @@ -3,7 +3,7 @@ LDFLAGS = -lnsl -lpthread all:: plugin.so portmap -plugin.so: plugin.c portmap.c schema.c stream.c +plugin.so: plugin.c portmap.c schema.c stream.c nis.c $(CC) $(CFLAGS) -shared -o $@ $^ $(LDFLAGS) portmap: portmap.c $(CC) $(CFLAGS) -o $@ -DPORTMAP_MAIN $^ $(LDFLAGS) diff --git a/src/nis.c b/src/nis.c new file mode 100644 index 0000000..6090a18 --- /dev/null +++ b/src/nis.c @@ -0,0 +1,337 @@ +#ifdef HAVE_CONFIG_H +#include "../config.h" +#endif + +#include <sys/types.h> +#include <sys/socket.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +#include <rpc/rpc.h> +#include <rpc/pmap_clnt.h> +#include <rpcsvc/yp_prot.h> + +#include "nis.h" +#include "plugin.h" +#include "schema.h" + +void +nis_process_request(struct plugin_state *state, int client, + struct sockaddr *client_addr, socklen_t client_addrlen, + char *request_buf, size_t request_buflen) +{ + 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, request_buf, request_buflen, XDR_DECODE); + if (xdr_callmsg(&request_xdrs, &request) && + (request.rm_direction == CALL)) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->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, + state->plugin_desc->spd_id, + "validated auth_sys creds\n"); + superuser = 0; + break; + default: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "validated other creds\n"); + superuser = 0; + break; + } + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->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; + break; + 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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->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, + state->plugin_desc->spd_id, + "encoding reply\n"); + if (client_addr != NULL) { + xdr_replymsg(&reply_xdrs, &reply); + sendto(client, + 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, + state->plugin_desc->spd_id, + "sending %d bytes\n", + xdr_getpos(&reply_xdrs)); + send(client, 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, + state->plugin_desc->spd_id, + "sending %d bytes\n", + xdr_getpos(&reply_xdrs)); + send(client, reply_buf, + xdr_getpos(&reply_xdrs), 0); + } + } + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "sent reply\n"); + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "suppressed reply\n"); + } + } + xdr_destroy(&reply_xdrs); + } + xdr_destroy(&request_xdrs); +} diff --git a/src/nis.h b/src/nis.h new file mode 100644 index 0000000..681eec7 --- /dev/null +++ b/src/nis.h @@ -0,0 +1,12 @@ +#ifndef nis_h +#define nis_h + +#include <sys/types.h> +#include <sys/socket.h> +#include "plugin.h" + +void nis_process_request(struct plugin_state *state, int client, + struct sockaddr *client_addr, socklen_t client_addrlen, + char *request_buf, size_t request_buflen); + +#endif 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; diff --git a/src/stream.c b/src/stream.c index ebf8c7f..dbb53bf 100644 --- a/src/stream.c +++ b/src/stream.c @@ -4,21 +4,15 @@ #include <sys/types.h> #include <sys/socket.h> -#include <sys/stat.h> #include <errno.h> #include <fcntl.h> #include <poll.h> #include <pthread.h> -#include <stdlib.h> -#include <string.h> -#include <syslog.h> #include <unistd.h> -#include <nspr.h> -#include <secport.h> -#include <dirsrv/slapi-plugin.h> - +#include "nis.h" #include "stream.h" +#define MAX_CLIENT_IDLE (60 * 1000) struct stream_client_thread_parms { int client; @@ -35,26 +29,33 @@ stream_client_thread(void *arg) struct stream_client_thread_parms *parms = arg; struct plugin_state *state = parms->state; - int client = parms->client; + int done, client = parms->client; free(parms); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "opened client connection %d, thread started\n", + client); last = fcntl(client, F_GETFD); if ((last == -1) || (fcntl(client, F_SETFD, last | O_NONBLOCK) == -1)) { slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc.spd_id, + state->plugin_desc->spd_id, "error setting new client connection to be " "non-blocking\n"); close(client); - client = -1; return NULL; } + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "set new client connection to be non-blocking\n"); frag_len = 0; record_len = 0; - while (client != -1) { + done = 0; + while (!done) { pollfd.fd = client; pollfd.events = POLLIN | POLLHUP; - if (poll(&pollfd, 1, 60 * 1000) > 0) { + if (poll(&pollfd, 1, MAX_CLIENT_IDLE) > 0) { i = read(client, fragment + frag_len, sizeof(fragment) - frag_len); switch (i) { @@ -63,37 +64,57 @@ stream_client_thread(void *arg) continue; } slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc.spd_id, + state->plugin_desc->spd_id, "communication error\n"); - close(client); - client = -1; + done = 1; break; case 0: slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc.spd_id, + state->plugin_desc->spd_id, "client closed connection\n"); - close(client); - client = -1; + done = 1; break; default: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "read %d bytes\n", i); frag_len += i; break; } if (frag_len > 4) { memcpy(&nlen, fragment, 4); len = ntohl(nlen); - last = ((len >> 31) == 1); + last = ((len & 0x80000000) != 0); len &= 0x7fffffff; + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "expecting %d bytes\n", len); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "in: frag_len=%d,record=%d\n", + frag_len, record_len); if (frag_len >= len + 4) { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "got whole fragment " + "(%d bytes)\n", len); /* we have a whole fragment */ memmove(record + record_len, fragment + 4, len); record_len += len; if (last) { - /* we have a whole record */ - process_request(state, client, - record, + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "got whole " + "record (%d " + "bytes)\n", record_len); + /* we have a whole record */ + nis_process_request(state, + client, + NULL, 0, + record, + record_len); record_len = 0; } memmove(fragment, @@ -101,16 +122,22 @@ stream_client_thread(void *arg) frag_len - (len + 4)); frag_len -= (len + 4); } + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "out: frag_len=%d,record=%d\n", + frag_len, record_len); } } else { slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc.spd_id, + state->plugin_desc->spd_id, "connection timeout\n"); - close(client); - client = -1; + done = 1; } } close(client); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "closed client connection %d, thread ending\n", client); return NULL; } @@ -123,7 +150,7 @@ stream_client_start(struct plugin_state *state, int client) parms = malloc(sizeof(*parms)); if (parms == NULL) { slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc.spd_id, + state->plugin_desc->spd_id, "out of memory\n"); close(client); return; @@ -133,9 +160,12 @@ stream_client_start(struct plugin_state *state, int client) if (pthread_create(&thread, NULL, &stream_client_thread, parms) != 0) { slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc.spd_id, + state->plugin_desc->spd_id, "error starting thread\n"); close(client); } + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "started client-specific thread\n"); return; } diff --git a/src/stream.h b/src/stream.h index 443e3cd..a5de9b9 100644 --- a/src/stream.h +++ b/src/stream.h @@ -1,6 +1,8 @@ #ifndef stream_h #define stream_h +#include "plugin.h" + void stream_client_start(struct plugin_state *state, int client); #endif |
