From bb78a286dbc90d248bd7a9d29344de87051920f2 Mon Sep 17 00:00:00 2001 From: Simo Sorce Date: Fri, 18 Dec 2009 10:23:41 -0500 Subject: Fix ldap child memory hierarchy and other issues The timeout handler was not a child of the request so it could fire even though the request was already freed. The code wouldn't use async writes to the children so it could incur in a short write with no way to detect or recover from it. Also fixed style of some helper functions to pass explicit paramters instead of a general structure. Add common code to do async writes to pipes. Fixed async write issue for the krb5_child as well. Fix also sdap_kinit_done(), a return statement was missing and we were mixing SDAP_AUTH and errno return codes in state->result Remove usless helper function that just replicates talloc_strndup() --- server/providers/ldap/ldap_child.c | 64 +++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 28 deletions(-) (limited to 'server/providers/ldap/ldap_child.c') diff --git a/server/providers/ldap/ldap_child.c b/server/providers/ldap/ldap_child.c index 9c11bf401..4a577b87f 100644 --- a/server/providers/ldap/ldap_child.c +++ b/server/providers/ldap/ldap_child.c @@ -42,10 +42,11 @@ struct input_buffer { const char *keytab_name; }; -static errno_t unpack_buffer(uint8_t *buf, size_t size, struct input_buffer *ibuf) +static errno_t unpack_buffer(uint8_t *buf, size_t size, + struct input_buffer *ibuf) { size_t p = 0; - uint32_t *len; + uint32_t len; /* realm_str size and length */ DEBUG(7, ("total buffer size: %d\n", size)); @@ -53,47 +54,44 @@ static errno_t unpack_buffer(uint8_t *buf, size_t size, struct input_buffer *ibu DEBUG(1, ("Error: buffer too big!\n")); return EINVAL; } - len = ((uint32_t *)(buf+p)); + len = ((uint32_t *)(buf + p))[0]; p += sizeof(uint32_t); - DEBUG(7, ("realm_str size: %d\n", *len)); - if (*len) { - if ((p + *len ) > size) return EINVAL; - ibuf->realm_str = (char *) copy_buffer_and_add_zero(ibuf, buf+p, - sizeof(char) * (*len)); + DEBUG(7, ("realm_str size: %d\n", len)); + if (len) { + if ((p + len ) > size) return EINVAL; + ibuf->realm_str = talloc_strndup(ibuf, (char *)(buf + p), len); DEBUG(7, ("got realm_str: %s\n", ibuf->realm_str)); if (ibuf->realm_str == NULL) return ENOMEM; - p += *len; + p += len; } /* princ_str size and length */ if ((p + sizeof(uint32_t)) > size) return EINVAL; - len = ((uint32_t *)(buf+p)); + len = ((uint32_t *)(buf + p))[0]; p += sizeof(uint32_t); - DEBUG(7, ("princ_str size: %d\n", *len)); - if (*len) { - if ((p + *len ) > size) return EINVAL; - ibuf->princ_str = (char *) copy_buffer_and_add_zero(ibuf, buf+p, - sizeof(char) * (*len)); + DEBUG(7, ("princ_str size: %d\n", len)); + if (len) { + if ((p + len ) > size) return EINVAL; + ibuf->princ_str = talloc_strndup(ibuf, (char *)(buf + p), len); DEBUG(7, ("got princ_str: %s\n", ibuf->princ_str)); if (ibuf->princ_str == NULL) return ENOMEM; - p += *len; + p += len; } /* keytab_name size and length */ if ((p + sizeof(uint32_t)) > size) return EINVAL; - len = ((uint32_t *)(buf+p)); + len = ((uint32_t *)(buf + p))[0]; p += sizeof(uint32_t); - DEBUG(7, ("keytab_name size: %d\n", *len)); - if (*len) { - if ((p + *len ) > size) return EINVAL; - ibuf->keytab_name = (char *) copy_buffer_and_add_zero(ibuf, buf+p, - sizeof(char) * (*len)); + DEBUG(7, ("keytab_name size: %d\n", len)); + if (len) { + if ((p + len ) > size) return EINVAL; + ibuf->keytab_name = talloc_strndup(ibuf, (char *)(buf + p), len); DEBUG(7, ("got keytab_name: %s\n", ibuf->keytab_name)); if (ibuf->keytab_name == NULL) return ENOMEM; - p += *len; + p += len; } return EOK; @@ -321,6 +319,7 @@ int main(int argc, const char *argv[]) const char *ccname = NULL; struct input_buffer *ibuf = NULL; struct response *resp = NULL; + size_t written; struct poptOption long_options[] = { POPT_AUTOHELP @@ -346,6 +345,8 @@ int main(int argc, const char *argv[]) poptFreeContext(pc); + DEBUG(7, ("ldap_child started.\n")); + main_ctx = talloc_new(NULL); if (main_ctx == NULL) { DEBUG(1, ("talloc_new failed.\n")); @@ -414,11 +415,18 @@ int main(int argc, const char *argv[]) return ENOMEM; } - ret = write(STDOUT_FILENO, resp->buf, resp->size); - if (ret == -1) { - ret = errno; - DEBUG(1, ("write failed [%d][%s].\n", ret, strerror(ret))); - return errno; + written = 0; + while (written < resp->size) { + ret = write(STDOUT_FILENO, resp->buf + written, resp->size - written); + if (ret == -1) { + if (errno == EAGAIN || errno == EINTR) { + continue; + } + ret = errno; + DEBUG(1, ("write failed [%d][%s].\n", ret, strerror(ret))); + return ret; + } + written += ret; } close(STDOUT_FILENO); -- cgit