From: pk910 Date: Thu, 24 Jul 2014 08:48:08 +0000 (+0200) Subject: Merge remote-tracking branch 'IOMultiplexer/v2' X-Git-Url: http://git.pk910.de/?p=NextIRCd.git;a=commitdiff_plain;h=e17a8a5dc929df2a5ae6169f1955fcde7c70e04b Merge remote-tracking branch 'IOMultiplexer/v2' Conflicts: src/IOHandler/IODNSLookup.c src/IOHandler/IODNSLookup.h --- e17a8a5dc929df2a5ae6169f1955fcde7c70e04b diff --cc configure.ac index 44f4e88,4275959..aa5b500 --- a/configure.ac +++ b/configure.ac @@@ -36,22 -36,22 +36,14 @@@ AC_CHECK_FUNCS([usleep select socket in AC_CHECK_HEADERS([fcntl.h sys/socket.h sys/select.h sys/time.h sys/types.h unistd.h windows.h winsock2.h errno.h sys/epoll.h sys/event.h]) AC_CHECK_LIB(ws2_32, main, [ LIBS="$LIBS -lws2_32" ], []) --have_gnutls="no" --AC_CHECK_LIB(gnutls, gnutls_init, [ -- AC_CHECK_HEADERS(gnutls/gnutls.h, [ -- LIBS="$LIBS -lgnutls" -- have_gnutls="yes" -- ]) --]) --if test x"$have_gnutls" = xno; then -- AC_CHECK_LIB(ssl, SSL_read, [ -- AC_CHECK_LIB(crypto, X509_new, [ -- AC_CHECK_HEADERS(openssl/ssl.h openssl/err.h openssl/rand.h, [ -- LIBS="$LIBS -lssl -lcrypto" -- ]) ++ ++AC_CHECK_LIB(ssl, SSL_read, [ ++ AC_CHECK_LIB(crypto, X509_new, [ ++ AC_CHECK_HEADERS(openssl/ssl.h openssl/err.h openssl/rand.h, [ ++ LIBS="$LIBS -lssl -lcrypto" ]) ]) --fi ++]) AC_CHECK_LIB(pthread, pthread_create, [ AC_CHECK_HEADERS(pthread.h, [ LIBS="$LIBS -lpthread" diff --cc src/crypt_base64.c index 2e54c92,0000000..60e10ee mode 100644,000000..100644 --- a/src/crypt_base64.c +++ b/src/crypt_base64.c @@@ -1,102 -1,0 +1,105 @@@ +/* crypt_base64.c - NextIRCd + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "crypt_base64.h" +#include +#include + +static char encoding_table[] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', + 'I', 'J', 'K', 'L', 'M', 'N', 'O', 'P', + 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', + 'Y', 'Z', 'a', 'b', 'c', 'd', 'e', 'f', + 'g', 'h', 'i', 'j', 'k', 'l', 'm', 'n', + 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', + 'w', 'x', 'y', 'z', '0', '1', '2', '3', + '4', '5', '6', '7', '8', '9', '+', '/'}; +static char *decoding_table = NULL; +static int mod_table[] = {0, 2, 1}; + + +char *crypt_base64_encode(const unsigned char *data, size_t input_length, size_t *output_length) { + *output_length = 4 * ((input_length + 2) / 3); + + char *encoded_data = malloc(*output_length); + if (encoded_data == NULL) + return NULL; + - for (int i = 0, j = 0; i < input_length;) { ++ int i, j; ++ for (i = 0, j = 0; i < input_length;) { + uint32_t octet_a = i < input_length ? (unsigned char)data[i++] : 0; + uint32_t octet_b = i < input_length ? (unsigned char)data[i++] : 0; + uint32_t octet_c = i < input_length ? (unsigned char)data[i++] : 0; + + uint32_t triple = (octet_a << 0x10) + (octet_b << 0x08) + octet_c; + + encoded_data[j++] = encoding_table[(triple >> 3 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 2 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 1 * 6) & 0x3F]; + encoded_data[j++] = encoding_table[(triple >> 0 * 6) & 0x3F]; + } + - for (int i = 0; i < mod_table[input_length % 3]; i++) ++ for (i = 0; i < mod_table[input_length % 3]; i++) + encoded_data[*output_length - 1 - i] = '='; + + return encoded_data; +} + + +unsigned char *crypt_base64_decode(const char *data, size_t input_length, size_t *output_length) { + if (decoding_table == NULL) + crypt_base64_init(); + if (input_length % 4 != 0) + return NULL; + + *output_length = input_length / 4 * 3; + if (data[input_length - 1] == '=') (*output_length)--; + if (data[input_length - 2] == '=') (*output_length)--; + + unsigned char *decoded_data = malloc(*output_length); + if (decoded_data == NULL) + return NULL; + - for (int i = 0, j = 0; i < input_length;) { ++ int i, j; ++ for (i = 0, j = 0; i < input_length;) { + uint32_t sextet_a = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_b = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_c = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + uint32_t sextet_d = data[i] == '=' ? 0 & i++ : decoding_table[data[i++]]; + + uint32_t triple = (sextet_a << 3 * 6) + + (sextet_b << 2 * 6) + + (sextet_c << 1 * 6) + + (sextet_d << 0 * 6); + + if (j < *output_length) decoded_data[j++] = (triple >> 2 * 8) & 0xFF; + if (j < *output_length) decoded_data[j++] = (triple >> 1 * 8) & 0xFF; + if (j < *output_length) decoded_data[j++] = (triple >> 0 * 8) & 0xFF; + } + + return decoded_data; +} + + +void crypt_base64_init() { + decoding_table = malloc(256); - for (int i = 0; i < 64; i++) ++ int i; ++ for (i = 0; i < 64; i++) + decoding_table[(unsigned char) encoding_table[i]] = i; +} + +void crypt_base64_deinit() { + free(decoding_table); +} diff --cc src/crypt_base64.h index 5ada93c,0000000..2892573 mode 100644,000000..100644 --- a/src/crypt_base64.h +++ b/src/crypt_base64.h @@@ -1,27 -1,0 +1,28 @@@ +/* crypt_base64.h - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _crypt_base64_h +#define _crypt_base64_h ++#include + +void crypt_base64_init(); +void crypt_base64_deinit(); + +char *crypt_base64_encode(const unsigned char *data, size_t input_length, size_t *output_length); +unsigned char *crypt_base64_decode(const char *data, size_t input_length, size_t *output_length); + +#endif diff --cc src/crypt_rsa.c index 80450f1,0000000..c78bf89 mode 100644,000000..100644 --- a/src/crypt_rsa.c +++ b/src/crypt_rsa.c @@@ -1,501 -1,0 +1,458 @@@ +/* crypt_rsa.c - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ +#include "../config.h" +#include "crypt_rsa.h" + +#include +#include +#include +#include + - - int main(char *argv[], int argc) { - crypt_init(); - - struct crypt_rsa_privkey *privkey; - FILE *fp; - if(fp = fopen("privkey.pem", "r")) { - char buffer[4096]; - fread(buffer, sizeof(buffer), 1, fp); - fclose(fp); - - privkey = crypt_load_privkey(buffer); - } else { - privkey = crypt_generate_privkey(2048); - - fp = fopen("privkey.pem", "w"); - char *buffer = crypt_export_privkey(privkey, 0); - fprintf(fp, "%s", buffer); - free(buffer); - fclose(fp); - } - - struct crypt_rsa_pubkey *pubkey = crypt_get_pubkey(privkey); - char plain[] = "Test String!!!"; - char *crypted = NULL; - int len = crypt_encrypt_data(pubkey, plain, sizeof(plain), &crypted); - - printf("Crypt Len: %d\n", len); - printf("Crypt: "); - int i; - for(i = 0; i < len; i++) { - printf(" %02X", ((unsigned int)crypted[i] & 0xFF)); - } - printf("\n"); - - char *decrypted = NULL; - len = crypt_decrypt_data(privkey, crypted, len, &decrypted); - printf("Decrypt Len: %d\n", len); - printf("Decrypt: %s\n", decrypted); - } - - - +/* +// GnuTLS Backend not working because of gnutls_pubkey_encrypt_data doesn't exists prior to GnuTLS 3.0 +// still searching for a replacement... + +#if defined(HAVE_GNUTLS_GNUTLS_H) +#include +#include +#include + +struct crypt_rsa_pubkey { + unsigned int free_crt : 1; + unsigned int free_pubkey : 1; + gnutls_x509_crt_t crt; + gnutls_pubkey_t pubkey; +}; + +struct crypt_rsa_privkey { + unsigned int free_key : 1; + unsigned int free_privkey : 1; + gnutls_x509_privkey_t key; + gnutls_privkey_t privkey; +}; + +void crypt_rsa_init() { + gnutls_global_init(); +} + +void crypt_rsa_deinit() { + gnutls_global_deinit(); +} + +struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) { + struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey)); + int ret; + const gnutls_datum_t key_dat = {(void *)key, strlen(key)}; + + if(!pubkey) + return NULL; + + ret = gnutls_x509_crt_init(&pubkey->crt); + if(ret < 0) + goto crypt_rsa_load_pubkey_fail; + pubkey->free_crt = 1; + + ret = gnutls_x509_crt_import(pubkey->crt, &key_dat, GNUTLS_X509_FMT_PEM); + if (ret < 0) + goto crypt_rsa_load_pubkey_fail; + + ret = gnutls_pubkey_init(&pubkey->pubkey); + if(ret < 0) + goto crypt_rsa_load_pubkey_fail; + pubkey->free_pubkey = 1; + + ret = gnutls_pubkey_import_x509(pubkey->pubkey, pubkey->crt, 0); + if(ret < 0) + goto crypt_rsa_load_pubkey_fail; + + return pubkey; + crypt_rsa_load_pubkey_fail: + crypt_rsa_unload_pubkey(pubkey); + return NULL; +} + +void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) { + if(pubkey->free_crt) + gnutls_x509_crt_deinit(pubkey->crt); + if(pubkey->free_pubkey) + gnutls_pubkey_deinit(pubkey->pubkey); + free(pubkey); +} + +char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) { + size_t size = 1024; + char *buffer = malloc(size); + int ret; + + ret = gnutls_pubkey_export(pubkey->pubkey, GNUTLS_X509_FMT_PEM, buffer, &size); + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { + buffer = realloc(buffer, size); + ret = gnutls_pubkey_export(pubkey->pubkey, GNUTLS_X509_FMT_PEM, buffer, &size); + } + if(ret < 0) { + free(buffer); + return NULL; + } + return buffer; +} + +struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) { + struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey)); + int ret; + + const gnutls_datum_t key_dat = {(void *)key, strlen(key)}; + + ret = gnutls_x509_privkey_init(&privkey->key); + if(ret < 0) + goto crypt_rsa_load_privkey_fail; + privkey->free_key = 1; + + ret = gnutls_x509_privkey_import(privkey->key, &key_dat, GNUTLS_X509_FMT_PEM); + if (ret < 0) + goto crypt_rsa_load_privkey_fail; + + ret = gnutls_privkey_init(&privkey->privkey); + if(ret < 0) + goto crypt_rsa_load_privkey_fail; + privkey->free_privkey = 1; + + ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0); + if(ret < 0) + goto crypt_rsa_load_privkey_fail; + + return privkey; + crypt_rsa_load_privkey_fail: + crypt_rsa_unload_privkey(privkey); + return NULL; +} + +struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) { + struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey)); + int ret; + + ret = gnutls_x509_privkey_init(&privkey->key); + if(ret < 0) + goto crypt_rsa_generate_privkey_fail; + privkey->free_key = 1; + + ret = gnutls_x509_privkey_generate(privkey->key, GNUTLS_PK_RSA, keysize, 0); + if (ret < 0) + goto crypt_rsa_generate_privkey_fail; + + ret = gnutls_privkey_init(&privkey->privkey); + if(ret < 0) + goto crypt_rsa_generate_privkey_fail; + privkey->free_privkey = 1; + + ret = gnutls_privkey_import_x509(privkey->privkey, privkey->key, 0); + if(ret < 0) + goto crypt_rsa_generate_privkey_fail; + + return privkey; + crypt_rsa_generate_privkey_fail: + crypt_rsa_unload_privkey(privkey); + return NULL; +} + +char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) { + size_t size = 1024; + char *buffer = malloc(size); + int ret; + + if(pubkey) { + gnutls_pubkey_t pkey; + ret = gnutls_pubkey_init(&pkey); + if(ret < 0) { + free(buffer); + return NULL; + } + ret = gnutls_pubkey_import_privkey(pkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0); + if(ret < 0) { + free(buffer); + gnutls_pubkey_deinit(pkey); + return NULL; + } + ret = gnutls_pubkey_export(pkey, GNUTLS_X509_FMT_PEM, buffer, &size); + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { + buffer = realloc(buffer, size); + ret = gnutls_pubkey_export(pkey, GNUTLS_X509_FMT_PEM, buffer, &size); + } + gnutls_pubkey_deinit(pkey); + } else { + ret = gnutls_x509_privkey_export(privkey->key, GNUTLS_X509_FMT_PEM, buffer, &size); + if(ret == GNUTLS_E_SHORT_MEMORY_BUFFER) { + buffer = realloc(buffer, size); + ret = gnutls_x509_privkey_export(privkey->key, GNUTLS_X509_FMT_PEM, buffer, &size); + } + } + if(ret < 0) { + free(buffer); + return NULL; + } + return buffer; +} + +void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) { + if(privkey->free_key) + gnutls_x509_privkey_deinit(privkey->key); + if(privkey->free_privkey) + gnutls_privkey_deinit(privkey->privkey); + free(privkey); +} + +struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) { + struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey)); + if(!pubkey) + return NULL; + int ret; + + ret = gnutls_pubkey_init(&pubkey->pubkey); + if(ret < 0) + goto crypt_rsa_get_pubkey_fail; + pubkey->free_pubkey = 1; + + ret = gnutls_pubkey_import_privkey(pubkey->pubkey, privkey->privkey, GNUTLS_KEY_KEY_ENCIPHERMENT | GNUTLS_KEY_DIGITAL_SIGNATURE, 0); + if(ret < 0) + goto crypt_rsa_get_pubkey_fail; + + return pubkey; + crypt_rsa_get_pubkey_fail: + crypt_rsa_unload_pubkey(pubkey); + return NULL; +} + +int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) { + const gnutls_datum_t data_dat = {(void *)data, datalen}; + gnutls_datum_t out; + + int ret = gnutls_pubkey_encrypt_data(pubkey->pubkey, 0, &data_dat, &out); + if(ret < 0) + return ret; + + *encrypted = out.data; + return out.size; +} + +int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) { + const gnutls_datum_t enc_dat = {(void *)encrypted, enclen}; + gnutls_datum_t out; + + int ret = gnutls_privkey_decrypt_data(privkey->privkey, 0, &enc_dat, &out); + if(ret < 0) + return ret; + + *data = out.data; + return out.size; +} + +int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) { + //int size = (pubkey->pubkey->bits / 8) - 12; + //todo! + int size = 1024; + return size; +} + +void crypt_rsa_encrypt_free(char *encrypted) { + gnutls_free(encrypted); +} + +void crypt_rsa_decrypt_free(char *data) { + gnutls_free(data); +} + +#elif defined(HAVE_OPENSSL_SSL_H) +*/ + +#include +#include +#include +#include +#include +#include + +struct crypt_rsa_pubkey { + RSA *rsa; +}; + +struct crypt_rsa_privkey { + RSA *rsa; +}; + +void crypt_rsa_init() { + +} + +void crypt_rsa_deinit() { + +} + +RSA *createRSA(unsigned char *key, int public) { + RSA *rsa= NULL; + BIO *keybio ; + keybio = BIO_new_mem_buf(key, -1); + if(!keybio) + return NULL; + if(public) + rsa = PEM_read_bio_RSA_PUBKEY(keybio, &rsa, NULL, NULL); + else + rsa = PEM_read_bio_RSAPrivateKey(keybio, &rsa,NULL, NULL); + BIO_free(keybio); + return rsa; +} + +struct crypt_rsa_pubkey *crypt_rsa_load_pubkey(const char *key) { + struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey)); + if(!pubkey) + return NULL; + + RSA *rsa = createRSA((unsigned char *) key, 1); + + if(!rsa) { + free(pubkey); + return NULL; + } + + pubkey->rsa = rsa; + return pubkey; +} + +void crypt_rsa_unload_pubkey(struct crypt_rsa_pubkey *pubkey) { + RSA_free(pubkey->rsa); + free(pubkey); +} + +char *crypt_rsa_export_pubkey(struct crypt_rsa_pubkey *pubkey) { + BIO *bio = BIO_new(BIO_s_mem()); + PEM_write_bio_RSA_PUBKEY(bio, pubkey->rsa); + + int keylen = BIO_pending(bio); + char *key = calloc(1, keylen+1); + BIO_read(bio, key, keylen); + + BIO_free_all(bio); + return key; +} + +struct crypt_rsa_privkey *crypt_rsa_load_privkey(const char *key) { + struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey)); + if(!privkey) + return NULL; + + RSA *rsa = createRSA((unsigned char *) key, 0); + + if(!rsa) { + free(privkey); + return NULL; + } + + privkey->rsa = rsa; + return privkey; +} + +struct crypt_rsa_privkey *crypt_rsa_generate_privkey(const int keysize) { + struct crypt_rsa_privkey *privkey = calloc(1, sizeof(*privkey)); + if(!privkey) + return NULL; + + BIGNUM *e = BN_new(); + RSA *rsa = RSA_new(); + + BN_set_word(e, 65537); + if (!RSA_generate_key_ex(rsa, keysize, e, NULL)) { + BN_free(e); + RSA_free(rsa); + free(privkey); + return NULL; + } + + privkey->rsa = rsa; + return privkey; +} + +char *crypt_rsa_export_privkey(struct crypt_rsa_privkey *privkey, int pubkey) { + BIO *bio = BIO_new(BIO_s_mem()); + if(pubkey) + PEM_write_bio_RSA_PUBKEY(bio, privkey->rsa); + else + PEM_write_bio_RSAPrivateKey(bio, privkey->rsa, NULL, NULL, 0, NULL, NULL); + + int keylen = BIO_pending(bio); + char *key = calloc(1, keylen+1); + BIO_read(bio, key, keylen); + + BIO_free_all(bio); + return key; +} + +void crypt_rsa_unload_privkey(struct crypt_rsa_privkey *privkey) { + RSA_free(privkey->rsa); + free(privkey); +} + +struct crypt_rsa_pubkey *crypt_rsa_get_pubkey(struct crypt_rsa_privkey *privkey) { + struct crypt_rsa_pubkey *pubkey = calloc(1, sizeof(*pubkey)); + if(!pubkey) + return NULL; + + RSA *rsa = RSA_new(); + memcpy(rsa, privkey->rsa, sizeof(*rsa)); + + pubkey->rsa = rsa; + return pubkey; +} + +int crypt_rsa_encrypt_data(struct crypt_rsa_pubkey *pubkey, const char *data, int datalen, char **encrypted) { + if(!pubkey) + return 0; + if(datalen > crypt_rsa_encrypt_maxlen(pubkey)) + return 0; + *encrypted = malloc(RSA_size(pubkey->rsa)); + if(!*encrypted) + return 0; + int ret = RSA_public_encrypt(datalen, data, *encrypted, pubkey->rsa, RSA_PKCS1_PADDING); + if(ret <= 0) + free(*encrypted); + return ret; +} + +int crypt_rsa_decrypt_data(struct crypt_rsa_privkey *privkey, const char *encrypted, int enclen, char **data) { + if(!privkey) + return 0; + if(enclen > RSA_size(privkey->rsa)) + return 0; + *data = malloc(RSA_size(privkey->rsa)); + if(!*data) + return 0; + int ret = RSA_private_decrypt(enclen, encrypted, *data, privkey->rsa, RSA_PKCS1_PADDING); + if(ret <= 0) + free(*data); + return ret; +} + +int crypt_rsa_encrypt_maxlen(struct crypt_rsa_pubkey *pubkey) { + return RSA_size(pubkey->rsa) - 12; +} + +void crypt_rsa_encrypt_free(char *encrypted) { + free(encrypted); +} + +void crypt_rsa_decrypt_free(char *data) { + free(data); +} + +//#endif diff --cc src/ircd_auth.c index 0478f9b,0000000..8079db1 mode 100644,000000..100644 --- a/src/ircd_auth.c +++ b/src/ircd_auth.c @@@ -1,84 -1,0 +1,85 @@@ +/* ircd_auth.c - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ ++ ++#include ++ +#include "struct_auth.h" +#include "struct_connection.h" +#include "ircd_client.h" +#include "IOHandler/IOSockets.h" +#include "IOHandler/IODNSLookup.h" +#include "version.h" + +static IODNS_CALLBACK(auth_dns_callback); + +static struct Auth *authlist_first = NULL; +static struct Auth *authlist_last = NULL; + +struct Auth *auth_new(struct Connection *conn) { + struct Auth *auth = calloc(1, sizeof(*auth)); + client_printf(conn, "NOTICE AUTH :*** NextIRCd v%d.%d (%s)", VERSION_NUMBER, patchlevel, revision); + + auth->conn = conn; + time(&auth->startup_time); + + auth->prev = authlist_last; + auth->next = NULL; + if(!authlist_last) - authlist_first = auth ++ authlist_first = auth; + authlist_last = auth; + + return auth; +} + +void auth_start_dnsreverse(struct Auth *auth) { + client_printf(auth->conn, "NOTICE AUTH :*** Looking up your hostname"); + + struct IODNSAddress *sockaddr; + sockaddr = iosocket_get_remote_addr(auth->conn->socket); + if(sockaddr) { + auth->dnslookup = iodns_getnameinfo(sockaddr->address, sockaddr->addresslen, auth_dns_callback, auth); + } else { + // critical error! + } +} + +static IODNS_CALLBACK(auth_dns_callback) { + struct Auth *auth = event->query->data; + struct IODNSResult *dnsresult = event->result; + + if(event->type == IODNSEVENT_SUCCESS) { + strncpy(auth->host, dnsresult->result.host, HOSTLEN); + client_printf(auth->conn, "NOTICE AUTH :*** Found your hostname (%s)", auth->host); + } else { + struct IODNSAddress *sockaddr = iosocket_get_remote_addr(auth->conn->socket); - if(sockaddr->addresslen == sizeof(struct sockaddr_in)) { - //ipv4 - inet_ntop(AF_INET, (void *)(&((struct sockaddr_in *)sockaddr->address)->sin_addr), auth->host, HOSTLEN); - } else { - //ipv6 ++ if(auth->conn->ipv6) + inet_ntop(AF_INET6, (void *)(&((struct sockaddr_in6 *)sockaddr->address)->sin6_addr), auth->host, HOSTLEN); - } ++ else ++ inet_ntop(AF_INET, (void *)(&((struct sockaddr_in *)sockaddr->address)->sin_addr), auth->host, HOSTLEN); ++ + client_printf(auth->conn, "NOTICE AUTH :*** Couldn't look up your hostname. Using your IP instead (%s)", auth->host); + } + if(dnsresult) + iodns_free_result(dnsresult); + + auth_try_finish(auth); +} + + +void auth_try_finish(struct Auth *auth) { + +} diff --cc src/ircd_client.c index 5af6f1d,0000000..6fddf09 mode 100644,000000..100644 --- a/src/ircd_client.c +++ b/src/ircd_client.c @@@ -1,51 -1,0 +1,52 @@@ +/* ircd_client.c - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include "ircd_client.h" +#include "ircd_sock.h" +#include "struct_connection.h" +#include "struct_auth.h" +#include "ircd_config.h" ++#include "ircd_auth.h" + +#include +#include +#include +#define CLIENT_MAXLEN 512 + +void client_printf(struct Connection *conn, const char *text, ...) { + va_list arg_list; + char sendBuf[CLIENT_MAXLEN]; + int pos; + sendBuf[0] = '\0'; + va_start(arg_list, text); + pos = vsnprintf(sendBuf, CLIENT_MAXLEN - 2, text, arg_list); + va_end(arg_list); + if (pos < 0 || pos > (CLIENT_MAXLEN - 2)) pos = CLIENT_MAXLEN - 2; + sendBuf[pos] = '\n'; + sendBuf[pos+1] = '\0'; + socket_send(conn, sendBuf, pos+1); +} + +void client_connected(struct Connection *conn) { + struct Auth *auth = auth_new(conn); + + auth_start_dnsreverse(auth); +} + +void client_disconnected(struct Connection *conn) { + +} diff --cc src/ircd_parse.c index 12dc6de,0000000..1bfa8b7 mode 100644,000000..100644 --- a/src/ircd_parse.c +++ b/src/ircd_parse.c @@@ -1,305 -1,0 +1,313 @@@ +/* ircd_client.c - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + ++#include ++#include ++ +#include "tools.h" +#include "IOHandler/IOSockets.h" ++#include "ircd_parse.h" ++struct Server; ++#include "struct_client.h" ++#include "struct_auth.h" ++#include "struct_servermsg.h" + +typedef int cmd_client_t(struct Client *client, char *argv[], int argc); +typedef int cmd_auth_t(struct Auth *auth, char *argv[], int argc); +typedef int cmd_server_t(struct Server *server, char *argv[], int argc); + +static struct ServerMsg parse_static_srvmsg; + +#define PARSE_CLIFLAG_OPONLY 0x01 + +//include all commands - #include "cmd_ping.h" ++#include "cmd_nick.h" + + +struct { + struct { + const char *client; + const char *server; + } tokens; + struct { + cmd_client_t *function; + unsigned int min_argc : 8; + unsigned int max_argc : 8; + unsigned int flags : 8; + } client; + struct { + cmd_auth_t *function; + unsigned int min_argc : 8; + unsigned int max_argc : 8; + unsigned int flags : 8; + } auth; + struct { + cmd_server_t *function; + unsigned int min_argc : 8; + unsigned int max_argc : 8; + unsigned int flags : 8; + } server; + - } parse_command_list { ++} parse_command_list[] = { + {{"PING", "P"}, /* Ping Command */ + {NULL, 0, 1, 0}, /* Client */ + {NULL, 0, 1, 0}, /* Unauthed */ + {NULL, 0, 1, 0} /* Server */ + }, + {{"PASS", NULL}, /* PASS Command */ + {NULL, 0, 1, 0}, /* Client */ + {NULL, 0, 1, 0}, /* Unauthed */ + {NULL, 0, 1, 0} /* Server */ + }, + {{"NICK", "N"}, /* Nick Command */ + {cmd_nick_cli, 1, 1, 0}, /* Client */ + {cmd_nick_auth, 1, 1, 0}, /* Unauthed */ + {NULL, 0, 1, 0} /* Server */ + }, + {{"USER", "U"}, /* User Command */ + {NULL, 0, 1, 0}, /* Client */ + {NULL, 0, 1, 0}, /* Unauthed */ + {NULL, 0, 1, 0} /* Server */ + }, + + {{NULL, NULL},{NULL, 0, 0, 0},{NULL, 0, 0, 0},{NULL, 0, 0, 0}} +}; + +static char *parse_irc_token(char **data) { + //find next " " + int i; + char *token = *data; + for(i = 0; *data[i]; i++) { + if(*data[i] != ' ') { + *data[i] = '\0'; + *data += i+1; + break; + } + } + return token; +} + +static char **parse_irc_params(char *data, int *argc, int maxargs) { + if(maxargs == 0) { + *argc = 0; + return NULL; + } + char **argv = calloc(maxargs, sizeof(*argv)); + while(*data) { + //skip leading spaces - while (*line == ' ') - *line++ = 0; - if (*line == ':') { ++ while (*data == ' ') ++ *data++ = 0; ++ if (*data == ':') { + //the rest is a single parameter - argv[*argc++] = line + 1; ++ argv[*argc++] = data + 1; + break; + } - argv[*argc++] = line; - if (argc >= maxargs) ++ argv[*argc++] = data; ++ if (*argc >= maxargs) + break; - while (*line != ' ' && *line) - line++; ++ while (*data != ' ' && *data) ++ data++; + } + return argv; +} + +/* Client Data Format +* +*/ +void parse_client_data(struct Client *client, char *data) { + char *token = parse_irc_token(&data); + int found = 0; + int i; + for(i = 0; (parse_command_list[i].tokens.client || parse_command_list[i].tokens.server); i++) { + if(stricmp(parse_command_list[i].tokens.client, token)) { + found = 1; + break; + } + } + if(found && !parse_command_list[i].client.function) { + // reply 462 You may not reregister + } else if(found) { + int argc; + char **argv = parse_irc_params(data, &argc, parse_command_list[i].client.max_argc); + if(argc < parse_command_list[i].client.min_argc) { + // reply 461 Not enough parameters + } else { + int ret = parse_command_list[i].client.function(client, argv, argc); + if(ret) { + // error occurred! + // do something? + } + } + free(argv); + } else { + // reply 421 Unknown command + } +} + +void parse_unauth_data(struct Auth *auth, char *data) { + char *token = parse_irc_token(&data); + int found = 0; + int i; + for(i = 0; (parse_command_list[i].tokens.client || parse_command_list[i].tokens.server); i++) { + if(stricmp(parse_command_list[i].tokens.client, token)) { + found = 1; + break; + } + } + if(found && !parse_command_list[i].auth.function) { + // reply 451 Register first. + } else if(found) { + int argc; + char **argv = parse_irc_params(data, &argc, parse_command_list[i].auth.max_argc); + if(argc < parse_command_list[i].auth.min_argc) { + // reply 461 Not enough parameters + } else { + int ret = parse_command_list[i].auth.function(auth, argv, argc); + if(ret) { + // error occurred! + // do something? + } + } + free(argv); + } else { + // reply 421 Unknown command + } +} + +/* Unicast Multicast Broadcast +* 4 Bytes 4 Bytes 4 Bytes +* 2 Bytes 2 Bytes 2 Bytes +* 1 Byte 1 Byte 1 Byte +* x Bytes x Bytes x Bytes +* " " 1 Byte " " 1 Byte " " 1 Byte +* 4 Bytes 1 Byte 1 Byte +* 4 Bytes +* 4 Bytes +* +*/ +void parse_server_data(struct Server *server, struct IOSocketBuffer *buffer) { + struct ServerMsg *srvmsg = &parse_static_srvmsg; + unsigned char *buf = (unsigned char *)buffer->buffer; + unsigned int buflen, require_more = 0; + int i; + + while(buffer->bufpos >= 9 && !require_more) { //require at least 9 Bytes + srvmsg->source.srvnum = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); + srvmsg->resolved_source = 0; + srvmsg->msglen = ((buf[4] << 8) | buf[5]); + srvmsg->msgflags = buf[6]; + srvmsg->msgtype = (buf[6] & SERVERMSG_TYPEMASK); + + if(buffer->bufpos < srvmsg->msglen) { + require_more = 1; + break; + } + + for(i = 0; buffer->bufpos > i+7; i++) { + if(buf[i+7] == ' ') { + if(i >= MAXSERVERTOKENLEN) + srvmsg->token[MAXSERVERTOKENLEN] = '\0'; + else + srvmsg->token[i] = '\0'; + break; + } + if(i >= MAXSERVERTOKENLEN) + continue; + srvmsg->token[i] = buf[i+7]; + } + if(buf[i+7] != ' ') { + require_more = 1; + break; + } + buf += i+8; + buflen = buffer->bufpos - (i+8); + + switch(srvmsg->msgtype) { + case SERVERMSG_TYPE_UNICAST: + if(buflen < 4) { + require_more = 1; + break; + } + srvmsg->destinations = malloc(sizeof(struct ServerMsgDstMap)); + srvmsg->destinations->dstcount = 1; + srvmsg->destinations->dst[0].destination.srvnum = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); - srvmsg->destinations->dst[0].destination.resolved_destination = 0; ++ srvmsg->destinations->dst[0].resolved_destination = 0; + break; + case SERVERMSG_TYPE_MULTICAST: + if(buflen < 5) { + require_more = 1; + break; + } + unsigned int srvcount = buf[0]; + buf++; + buflen--; + if(buflen < (srvcount * 4)) { + require_more = 1; + break; + } + srvmsg->destinations = malloc(sizeof(struct ServerMsgDstMap) + (sizeof(struct ServerMsgDestination) * (srvcount - 1))); + srvmsg->destinations->dstcount = srvcount; + for(i = 0; i < srvcount; i++) { + srvmsg->destinations->dst[i].destination.srvnum = ((buf[0] << 24) | (buf[1] << 16) | (buf[2] << 8) | buf[3]); - srvmsg->destinations->dst[i].destination.resolved_destination = 0; ++ srvmsg->destinations->dst[i].resolved_destination = 0; + buf += 4; + buflen -= 4; + } + break; + case SERVERMSG_TYPE_BROADCAST: + if(buflen == 0) { + require_more = 1; + break; + } + srvmsg->destinations = NULL; + srvmsg->msgttl = buf[0]; + buf++; + buflen--; + break; + default: + // PARSE ERROR + goto parse_server_data_finish; + } + - srvmsg->arglen = srvmsg->msglen - (buf - buffer->buffer); ++ srvmsg->arglen = srvmsg->msglen - (buf - (unsigned char *)buffer->buffer); + srvmsg->args = buf; + + int found = 0; + for(i = 0; (parse_command_list[i].tokens.client || parse_command_list[i].tokens.server); i++) { + if(stricmp(parse_command_list[i].tokens.server, srvmsg->token)) { + found = 1; + break; + } + } + if(!found) + goto parse_server_data_finish; + + //exec command function + + + parse_server_data_finish: + if(srvmsg->destinations) + free(srvmsg->destinations); + + if(srvmsg->msglen > buffer->bufpos) { + memmove(buffer->buffer, buffer->buffer + srvmsg->msglen, srvmsg->msglen - buffer->bufpos); + buffer->bufpos -= srvmsg->msglen; + } else - srvmsg->bufpos = 0; ++ buffer->bufpos = 0; + } +} + diff --cc src/struct_client.h index 537b832,0000000..a944bb2 mode 100644,000000..100644 --- a/src/struct_client.h +++ b/src/struct_client.h @@@ -1,58 -1,0 +1,58 @@@ +/* struct_client.h - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _struct_client_h +#define _struct_client_h - #include "crypto_md5.h" ++#include "crypt_md5.h" +#include "struct_user.h" + +struct Connection; +struct User; + +struct ClientNickChange; + +#define AWAYLEN 300 + +/* Client represents a local User */ +struct Client { + struct Connection *conn; + struct User *user; + + struct ClientNickChange *nickchange; + + time_t userage; + time_t nickage; + time_t lastping; + time_t idlelen; + + char *userage_sign; + char *nickage_sign; + + char awaymsg[AWAYLEN-1]; + + unsigned int isonline : 1; + unsigned int isaway : 1; + - struct Client *prev, *next ++ struct Client *prev, *next; +}; + +struct ClientNickChange { + char newnick[NICKLEN+1]; + char nickhash[MDHASHLEN]; +}; + +#endif diff --cc src/struct_user.h index 9fc65c3,0000000..57aac3d mode 100644,000000..100644 --- a/src/struct_user.h +++ b/src/struct_user.h @@@ -1,44 -1,0 +1,44 @@@ +/* struct_user.h - NextIRCd + * Copyright (C) 2012-2013 Philipp Kreil (pk910) + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#ifndef _struct_user_h +#define _struct_user_h - #include "crypto_md5.h" ++#include "crypt_md5.h" + +#define NICKLEN 30 +#define IDENTLEN 15 +#define HOSTLEN 63 +#define REALLEN 50 + +struct User { + unsigned int usernum; + unsigned int servernum; + + struct Server *server; + + unsigned int islocal : 1; + + char nick[NICKLEN+1]; + char nickhash[MDHASHLEN]; + char ident[IDENTLEN+1]; + char realname[REALLEN+1]; + char hostname[HOSTLEN+1]; + + struct Member *channels; +}; + +#endif