diff options
-rw-r--r-- | source4/lib/util_sock.c | 175 | ||||
-rw-r--r-- | source4/libcli/ldap/ldap_client.c | 240 | ||||
-rw-r--r-- | source4/libcli/util/asn1.c | 61 | ||||
-rw-r--r-- | source4/torture/ldap/common.c | 65 |
4 files changed, 299 insertions, 242 deletions
diff --git a/source4/lib/util_sock.c b/source4/lib/util_sock.c index 1859aef4d7..b2f949ebe5 100644 --- a/source4/lib/util_sock.c +++ b/source4/lib/util_sock.c @@ -122,178 +122,3 @@ void set_socket_options(int fd, const char *options) } } - -/**************************************************************************** - Check the timeout. -****************************************************************************/ -static BOOL timeout_until(struct timeval *timeout, - const struct timeval *endtime) -{ - struct timeval now; - - GetTimeOfDay(&now); - - if ((now.tv_sec > endtime->tv_sec) || - ((now.tv_sec == endtime->tv_sec) && - (now.tv_usec > endtime->tv_usec))) - return False; - - timeout->tv_sec = endtime->tv_sec - now.tv_sec; - timeout->tv_usec = endtime->tv_usec - now.tv_usec; - return True; -} - - -/**************************************************************************** - Read data from the client, reading exactly N bytes, with timeout. -****************************************************************************/ -ssize_t read_data_until(int fd,char *buffer,size_t N, - const struct timeval *endtime) -{ - ssize_t ret; - size_t total=0; - - while (total < N) { - - if (endtime != NULL) { - fd_set r_fds; - struct timeval timeout; - int res; - - FD_ZERO(&r_fds); - FD_SET(fd, &r_fds); - - if (!timeout_until(&timeout, endtime)) - return -1; - - res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout); - if (res <= 0) - return -1; - } - - ret = sys_read(fd,buffer + total,N - total); - - if (ret == 0) { - DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); - return 0; - } - - if (ret == -1) { - DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); - return -1; - } - total += ret; - } - return (ssize_t)total; -} - - -/**************************************************************************** - Write data to a fd with timeout. -****************************************************************************/ -ssize_t write_data_until(int fd,char *buffer,size_t N, - const struct timeval *endtime) -{ - size_t total=0; - ssize_t ret; - - while (total < N) { - - if (endtime != NULL) { - fd_set w_fds; - struct timeval timeout; - int res; - - FD_ZERO(&w_fds); - FD_SET(fd, &w_fds); - - if (!timeout_until(&timeout, endtime)) - return -1; - - res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout); - if (res <= 0) - return -1; - } - - ret = sys_write(fd,buffer + total,N - total); - - if (ret == -1) { - DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); - return -1; - } - if (ret == 0) - return total; - - total += ret; - } - return (ssize_t)total; -} - - - -/**************************************************************************** - create an outgoing socket. timeout is in milliseconds. - **************************************************************************/ -int open_socket_out(int type, struct ipv4_addr *addr, int port, int timeout) -{ - struct sockaddr_in sock_out; - int res,ret; - int connect_loop = 250; /* 250 milliseconds */ - int loops = (timeout) / connect_loop; - - /* create a socket to write to */ - res = socket(PF_INET, type, 0); - if (res == -1) - { DEBUG(0,("socket error\n")); return -1; } - - if (type != SOCK_STREAM) return(res); - - memset((char *)&sock_out,'\0',sizeof(sock_out)); - putip((char *)&sock_out.sin_addr,(char *)addr); - - sock_out.sin_port = htons( port ); - sock_out.sin_family = PF_INET; - - /* set it non-blocking */ - set_blocking(res,False); - - DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port)); - - /* and connect it to the destination */ -connect_again: - ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); - - /* Some systems return EAGAIN when they mean EINPROGRESS */ - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN) && loops--) { - msleep(connect_loop); - goto connect_again; - } - - if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || - errno == EAGAIN)) { - DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port)); - close(res); - return -1; - } - -#ifdef EISCONN - if (ret < 0 && errno == EISCONN) { - errno = 0; - ret = 0; - } -#endif - - if (ret < 0) { - DEBUG(2,("error connecting to %s:%d (%s)\n", - sys_inet_ntoa(*addr),port,strerror(errno))); - close(res); - return -1; - } - - /* set it blocking again */ - set_blocking(res,True); - - return res; -} - diff --git a/source4/libcli/ldap/ldap_client.c b/source4/libcli/ldap/ldap_client.c index c9e81ac28f..73099ec1be 100644 --- a/source4/libcli/ldap/ldap_client.c +++ b/source4/libcli/ldap/ldap_client.c @@ -29,6 +29,246 @@ #include "asn_1.h" #include "dlinklist.h" + + +/**************************************************************************** + Check the timeout. +****************************************************************************/ +static BOOL timeout_until(struct timeval *timeout, + const struct timeval *endtime) +{ + struct timeval now; + + GetTimeOfDay(&now); + + if ((now.tv_sec > endtime->tv_sec) || + ((now.tv_sec == endtime->tv_sec) && + (now.tv_usec > endtime->tv_usec))) + return False; + + timeout->tv_sec = endtime->tv_sec - now.tv_sec; + timeout->tv_usec = endtime->tv_usec - now.tv_usec; + return True; +} + + +/**************************************************************************** + Read data from the client, reading exactly N bytes, with timeout. +****************************************************************************/ +static ssize_t read_data_until(int fd,char *buffer,size_t N, + const struct timeval *endtime) +{ + ssize_t ret; + size_t total=0; + + while (total < N) { + + if (endtime != NULL) { + fd_set r_fds; + struct timeval timeout; + int res; + + FD_ZERO(&r_fds); + FD_SET(fd, &r_fds); + + if (!timeout_until(&timeout, endtime)) + return -1; + + res = sys_select(fd+1, &r_fds, NULL, NULL, &timeout); + if (res <= 0) + return -1; + } + + ret = sys_read(fd,buffer + total,N - total); + + if (ret == 0) { + DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", (int)(N - total), strerror(errno) )); + return 0; + } + + if (ret == -1) { + DEBUG(0,("read_data: read failure for %d. Error = %s\n", (int)(N - total), strerror(errno) )); + return -1; + } + total += ret; + } + return (ssize_t)total; +} + + +/**************************************************************************** + Write data to a fd with timeout. +****************************************************************************/ +static ssize_t write_data_until(int fd,char *buffer,size_t N, + const struct timeval *endtime) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + + if (endtime != NULL) { + fd_set w_fds; + struct timeval timeout; + int res; + + FD_ZERO(&w_fds); + FD_SET(fd, &w_fds); + + if (!timeout_until(&timeout, endtime)) + return -1; + + res = sys_select(fd+1, NULL, &w_fds, NULL, &timeout); + if (res <= 0) + return -1; + } + + ret = sys_write(fd,buffer + total,N - total); + + if (ret == -1) { + DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (ret == 0) + return total; + + total += ret; + } + return (ssize_t)total; +} + + + +static BOOL read_one_uint8(int sock, uint8_t *result, struct asn1_data *data, + const struct timeval *endtime) +{ + if (read_data_until(sock, result, 1, endtime) != 1) + return False; + + return asn1_write(data, result, 1); +} + +/* Read a complete ASN sequence (ie LDAP result) from a socket */ +static BOOL asn1_read_sequence_until(int sock, struct asn1_data *data, + const struct timeval *endtime) +{ + uint8_t b; + size_t len; + char *buf; + + ZERO_STRUCTP(data); + + if (!read_one_uint8(sock, &b, data, endtime)) + return False; + + if (b != 0x30) { + data->has_error = True; + return False; + } + + if (!read_one_uint8(sock, &b, data, endtime)) + return False; + + if (b & 0x80) { + int n = b & 0x7f; + if (!read_one_uint8(sock, &b, data, endtime)) + return False; + len = b; + while (n > 1) { + if (!read_one_uint8(sock, &b, data, endtime)) + return False; + len = (len<<8) | b; + n--; + } + } else { + len = b; + } + + buf = talloc_size(NULL, len); + if (buf == NULL) + return False; + + if (read_data_until(sock, buf, len, endtime) != len) + return False; + + if (!asn1_write(data, buf, len)) + return False; + + talloc_free(buf); + + data->ofs = 0; + + return True; +} + + + +/**************************************************************************** + create an outgoing socket. timeout is in milliseconds. + **************************************************************************/ +static int open_socket_out(int type, struct ipv4_addr *addr, int port, int timeout) +{ + struct sockaddr_in sock_out; + int res,ret; + int connect_loop = 250; /* 250 milliseconds */ + int loops = (timeout) / connect_loop; + + /* create a socket to write to */ + res = socket(PF_INET, type, 0); + if (res == -1) + { DEBUG(0,("socket error\n")); return -1; } + + if (type != SOCK_STREAM) return(res); + + memset((char *)&sock_out,'\0',sizeof(sock_out)); + putip((char *)&sock_out.sin_addr,(char *)addr); + + sock_out.sin_port = htons( port ); + sock_out.sin_family = PF_INET; + + /* set it non-blocking */ + set_blocking(res,False); + + DEBUG(3,("Connecting to %s at port %d\n", sys_inet_ntoa(*addr),port)); + + /* and connect it to the destination */ +connect_again: + ret = connect(res,(struct sockaddr *)&sock_out,sizeof(sock_out)); + + /* Some systems return EAGAIN when they mean EINPROGRESS */ + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN) && loops--) { + msleep(connect_loop); + goto connect_again; + } + + if (ret < 0 && (errno == EINPROGRESS || errno == EALREADY || + errno == EAGAIN)) { + DEBUG(1,("timeout connecting to %s:%d\n", sys_inet_ntoa(*addr),port)); + close(res); + return -1; + } + +#ifdef EISCONN + if (ret < 0 && errno == EISCONN) { + errno = 0; + ret = 0; + } +#endif + + if (ret < 0) { + DEBUG(2,("error connecting to %s:%d (%s)\n", + sys_inet_ntoa(*addr),port,strerror(errno))); + close(res); + return -1; + } + + /* set it blocking again */ + set_blocking(res,True); + + return res; +} + #if 0 static struct ldap_message *new_ldap_search_message(struct ldap_connection *conn, const char *base, diff --git a/source4/libcli/util/asn1.c b/source4/libcli/util/asn1.c index 550450fea7..1124cc1701 100644 --- a/source4/libcli/util/asn1.c +++ b/source4/libcli/util/asn1.c @@ -379,67 +379,6 @@ BOOL asn1_start_tag(struct asn1_data *data, uint8_t tag) return !data->has_error; } -static BOOL read_one_uint8(int sock, uint8_t *result, struct asn1_data *data, - const struct timeval *endtime) -{ - if (read_data_until(sock, result, 1, endtime) != 1) - return False; - - return asn1_write(data, result, 1); -} - -/* Read a complete ASN sequence (ie LDAP result) from a socket */ -BOOL asn1_read_sequence_until(int sock, struct asn1_data *data, - const struct timeval *endtime) -{ - uint8_t b; - size_t len; - char *buf; - - ZERO_STRUCTP(data); - - if (!read_one_uint8(sock, &b, data, endtime)) - return False; - - if (b != 0x30) { - data->has_error = True; - return False; - } - - if (!read_one_uint8(sock, &b, data, endtime)) - return False; - - if (b & 0x80) { - int n = b & 0x7f; - if (!read_one_uint8(sock, &b, data, endtime)) - return False; - len = b; - while (n > 1) { - if (!read_one_uint8(sock, &b, data, endtime)) - return False; - len = (len<<8) | b; - n--; - } - } else { - len = b; - } - - buf = talloc_size(NULL, len); - if (buf == NULL) - return False; - - if (read_data_until(sock, buf, len, endtime) != len) - return False; - - if (!asn1_write(data, buf, len)) - return False; - - talloc_free(buf); - - data->ofs = 0; - - return True; -} /* Get the length to be expected in buf */ BOOL asn1_object_length(uint8_t *buf, size_t buf_length, diff --git a/source4/torture/ldap/common.c b/source4/torture/ldap/common.c index 162934a38d..b9f0f5c655 100644 --- a/source4/torture/ldap/common.c +++ b/source4/torture/ldap/common.c @@ -103,6 +103,61 @@ NTSTATUS torture_ldap_close(struct ldap_connection *conn) return NT_STATUS_OK; } + +/* + Write data to a fd +*/ +static ssize_t write_data(int fd, char *buffer, size_t N) +{ + size_t total=0; + ssize_t ret; + + while (total < N) { + ret = sys_write(fd,buffer + total,N - total); + + if (ret == -1) { + DEBUG(0,("write_data: write failure. Error = %s\n", strerror(errno) )); + return -1; + } + if (ret == 0) + return total; + + total += ret; + } + + return (ssize_t)total; +} + + +/* + Read data from the client, reading exactly N bytes +*/ +static ssize_t read_data(int fd, char *buffer, size_t N) +{ + ssize_t ret; + size_t total=0; + + while (total < N) { + + ret = sys_read(fd,buffer + total,N - total); + + if (ret == 0) { + DEBUG(10,("read_data: read of %d returned 0. Error = %s\n", + (int)(N - total), strerror(errno) )); + return 0; + } + + if (ret == -1) { + DEBUG(0,("read_data: read failure for %d. Error = %s\n", + (int)(N - total), strerror(errno) )); + return -1; + } + total += ret; + } + + return (ssize_t)total; +} + BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg, const struct timeval *endtime) { @@ -131,26 +186,24 @@ BOOL ldap_sasl_send_msg(struct ldap_connection *conn, struct ldap_message *msg, RSIVAL(length, 0, wrapped.length); - result = (write_data_until(conn->sock, length, 4, - endtime) == 4); + result = (write_data(conn->sock, length, 4) == 4); if (!result) return result; - result = (write_data_until(conn->sock, wrapped.data, wrapped.length, - endtime) == wrapped.length); + result = (write_data(conn->sock, wrapped.data, wrapped.length) == wrapped.length); if (!result) return result; wrapped = data_blob(NULL, 0x4000); data_blob_clear(&wrapped); - result = (read_data_until(conn->sock, length, 4, NULL) == 4); + result = (read_data(conn->sock, length, 4) == 4); if (!result) return result; len = RIVAL(length,0); - result = (read_data_until(conn->sock, wrapped.data, MIN(wrapped.length,len), NULL) == len); + result = (read_data(conn->sock, wrapped.data, MIN(wrapped.length,len)) == len); if (!result) return result; |