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"
--- /dev/null
- for (int i = 0, j = 0; i < input_length;) {
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#include "crypt_base64.h"
+#include <stdint.h>
+#include <stdlib.h>
+
+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; i < mod_table[input_length % 3]; i++)
++ 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, j = 0; i < input_length;) {
++ 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; i < 64; i++)
++ 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);
++ int i;
++ for (i = 0; i < 64; i++)
+ decoding_table[(unsigned char) encoding_table[i]] = i;
+}
+
+void crypt_base64_deinit() {
+ free(decoding_table);
+}
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _crypt_base64_h
+#define _crypt_base64_h
++#include <stdlib.h>
+
+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
--- /dev/null
-
- 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);
- }
-
-
-
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+#include "../config.h"
+#include "crypt_rsa.h"
+
+#include <stdio.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+/*
+// 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 <gnutls/gnutls.h>
+#include <gnutls/x509.h>
+#include <gnutls/abstract.h>
+
+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 <openssl/pem.h>
+#include <openssl/ssl.h>
+#include <openssl/rsa.h>
+#include <openssl/evp.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+
+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
--- /dev/null
- authlist_first = auth
+/* 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 <http://www.gnu.org/licenses/>.
+ */
++
++#include <string.h>
++
+#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)
- 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
++ 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(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) {
+
+}
--- /dev/null
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#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 <stdio.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#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) {
+
+}
--- /dev/null
- #include "cmd_ping.h"
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
++#include <stdlib.h>
++#include <string.h>
++
+#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
- } parse_command_list {
++#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;
+
- while (*line == ' ')
- *line++ = 0;
- if (*line == ':') {
++} 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
- argv[*argc++] = line + 1;
++ while (*data == ' ')
++ *data++ = 0;
++ if (*data == ':') {
+ //the rest is a single parameter
- argv[*argc++] = line;
- if (argc >= maxargs)
++ argv[*argc++] = data + 1;
+ break;
+ }
- while (*line != ' ' && *line)
- line++;
++ argv[*argc++] = data;
++ if (*argc >= maxargs)
+ break;
- srvmsg->destinations->dst[0].destination.resolved_destination = 0;
++ while (*data != ' ' && *data)
++ data++;
+ }
+ return argv;
+}
+
+/* Client Data Format
+* <TOKEN> <arg1> <arg2>
+*/
+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
+* <src-srvnum> 4 Bytes <source> 4 Bytes <source> 4 Bytes
+* <length> 2 Bytes <length> 2 Bytes <length> 2 Bytes
+* <flags> 1 Byte <flags> 1 Byte <flags> 1 Byte
+* <token> x Bytes <token> x Bytes <token> x Bytes
+* " " 1 Byte " " 1 Byte " " 1 Byte
+* <dst-srvnum> 4 Bytes <servers> 1 Byte <ttl> 1 Byte
+* <dst-srv01> 4 Bytes
+* <dst-srv02> 4 Bytes
+* <args> <args> <args>
+*/
+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[i].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->arglen = srvmsg->msglen - (buf - buffer->buffer);
++ 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->bufpos = 0;
++ 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
++ buffer->bufpos = 0;
+ }
+}
+
--- /dev/null
- #include "crypto_md5.h"
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _struct_client_h
+#define _struct_client_h
- struct Client *prev, *next
++#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 ClientNickChange {
+ char newnick[NICKLEN+1];
+ char nickhash[MDHASHLEN];
+};
+
+#endif
--- /dev/null
- #include "crypto_md5.h"
+/* 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 <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _struct_user_h
+#define _struct_user_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