diff options
Diffstat (limited to 'server.c')
-rw-r--r-- | server.c | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/server.c b/server.c index b86d769..4c22287 100644 --- a/server.c +++ b/server.c @@ -17,7 +17,10 @@ #include <err.h> #include <netdb.h> #include <netinet/in.h> +#include <stdarg.h> +#include <stdio.h> #include <stdlib.h> +#include <string.h> #include <sys/socket.h> #include <sysexits.h> #include <tls.h> @@ -25,6 +28,8 @@ #include "bounce.h" +typedef unsigned char byte; + static struct tls *client; int serverConnect(const char *host, const char *port) { @@ -69,3 +74,77 @@ int serverConnect(const char *host, const char *port) { return sock; } + +void serverSend(const char *ptr, size_t len) { + while (len) { + ssize_t ret = tls_write(client, ptr, len); + if (ret == TLS_WANT_POLLIN || ret == TLS_WANT_POLLOUT) continue; + if (ret < 0) errx(EX_IOERR, "tls_write: %s", tls_error(client)); + ptr += ret; + len -= ret; + } +} + +static void format(const char *format, ...) { + char *buf; + va_list ap; + va_start(ap, format); + int len = vasprintf(&buf, format, ap); + va_end(ap); + if (!buf) err(EX_OSERR, "vasprintf"); + serverSend(format, len); + free(buf); +} + +static const char Base64[64] = { + "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/" +}; + +static char *base64(const byte *src, size_t len) { + char *dst = malloc(1 + (len + 2) / 3 * 4); + if (!dst) err(EX_OSERR, "malloc"); + + size_t i = 0; + while (len > 2) { + dst[i++] = Base64[0x3F & (src[0] >> 2)]; + dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)]; + dst[i++] = Base64[0x3F & (src[1] << 2 | src[2] >> 6)]; + dst[i++] = Base64[0x3F & src[2]]; + src += 3; + len -= 3; + } + + if (len) { + dst[i++] = Base64[0x3F & (src[0] >> 2)]; + if (len > 1) { + dst[i++] = Base64[0x3F & (src[0] << 4 | src[1] >> 4)]; + dst[i++] = Base64[0x3F & (src[1] << 2)]; + } else { + dst[i++] = Base64[0x3F & (src[0] << 4)]; + dst[i++] = '='; + } + dst[i++] = '='; + } + + dst[i] = '\0'; + return dst; +} + +static char *authBase64; + +void serverLogin( + const char *pass, const char *auth, + const char *nick, const char *user, const char *real +) { + if (pass) format("PASS :%s\r\n", pass); + if (auth) { + byte plain[1 + strlen(auth)]; + plain[0] = 0; + for (size_t i = 0; auth[i]; ++i) { + plain[1 + i] = (auth[i] == ':' ? 0 : auth[i]); + } + authBase64 = base64(plain, sizeof(plain)); + format("CAP REQ :sasl\r\n"); + } + format("NICK %s\r\nUSER %s 0 * :%s\r\n", nick, user, real); +} |