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/plugin.c | |
| parent | af4e31549b09a6cfb9774649c69c8ab769bee4ae (diff) | |
| download | slapi-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.c | 475 |
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; |
