diff options
Diffstat (limited to 'src/nis.c')
-rw-r--r-- | src/nis.c | 247 |
1 files changed, 189 insertions, 58 deletions
@@ -19,8 +19,41 @@ #include "nis.h" #include "plugin.h" -#define DUMMY_KEY "leeroy" -#define DUMMY_VAL "jimbo:*K*:1234:5678:Leeroy Jenkins:/home/leeroy:/bin/bash" +static ssize_t +nis_write_with_retry(struct plugin_state *state, + int fd, const void *buffer, ssize_t length) +{ + ssize_t sent, i; + sent = 0; + while ((sent != -1) && (sent != length)) { + i = write(fd, ((unsigned char *)buffer) + sent, length - sent); + switch (i) { + case 0: + sent = -1; + break; + case -1: + switch (errno) { + case EAGAIN: + continue; + break; + default: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "Got error %s sending " + "%d bytes (at %d) to %d.\n", + strerror(errno), length, sent, + fd); + sent = -1; + break; + } + break; + default: + sent += i; + break; + } + } + return sent; +} /* Send a reply which _could_ be sent over a datagram. */ static void @@ -30,8 +63,7 @@ nis_reply_fragment(struct plugin_state *state, int client, bool_t first_fragment, bool_t last_fragment) { uint32_t len; - struct iovec iov[2]; - ssize_t i; + ssize_t i, sent; if (client_addr != NULL) { /* It's a datagram socket, so there's nothing to do but send * the data by itself. */ @@ -49,19 +81,19 @@ nis_reply_fragment(struct plugin_state *state, int client, /* Calculate the fragment length bytes. */ len = htonl(xdr_getpos(reply_xdrs) | (last_fragment ? 0x80000000 : 0)); - slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "Stream reply (4+%d bytes)\n", - xdr_getpos(reply_xdrs)); /* Send the data to the client. */ - iov[0].iov_base = &len; - iov[0].iov_len = 4; - iov[1].iov_base = reply_buf; - iov[1].iov_len = xdr_getpos(reply_xdrs); - i = writev(client, iov, 2); - if (i != (4 + xdr_getpos(reply_xdrs))) { + if ((nis_write_with_retry(state, client, &len, 4) == 4) && + (nis_write_with_retry(state, client, reply_buf, + xdr_getpos(reply_xdrs)) == + xdr_getpos(reply_xdrs))) { slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, - "Error sending stream reply!\n"); + "Stream reply (4+%d bytes) sent.\n", + xdr_getpos(reply_xdrs)); + } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "Stream reply (4+%d bytes) failed!\n"); } } } @@ -102,6 +134,9 @@ nis_domain(struct plugin_state *state, domain, *reply_bool ? "TRUE" : "FALSE"); } } else { + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "argument parsing error\n"); /* XXX */ } } @@ -150,6 +185,8 @@ nis_first(struct plugin_state *state, struct ypresp_key_val *reply_key_val) { struct ypreq_nokey req_nokey; + bool_t map_supported; + memset(&req_nokey, 0, sizeof(req_nokey)); memset(reply_key_val, 0, sizeof(*reply_key_val)); if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) { @@ -166,7 +203,11 @@ nis_first(struct plugin_state *state, req_nokey.map, reply_key_val->status); } else { - reply_key_val->status = YP_NOKEY; + map_supported = FALSE; + map_supports_map(state, req_nokey.domain, req_nokey.map, + &map_supported); + reply_key_val->status = map_supported ? YP_NOKEY : + YP_NOMAP; } nis_reply(state, client, client_addr, client_addrlen, reply, reply_xdrs, reply_buf); @@ -321,58 +362,100 @@ nis_all(struct plugin_state *state, int client, struct sockaddr *client_addr, socklen_t client_addrlen, XDR *request_xdrs, struct rpc_msg *reply, XDR *reply_xdrs, char *reply_buf, - bool_t *reply_more) + struct ypresp_all *reply_all) { - char domain[YPMAXDOMAIN + 1], *p; - int i; - keydat_t keydat; - bool_t more; struct ypreq_nokey req_nokey; - struct ypresp_key_val reply_key_val; + keydat_t *reply_key; + valdat_t *reply_val; + bool_t supported; - memset(&reply_key_val, 0, sizeof(reply_key_val)); - *reply_more = FALSE; memset(&req_nokey, 0, sizeof(req_nokey)); + reply_key = &reply_all->ypresp_all_u.val.keydat; + reply_val = &reply_all->ypresp_all_u.val.valdat; if (xdr_ypreq_nokey(request_xdrs, &req_nokey)) { - if (map_first(state, req_nokey.domain, req_nokey.map, - &reply_key_val.keydat.keydat_len, - &reply_key_val.keydat.keydat_val, - &reply_key_val.valdat.valdat_len, - &reply_key_val.valdat.valdat_val)) { - *reply_more = TRUE; + if (!map_supports_map(state, req_nokey.domain, req_nokey.map, + &supported) || + !supported) { + /* No entries? No such map final status. */ + reply_all->more = TRUE; + reply_all->ypresp_all_u.val.status = YP_NOMAP; + reply_key->keydat_len = 0; + reply_val->valdat_len = 0; nis_reply_fragment(state, client, client_addr, client_addrlen, reply, reply_xdrs, reply_buf, TRUE, FALSE); - slapi_log_error(SLAPI_LOG_PLUGIN, - state->plugin_desc->spd_id, - "all(%s/%s) -> %d\n", - req_nokey.domain, - req_nokey.map, - *reply_more); + /* End of data. */ + reply_all->more = FALSE; + xdr_setpos(reply_xdrs, 0); + xdr_ypresp_all(reply_xdrs, reply_all); + nis_reply_fragment(state, client, + client_addr, client_addrlen, + reply, reply_xdrs, reply_buf, + FALSE, TRUE); + } else { + bool_t first; + reply_all->more = TRUE; + reply_all->ypresp_all_u.val.status = YP_TRUE; + reply_all->more = map_first(state, + req_nokey.domain, + req_nokey.map, + &reply_key->keydat_len, + &reply_key->keydat_val, + &reply_val->valdat_len, + &reply_val->valdat_val); + first = TRUE; do { - xdr_setpos(reply_xdrs, 0); - xdr_ypresp_key_val(reply_xdrs, &reply_key_val); - keydat = reply_key_val.keydat; - more = map_next(state, - req_nokey.domain, req_nokey.map, - keydat.keydat_len, - keydat.keydat_val, - &reply_key_val.keydat.keydat_len, - &reply_key_val.keydat.keydat_val, - &reply_key_val.valdat.valdat_len, - &reply_key_val.valdat.valdat_val); - xdr_bool(reply_xdrs, &more); + /* Send back a result. If it's the first + * entry, also send back the reply header. */ + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "all(%s/%s) -> (%.*s),%d\n", + req_nokey.domain, + req_nokey.map, + reply_key->keydat_len, + reply_key->keydat_val, + reply_all->more); nis_reply_fragment(state, client, client_addr, client_addrlen, reply, reply_xdrs, reply_buf, - FALSE, !more); - } while(more); - } else { - *reply_more = FALSE; - nis_reply(state, client, - client_addr, client_addrlen, - reply, reply_xdrs, reply_buf); + first, FALSE); + first = FALSE; + /* Find the next entry. */ + reply_all->more = map_next(state, + req_nokey.domain, + req_nokey.map, + reply_key->keydat_len, + reply_key->keydat_val, + &reply_key->keydat_len, + &reply_key->keydat_val, + &reply_val->valdat_len, + &reply_val->valdat_val); + /* If we got an entry, encode it. */ + if (reply_all->more) { + xdr_setpos(reply_xdrs, 0); + xdr_ypresp_all(reply_xdrs, reply_all); + } + } while (reply_all->more); + /* Send the end-of-map marker. */ + reply_all->ypresp_all_u.val.status = YP_NOMORE; + reply_key->keydat_len = 0; + reply_val->valdat_len = 0; + xdr_setpos(reply_xdrs, 0); + reply_all->more = TRUE; + xdr_ypresp_all(reply_xdrs, reply_all); + /* End of data. */ + reply_all->more = FALSE; + xdr_ypresp_all(reply_xdrs, reply_all); + /* Bundle those two chunks into one reply. */ + nis_reply_fragment(state, client, + client_addr, client_addrlen, + reply, reply_xdrs, reply_buf, + FALSE, TRUE); + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "all(%s/%s) done\n", + req_nokey.domain, req_nokey.map); } } else { /* XXX */ @@ -394,6 +477,7 @@ nis_process_request(struct plugin_state *state, int client, int superuser, send_reply, auth_flavor, auth_len; struct ypresp_val reply_val; struct ypresp_key_val reply_key_val; + struct ypresp_all reply_all; struct ypresp_master reply_master; struct ypresp_order reply_order; struct ypresp_maplist reply_maplist; @@ -448,6 +532,12 @@ nis_process_request(struct plugin_state *state, int client, "validated auth_sys creds\n"); superuser = 0; break; + case AUTH_NONE: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "validated \"none\" creds\n"); + superuser = 0; + break; default: slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, @@ -478,6 +568,8 @@ nis_process_request(struct plugin_state *state, int client, auth_destroy(reply_auth); auth_len = xdr_getpos(&auth_xdrs); xdr_destroy(&auth_xdrs); + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "built reply authenticator\n"); /* Fill out the common RPC reply fields. */ reply.rm_xid = request.rm_xid; @@ -491,6 +583,8 @@ nis_process_request(struct plugin_state *state, int client, reply.rm_reply.rp_stat = MSG_DENIED; reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH; xdr_replymsg(&reply_xdrs, &reply); + slapi_log_error(SLAPI_LOG_PLUGIN, state->plugin_desc->spd_id, + "program request mismatch\n"); goto send_reply; } @@ -510,10 +604,17 @@ nis_process_request(struct plugin_state *state, int client, reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH; break; case YPPROC_NULL: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_null()\n"); /* Do nothing. The default successful reply is fine. */ break; case YPPROC_DOMAIN: case YPPROC_DOMAIN_NONACK: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + request.rm_call.cb_proc == YPPROC_DOMAIN ? + "yp_domain()\n" : "yp_domainnonack()\n"); /* Change the reply data to be a boolean. */ memset(&reply_bool, 0, sizeof(reply_bool)); accepted->ar_results.where = (caddr_t) &reply_bool; @@ -526,6 +627,9 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_MATCH: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_match()\n"); /* Change the reply data to be a resp_val. */ memset(&reply_val, 0, sizeof(reply_val)); accepted->ar_results.where = (caddr_t) &reply_val; @@ -537,6 +641,9 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_FIRST: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_first()\n"); /* Change the reply data to be a resp_key_val. */ memset(&reply_key_val, 0, sizeof(reply_key_val)); accepted->ar_results.where = (caddr_t) &reply_key_val; @@ -548,6 +655,9 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_NEXT: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_next()\n"); /* Change the reply data to be a resp_key_val. */ memset(&reply_key_val, 0, sizeof(reply_key_val)); accepted->ar_results.where = (caddr_t) &reply_key_val; @@ -559,23 +669,35 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_XFR: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_xfr()\n"); /* Do nothing. The default successful reply is fine. */ break; case YPPROC_CLEAR: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_clear()\n"); /* Do nothing. The default successful reply is fine. */ break; case YPPROC_ALL: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_all()\n"); /* Set the result type to a boolean. */ - memset(&reply_bool, 0, sizeof(reply_bool)); - accepted->ar_results.where = (caddr_t) &reply_bool; - accepted->ar_results.proc = (xdrproc_t) &xdr_bool; + memset(&reply_all, 0, sizeof(reply_all)); + accepted->ar_results.where = (caddr_t) &reply_all; + accepted->ar_results.proc = (xdrproc_t) &xdr_ypresp_all; /* Call the real function. */ nis_all(state, client, client_addr, client_addrlen, &request_xdrs, - &reply, &reply_xdrs, reply_buf, &reply_bool); + &reply, &reply_xdrs, reply_buf, &reply_all); goto sent_reply; break; case YPPROC_MASTER: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_master()\n"); /* Change reply type to be a resp_master. */ memset(&reply_master, 0, sizeof(reply_master)); accepted->ar_results.where = (caddr_t) &reply_master; @@ -587,6 +709,9 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_ORDER: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_order()\n"); /* Change reply type to be a resp_order. */ memset(&reply_order, 0, sizeof(reply_order)); accepted->ar_results.where = (caddr_t) &reply_order; @@ -598,6 +723,9 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_MAPLIST: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_maplist()\n"); /* Change reply type to be a resp_maplist. */ memset(&reply_maplist, 0, sizeof(reply_maplist)); accepted->ar_results.where = (caddr_t) &reply_maplist; @@ -609,6 +737,9 @@ nis_process_request(struct plugin_state *state, int client, goto sent_reply; break; case YPPROC_NEWXFR: + slapi_log_error(SLAPI_LOG_PLUGIN, + state->plugin_desc->spd_id, + "yp_newxfr()\n"); reply.rm_reply.rp_stat = MSG_DENIED; reply.rm_reply.rp_rjct.rj_stat = RPC_MISMATCH; break; |