summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Rettberg2018-03-12 15:28:33 +0100
committerSimon Rettberg2018-03-12 15:28:33 +0100
commite53dfcbdbed04cad690823ce5def521fea7b5483 (patch)
tree4a5d31e53515ad6a505d2cc4948abaa54a392b8c
parentAdd version information and --version (diff)
downloadldadp-e53dfcbdbed04cad690823ce5def521fea7b5483.tar.gz
ldadp-e53dfcbdbed04cad690823ce5def521fea7b5483.tar.xz
ldadp-e53dfcbdbed04cad690823ce5def521fea7b5483.zip
4s timeout when connecting to server; send error to client on failure
-rw-r--r--client.c36
-rw-r--r--client.h2
-rw-r--r--helper.c16
-rw-r--r--helper.h1
-rw-r--r--proxy.c4
-rw-r--r--server.c8
6 files changed, 50 insertions, 17 deletions
diff --git a/client.c b/client.c
index 2fbc560..41cda25 100644
--- a/client.c
+++ b/client.c
@@ -13,7 +13,7 @@
#define MAX_SEND_BUFFER 150000
static void client_haveIn(epoll_client_t *client);
-static void client_haveOut(epoll_client_t *client);
+static BOOL client_haveOut(epoll_client_t *client);
void client_free(epoll_client_t *client)
{
@@ -38,7 +38,9 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
if (client->ssl == NULL) {
// Plain connection
if (haveIn) client_haveIn(client);
- if (haveOut) client_haveOut(client);
+ if (haveOut || client->kill) {
+ if (client_haveOut(client)) return;
+ }
if (client->kill) {
//printf("Client gone (2).\n");
client_free(client);
@@ -57,7 +59,7 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup)
}
// Since we don't know if the incoming data is just wrapped application data or ssl protocol stuff, we always call both
client_haveIn(client);
- client_haveOut(client);
+ if (client_haveOut(client)) return;
if (client->kill) {
//printf("Client gone (3).\n");
client_free(client);
@@ -127,9 +129,15 @@ static void client_haveIn(epoll_client_t *client)
}
}
-static void client_haveOut(epoll_client_t *client)
+/**
+ * Send any queued data.
+ * Returns TRUE if anything has been sent, or the socket
+ * buffer is currently full (EAGAIN, non-blocking mode)
+ */
+static BOOL client_haveOut(epoll_client_t *client)
{
client->writeBlocked = FALSE;
+ if (client->sbPos >= client->sbFill) return FALSE;
while (client->sbPos < client->sbFill) {
const int tosend = client->sbFill - client->sbPos;
ssize_t ret;
@@ -137,11 +145,11 @@ static void client_haveOut(epoll_client_t *client)
// Plain
ret = write(client->fd, client->sendBuffer + client->sbPos, tosend);
if (ret < 0 && errno == EINTR) continue;
- if (ret < 0 && errno == EAGAIN) return;
+ if (ret < 0 && errno == EAGAIN) return TRUE;
if (ret <= 0) {
printf("[Proxy] Cannot send to client (ret=%d, errno=%d)\n", (int)ret, errno);
client->kill = TRUE;
- return;
+ return FALSE;
}
} else {
// SSL
@@ -150,12 +158,12 @@ static void client_haveOut(epoll_client_t *client)
int err = SSL_get_error(client->ssl, ret);
if (SSL_BLOCKED(err)) {
client->writeBlocked = TRUE;
- return; // Blocking
+ return TRUE; // Blocking
}
printf("[Proxy] SSL cannot send to client (ret=%d, err=%d)\n", (int)ret, err);
ERR_print_errors_fp(stdout);
client->kill = TRUE;
- return; // Closed
+ return FALSE; // Closed
}
}
client->sbPos += ret;
@@ -164,12 +172,13 @@ static void client_haveOut(epoll_client_t *client)
client->sbFill -= client->sbPos;
client->sbPos = 0;
}
- if (client->ssl == NULL && ret != tosend) return; // Sent less than requested -> buffer full, epoll will trigger us again
+ if (client->ssl == NULL && ret != tosend) return TRUE; // Sent less than requested -> buffer full, epoll will trigger us again
}
client->sbPos = client->sbFill = 0;
if (client->ssl == NULL && client->sbLen > MAX_SEND_BUFFER / 2) {
helper_realloc(&client->sendBuffer, &client->sbLen, 8000, "client_haveOut");
}
+ return TRUE;
}
BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const BOOL cork)
@@ -221,3 +230,12 @@ BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const B
return TRUE;
}
+BOOL client_searchResultError(epoll_client_t *client, const unsigned long messageId, const int code, const char *message)
+{
+ const size_t doneLen = fmt_ldapsearchresultdone(NULL, code, "", message, "");
+ const size_t doneHeaderLen = fmt_ldapmessage(NULL, messageId, SearchResultDone, doneLen);
+ char buffer[doneLen + doneHeaderLen];
+ fmt_ldapsearchresultdone(buffer + doneHeaderLen, code, "", message, "");
+ fmt_ldapmessage(buffer, messageId, SearchResultDone, doneLen);
+ return client_send(client, buffer, doneHeaderLen + doneLen, FALSE);
+}
diff --git a/client.h b/client.h
index 2cc8090..cd595ce 100644
--- a/client.h
+++ b/client.h
@@ -9,4 +9,6 @@ void client_callback(void *data, int haveIn, int haveOut, int doCleanup);
BOOL client_send(epoll_client_t *client, const char *buffer, size_t len, const BOOL cork);
+BOOL client_searchResultError(epoll_client_t *client, const unsigned long messageId, const int code, const char *message);
+
#endif
diff --git a/helper.c b/helper.c
index 2dc907e..6c51bab 100644
--- a/helper.c
+++ b/helper.c
@@ -46,7 +46,7 @@ int helper_connect4(char *address, int port, char *ip)
{
if (sizeof(struct in_addr) != 4) bail("Ach nöö ach nöö");
if (inet_pton(AF_INET, address, ip) == 1) {
- const int sock = socket_tcp4b();
+ const int sock = helper_newSocket();
if (sock == -1) return -1;
if (socket_connect4(sock, ip, port) == 0) {
return sock;
@@ -65,7 +65,7 @@ int helper_connect4(char *address, int port, char *ip)
return -1;
}
for (rp = result; rp != NULL; rp = rp->ai_next) {
- const int sock = socket_tcp4b();
+ const int sock = helper_newSocket();
if (sock == -1) continue;
if (rp->ai_addr != NULL) {
memcpy(ip, &((struct sockaddr_in*)rp->ai_addr)->sin_addr, 4);
@@ -80,6 +80,18 @@ int helper_connect4(char *address, int port, char *ip)
return -1;
}
+int helper_newSocket()
+{
+ struct timeval tv;
+ int sock = socket_tcp4b();
+ if (sock == -1) return -1;
+ tv.tv_sec = 4;
+ tv.tv_usec = 0;
+ setsockopt( sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv) );
+ setsockopt( sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv) );
+ return sock;
+}
+
void helper_nonblock(const int fd)
{
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK);
diff --git a/helper.h b/helper.h
index f2c895b..7aaece7 100644
--- a/helper.h
+++ b/helper.h
@@ -7,6 +7,7 @@
void bail(char *args, ...);
int helper_realloc(char **memory, size_t *curSize, const size_t newSize, const char *location);
int helper_connect4(char *address, int port, char *ip);
+int helper_newSocket();
void helper_nonblock(const int fd);
void helper_printava(struct AttributeValueAssertion* a,const char* rel);
diff --git a/proxy.c b/proxy.c
index 36f7cac..afb1bd8 100644
--- a/proxy.c
+++ b/proxy.c
@@ -809,7 +809,6 @@ static void response_replaceAttribute(server_t *server, const struct string * co
*/
static BOOL response_filterHomeDir(struct PartialAttributeList *pal)
{
- helper_printpal(pal);
for (struct AttributeDescriptionList *adl = pal->values; adl != NULL; adl = pal->values /* sic */) {
if (adl->a.s != NULL) {
if (adl->a.l > 0 && adl->a.s[0] == '\\') {
@@ -904,6 +903,7 @@ static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned lon
if (pending == NULL) {
plog(DEBUG_WARNING, "Cannot handle incoming client request; too many pending requests on the wire.");
free_ldapsearchrequest(&req);
+ client_searchResultError(client, messageId, busy, "I'm busy!");
return FALSE;
}
// In case of anonymous bind: Narrow down list of what the user can see to protect private data
@@ -935,7 +935,7 @@ static BOOL proxy_clientSearchRequest(epoll_client_t *client, const unsigned lon
pending->serverMessageId = server_searchRequestOnConnection(client->fixedServer, &req);
}
if (pending->serverMessageId == 0) {
- // Failed to forward.. TODO: Fail client
+ client_searchResultError(client, messageId, unavailable, "Cannot contact upstream server.");
plog(DEBUG_WARNING, "Failed to forward a search request to server.");
pending->client = NULL;
}
diff --git a/server.c b/server.c
index a4106f9..f22c5bf 100644
--- a/server.c
+++ b/server.c
@@ -696,17 +696,17 @@ static int server_connectInternal(server_t *server)
if (server->lastLookup + 300 < time(NULL)) {
sock = helper_connect4(server->addr, port, server->ip);
if (sock == -1) {
- printf("[Proxy] Could not resolve hostname or connect to AD server %s\n", server->addr);
+ printf("[Proxy] Could not resolve hostname or connect to AD server %s (errno=%d)\n", server->addr, errno);
return -1;
}
} else {
- sock = socket_tcp4b();
+ sock = helper_newSocket();
if (sock == -1) {
- printf("[Proxy] Could not allocate socket for connection to AD server %s\n", server->addr);
+ printf("[Proxy] Could not allocate socket for connection to AD server %s (errno=%d)\n", server->addr, errno);
return -1;
}
if (socket_connect4(sock, server->ip, port) == -1) {
- printf("[Proxy] Could not connect to cached IP (%s) of %s\n", server->ip, server->addr);
+ printf("[Proxy] Could not connect to cached IP (%s) of %s (errno=%d)\n", server->ip, server->addr, errno);
server->lastLookup = 0;
close(sock);
return -1;