/*
* ldadp - ldap to ad proxy
*
* LDAP protocol handling based on tinyldap https://www.fefe.de/tinyldap/
*/
#include "types.h"
#include "epoll.h"
#include "client.h"
#include "server.h"
#include "proxy.h"
#include "ini.h"
#include "helper.h"
#include "openssl.h"
#include "helper.h"
#include <stdio.h>
#include <socket.h>
#include <io.h>
#include <string.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
static void listen_callback(void *data, int haveIn, int haveOut, int doCleanup);
static BOOL loadConfig(char *file);
static int localPort = 1234;
static char *certFile = NULL, *keyFile = NULL;
int main(int argc, char **argv)
{
BOOL isdaemon = TRUE;
if (argc < 2) {
printf("Nö\n");
exit(1);
}
setbuf(stdout, NULL);
signal(SIGPIPE, SIG_IGN);
if (strcmp(argv[1], "-n") == 0 && argc > 2) {
isdaemon = FALSE;
argv++;
argc--;
}
if (!loadConfig(argv[1])) bail("Cannot read config file %s", argv[1]);
if (localPort < 1 || localPort > 65535) bail("Invalid port given in config");
proxy_init();
char listen_addr[4] = {0, 0, 0, 0};
// Setup socket
epoll_listen_t lsn;
memset(&lsn, 0, sizeof(lsn));
lsn.callback = &listen_callback;
lsn.fd = socket_tcp4();
if (certFile != NULL && keyFile != NULL) {
printf("Using SSL\n");
ssl_init();
lsn.sslContext = ssl_newServerCtx(certFile, keyFile);
} else {
printf("Not using SSL\n");
}
if (lsn.fd == -1) bail("Could not create listen socket");
if (socket_bind4_reuse(lsn.fd, listen_addr, localPort) == -1) bail("Could not bind to listening port");
if (socket_listen(lsn.fd, 10) == -1) bail("Could not listen");
// Setup epoll
if (ePoll_init() == -1) bail("epoll_create failed");
// Add listener
if (ePoll_add(EPOLLIN, (epoll_item_t*)&lsn) == -1) bail("Could not add listen socket to epoll fd");
// Init AD uplinks
if (!server_initServers())
exit(1);
// Daeaeaemon
if (isdaemon && daemon(1, 0) == -1) bail("daemon() failed.");
// Do the mainloop
for (;;) {
if (ePoll_wait(-1) == -1) bail("ePoll wait failed.");
}
return 0;
}
static void listen_callback(void *data, int haveIn, int haveOut, int doCleanup)
{
if (doCleanup) bail("doCleanup on Listen socket set.");
if (!haveIn) return;
epoll_listen_t *listen = (epoll_listen_t *)data;
char remote[4];
uint16 port;
int sock = socket_accept4(listen->fd, remote, &port);
if (sock < 0) {
printf("[Proxy] Error accepting new connection.\n");
return;
}
helper_nonblock(sock);
SSL *ssl = NULL;
if (listen->sslContext != NULL) {
ssl = ssl_new(sock, listen->sslContext);
if (ssl == NULL) {
close(sock);
return;
}
}
epoll_client_t *client = calloc(1, sizeof(epoll_client_t));
client->fd = sock;
client->callback = &client_callback;
client->ssl = ssl;
if (ssl != NULL && !ssl_acceptClient(client)) {
printf("[Proxy] SSL-Accepting client failed.\n");
SSL_free(ssl);
close(sock);
free(client);
return;
}
ePoll_add(EPOLLIN | EPOLLOUT | EPOLLET | EPOLLRDHUP, (epoll_item_t*)client);
}
static int loadConfig_handler(void *stuff, const char *section, const char *key, const char *value)
{
if (strcmp(section, "local") == 0) {
if (strcmp(key, "port") == 0) {
localPort = atoi(value);
} else if (strcmp(key, "cert") == 0) {
certFile = strdup(value);
} else if (strcmp(key, "privkey") == 0) {
keyFile = strdup(value);
} else if (strcmp(key, "debug") == 0) {
_debugLevel = atoi(value);
} else {
printf("Unknown local config option '%s'\n", key);
}
} else {
if (strcmp(key, "binddn") == 0) {
server_setBind(section, value);
} else if (strcmp(key, "bindpw") == 0) {
server_setPassword(section, value);
} else if (strcmp(key, "base") == 0) {
server_setBase(section, value);
} else if (strcmp(key, "home") == 0) {
if (value[0] != '\0') server_setHomeTemplate(section, value);
} else if (strcmp(key, "homeattr") == 0) {
if (value[0] != '\0') server_setHomeAttribute(section, value);
} else if (strcmp(key, "fingerprint") == 0) {
if (value[0] != '\0') server_setFingerprint(section, value);
} else if (strcmp(key, "cabundle") == 0) {
if (value[0] != '\0') server_setCaBundle(section, value);
} else if (strcmp(key, "port") == 0) {
server_setPort(section, value);
} else if (strcmp(key, "plainldap") == 0) {
server_setPlainLdap(section, value);
} else if (strncmp(key, "map.", 4) == 0) {
server_setMap(section, key+4, value);
} else {
printf("Unknown ADS config option '%s' for server '%s'\n", key, section);
}
}
return 1;
}
static BOOL loadConfig(char *file)
{
return ini_parse(file, &loadConfig_handler, NULL) >= 0;
}