diff options
| author | Maximiliano Pin <[email protected]> | 2020-12-19 17:21:51 +0100 |
|---|---|---|
| committer | Maximiliano Pin <[email protected]> | 2020-12-19 17:21:51 +0100 |
| commit | 9c1888ce67dc25527e4437d80c5843ccc8609c8e (patch) | |
| tree | 5d1b9b1c7fd8758db3ef957eebe71d202ade2b4b | |
| parent | d76116a5c54d33d55644d14102300a5a950b53e8 (diff) | |
| download | ipchat-master.tar.gz | |
various updatesHEADIPCHAT_0_6master
* fixed build on newer systems
* fixed all warnings (gcc 10.2)
* updated TLS code for newer gnutls versions
* documentation updated
| -rw-r--r-- | ChangeLog | 7 | ||||
| -rw-r--r-- | README | 42 | ||||
| -rwxr-xr-x | bootstrap | 2 | ||||
| -rw-r--r-- | configure.ac | 2 | ||||
| -rw-r--r-- | doc/ipchat.1 | 15 | ||||
| -rw-r--r-- | src/contact_list.c | 2 | ||||
| -rw-r--r-- | src/log.c | 1 | ||||
| -rw-r--r-- | src/parse.c | 1 | ||||
| -rw-r--r-- | src/pqueue.h | 4 | ||||
| -rw-r--r-- | src/protocol.c | 9 | ||||
| -rw-r--r-- | src/tls.c | 179 | ||||
| -rw-r--r-- | src/tls.h | 6 | ||||
| -rw-r--r-- | src/transport.c | 18 | ||||
| -rw-r--r-- | src/ui_common.h | 21 | ||||
| -rw-r--r-- | src/ui_input.c | 1 |
15 files changed, 185 insertions, 125 deletions
@@ -1,3 +1,10 @@ +2020-12-18 IPChat 0.6 + + * fixed build on newer systems + * fixed all warnings (gcc 10.2) + * updated TLS code for newer gnutls versions + * documentation updated + 2011-04-20 IPChat 0.5 * support for unicode terminal emulators @@ -6,11 +6,11 @@ Introduction ============ IPChat is a simple and small ncurses-based chat program, written in C, - where you find your partners (what we call contacts) by their IP - addresses or hostnames (so you may use it with dyn-dns things). + where you find your contacts using their IP addresses or hostnames (so + you can use it with dyn-dns things). - Even though it's meant to be a very lightweight program, it already has - nice features like colors, terminal window resizing, line editing and + Even though it's meant to be a very lightweight program, it has nice + features like colors, terminal window resizing, line editing and recalling of previously written lines. It mantains a persistent contact list, and it works like an "instant @@ -43,8 +43,8 @@ Installation ============ This program should compile on most POSIX compliant systems. It has been - tested on GNU/Linux, GNU/Hurd and HP-UX. If you have a POSIX system where - it does not compile, please report it as a bug. + tested on GNU/Linux and GNU/Hurd. If you have a POSIX system where it + does not compile, please report it as a bug. The ncursesw library is needed. You must install the development package for your distribution, something like libncursesw5-dev. You may also @@ -52,8 +52,8 @@ Installation You may also install gnutls if you wish your connections to be encrypted. You must install the development package for your distribution, something - like libgnutls-dev. This is optional, and it can also be disabled adding - the --without-gnutls argument to the configure script. + like libgnutls-dev. This is optional, and it can also be disabled by + passing --without-gnutls to the configure script. Then, just run: @@ -76,7 +76,7 @@ Usage also be added to his/her list of contacts. So only one of the two friends has to run the /add command. - Connected contacts appear on the top of the list of contacts (on the + Connected contacts appear at the top of the list of contacts (on the right). If more than one contact is connected, you use function keys (F1, F2, ..., F12), or /1, /2, /3 (in case some function key does not work) to switch among their windows. You see in the contact list which @@ -115,17 +115,16 @@ Network problems Routers ------- - If you use a router to connect to Internet (an ADSL router, for example), - you need to configure it properly so incomming connection requests go to - your computer. As many other applications require this, you should - already have it properly configured. In many routers, setting the private - IP address of your computer as the "default host" will work. You may also - use "port forwarding" or use the router as a modem by setting your public - IP address in your computer. Please, check your router documentation. - Anyway, you don't need to fix this if your contacts do not have the same - problem, as it's enough for one of the two peers to be able to receive - connections. Note most routers are firewalls as well, so you may need to - read the next section. + You need to configure your router properly so incomming connection + requests go to your computer. As many other applications require this, + you may already have it properly configured. In many routers, setting the + private IP address of your computer as the "default host" will work. You + may also use "port forwarding" or use the router as a modem by setting + your public IP address in your computer. Please, check your router + documentation. Anyway, you don't need to fix this if your contacts do + not have the same problem, as it's enough for one of the two peers to be + able to receive connections. Note most routers are firewalls as well, so + you may need to read the next section. Firewalls --------- @@ -195,8 +194,7 @@ Distribution Copyright ========= - Copyright (C) 2004 Maximiliano Pin - Copyright (C) 2004 Julio A. Becerra + Copyright (C) 2004-2020 Maximiliano Pin, Julio A. Becerra Some files are copyrighted by the people who contributed them. IPChat is free software; you can redistribute it and/or modify @@ -1,5 +1,5 @@ #! /bin/sh -# bootstrap -- Use this script to create generated files from the CVS dist +# bootstrap -- Use this script to create generated files from the Git dist # Note: Automake 0.7 or newer is required set -x mkdir config diff --git a/configure.ac b/configure.ac index f96a329..7d535a2 100644 --- a/configure.ac +++ b/configure.ac @@ -1,7 +1,7 @@ # -*- Autoconf -*- # Process this file with autoconf to produce a configure script. -AC_INIT([IPChat], [0.5]) +AC_INIT([IPChat], [0.6]) AC_CONFIG_AUX_DIR([config]) AC_CONFIG_SRCDIR([src/main.c]) AM_INIT_AUTOMAKE diff --git a/doc/ipchat.1 b/doc/ipchat.1 index e809660..3d60bf5 100644 --- a/doc/ipchat.1 +++ b/doc/ipchat.1 @@ -17,21 +17,6 @@ now supports nice features like improved message formatting, terminal window res .B ipchat is self-documented. Use the /help command if you need more help. -.SH TODO -.IP \(bu -encrypted communications support -.IP \(bu -unicode support -.IP \(bu -IPv6 support -.IP \(bu -file transfers -.IP \(bu -X-windows GUI -.PP -We need your help to develop all these things!! -.SH VERSION -ipchat 0.4 .SH AUTHOR Maximiliano Pin <[email protected]> and Julio A. Becerra <[email protected]>. See the AUTHORS file for a complete list of contributors. diff --git a/src/contact_list.c b/src/contact_list.c index 8eb964b..9c1175a 100644 --- a/src/contact_list.c +++ b/src/contact_list.c @@ -21,7 +21,7 @@ #define _XOPEN_SOURCE /* TODO we should not need this... */ #define _XOPEN_SOURCE_EXTENDED /* ... bug in GNU libc6? */ -#include <ctype.h> +#include <ctype.h> #include <pwd.h> #include <stdio.h> #include <stdlib.h> @@ -26,6 +26,7 @@ #include <sys/types.h> #include "log.h" #include "misc.h" +#include "user_iface.h" void lg_log_text (const char *user, contact_t *contact, const char *text, int len) diff --git a/src/parse.c b/src/parse.c index fd43d72..1595916 100644 --- a/src/parse.c +++ b/src/parse.c @@ -36,6 +36,7 @@ #include "uconfig.h" #include "transport.h" #include "misc.h" +#include "tls.h" #define ADD_C 0 #define BEEP_C 1 diff --git a/src/pqueue.h b/src/pqueue.h index 65d9504..4c9a158 100644 --- a/src/pqueue.h +++ b/src/pqueue.h @@ -75,8 +75,8 @@ extern void * pq_get(prio_t,pqueue *); extern void * pq_del_func(void*,pqueue*); extern void * pq_get_func(void*,pqueue*); extern void * pq_del_ptr(void*,pqueue*); -extern pq_chpri_func(void*,prio_t,pqueue*); -extern pq_chpri_ptr(void*,prio_t,pqueue*); +extern int pq_chpri_func(void*,prio_t,pqueue*); +extern int pq_chpri_ptr(void*,prio_t,pqueue*); extern int pq_delete(pqueue*); #endif /* PQUEUE_H */ diff --git a/src/protocol.c b/src/protocol.c index 3ec6e76..578b010 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -1,5 +1,5 @@ -/* protocol.c -- understands and generates messages sent over the network - Copyright (C) 2004 Maximiliano Pin +/* protocol.c -- decodes and generates messages sent over the network + Copyright (C) 2004-2020 Maximiliano Pin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -28,6 +28,7 @@ #include "demux.h" #include "misc.h" #include "log.h" +#include "tls.h" /* Header of sent and received messages. */ /* ATTENTION: Changing this struct requires revision of hton_header(), @@ -131,6 +132,7 @@ pr_msg_received (contact_t *contact, const BYTE *msg, int len) const BYTE *payload; int pl_size; int r; + struct hdr_hello hello; CHECK_J (len >= sizeof(header.type), small_size); type = *(uint16_t *)msg; @@ -147,7 +149,8 @@ pr_msg_received (contact_t *contact, const BYTE *msg, int len) switch (type) { case MSG_HELLO: - r = received_hello (contact, &header.c.hello, + memcpy (&hello, &header.c.hello, sizeof (hello)); + r = received_hello (contact, &hello, (const char *)payload, pl_size); break; @@ -1,5 +1,5 @@ /* tls.c -- encryption and authentication code - Copyright (C) 2006 Maximiliano Pin + Copyright (C) 2006-2020 Maximiliano Pin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -21,41 +21,59 @@ #include <unistd.h> /* read, write, fcntl */ #include <fcntl.h> /* fcntl */ #include <errno.h> /* errno */ +#include <stdint.h> /* intptr_t */ #include "common.h" #if HAVE_GNUTLS #include <gnutls/gnutls.h> #endif #include "tls.h" #include "demux.h" +#include "user_iface.h" extern int errno; #if HAVE_GNUTLS -#define DH_BITS 1024 +/* Implementation based on example at: + https://gnutls.org/manual/html_node/Simple-client-example-with-anonymous-authentication.html +*/ + +/* +#define TLS_DEBUG 1 +*/ -static gnutls_dh_params dh_params; -static gnutls_anon_server_credentials anoncred_srv; -static gnutls_anon_client_credentials anoncred_cli; +#define CHECK_TLS_SUCCESS(x) CHECK ((x) == GNUTLS_E_SUCCESS) +#define CALL_TLS(x) do { int ret_ = (x); \ + if (ret_ != GNUTLS_E_SUCCESS) \ + ui_output_err ("%s", gnutls_strerror (ret_)); \ + } while (0) + +static gnutls_anon_server_credentials_t anoncred_srv; +static gnutls_anon_client_credentials_t anoncred_cli; /* Prototypes */ -static int generate_dh_params (void); static void cb_continue_handshake (int fd, void *data); +#ifdef TLS_DEBUG +static void print_cipher_suite_list (const char *priorities); +#endif #endif -static int enabled = 0; +static BOOL enabled = FALSE; void tls_init (void) { #if HAVE_GNUTLS - gnutls_global_init (); - generate_dh_params (); - gnutls_anon_allocate_server_credentials (&anoncred_srv); - gnutls_anon_allocate_client_credentials (&anoncred_cli); - gnutls_anon_set_server_dh_params (anoncred_srv, dh_params); - enabled = 1; /* TODO check return values before... */ + int ret; + CHECK_TLS_SUCCESS (ret = gnutls_global_init ()); + CHECK_TLS_SUCCESS (ret = gnutls_anon_allocate_server_credentials (&anoncred_srv)); + CHECK_TLS_SUCCESS (ret = gnutls_anon_allocate_client_credentials (&anoncred_cli)); + enabled = TRUE; + return; +error: + ui_output_err ("%s", gnutls_strerror (ret)); + return; #endif } @@ -69,42 +87,56 @@ tls_finish (void) #endif } -int +BOOL tls_enabled (void) { return enabled; } -void +BOOL tls_session_init (contact_t *contact, int server) { #if HAVE_GNUTLS - const int kx_prio[] = { GNUTLS_KX_ANON_DH, 0 }; - gnutls_session session; + gnutls_session_t session; void *cred; + int ret; + const char *errp = NULL; + const char *priorities = "PERFORMANCE:+ANON-ECDH:+ANON-DH"; + + ret = gnutls_init (&session, server ? GNUTLS_SERVER : GNUTLS_CLIENT); + if (ret != GNUTLS_E_SUCCESS) { + ui_output_err ("SSL/TLS init failed!"); + ui_output_err ("%s", gnutls_strerror (ret)); + return FALSE; + } - gnutls_init (&session, server ? GNUTLS_SERVER : GNUTLS_CLIENT); + ret = (gnutls_priority_set_direct(session, priorities, &errp)); + if (ret != GNUTLS_E_SUCCESS) { + ui_output_err ("SSL/TLS set priority failed!"); + ui_output_err ("%s (at: \"%s\")", gnutls_strerror (ret), errp); + return FALSE; + } - /* use default priorities */ - gnutls_set_default_priority (session); - gnutls_kx_set_priority (session, kx_prio); +#ifdef TLS_DEBUG + print_cipher_suite_list (priorities); +#endif cred = server ? (void*)anoncred_srv : (void*)anoncred_cli; - gnutls_credentials_set (session, GNUTLS_CRD_ANON, cred); - gnutls_dh_set_prime_bits (session, DH_BITS); + CALL_TLS (gnutls_credentials_set (session, GNUTLS_CRD_ANON, cred)); gnutls_transport_set_ptr - (session, (gnutls_transport_ptr)contact->state.socket); + (session, (gnutls_transport_ptr_t)(intptr_t)contact->state.socket); contact->state.tls_info = (void *)session; #endif + return TRUE; } void tls_session_deinit (contact_t *contact) { #if HAVE_GNUTLS - gnutls_session session = (gnutls_session)contact->state.tls_info; + gnutls_session_t session = (gnutls_session_t)contact->state.tls_info; if (session) { gnutls_deinit (session); contact->state.tls_info = NULL; @@ -116,11 +148,11 @@ void tls_session_finish (contact_t *contact) { #if HAVE_GNUTLS - gnutls_session session = (gnutls_session)contact->state.tls_info; + gnutls_session_t session = (gnutls_session_t)contact->state.tls_info; if (session) { /* TODO i'm not sure if nonblocking affects gnutls_bye */ fcntl (contact->state.socket, F_SETFL, 0); - gnutls_bye (session, GNUTLS_SHUT_WR); + CALL_TLS (gnutls_bye (session, GNUTLS_SHUT_WR)); } #endif } @@ -129,7 +161,7 @@ void tls_handshake (contact_t *contact) { #if HAVE_GNUTLS - gnutls_session session = (gnutls_session)contact->state.tls_info; + gnutls_session_t session = (gnutls_session_t)contact->state.tls_info; int ret; if (!session) { @@ -165,6 +197,13 @@ tls_handshake (contact_t *contact) contact->state.cn_state = CS_CONNECTED; /* this will create a window for the contact */ ui_redraw_contacts (); +#ifdef TLS_DEBUG + { + char *desc = gnutls_session_get_desc(session); + ui_output_info("Session info: %s", desc); + gnutls_free(desc); + } +#endif } #else contact->state.cn_state = CS_CONNECTED; @@ -177,7 +216,7 @@ tls_send (contact_t *contact, const void *data, size_t size) ssize_t ret; /* TODO think about the return value */ #if HAVE_GNUTLS - gnutls_session session = (gnutls_session)contact->state.tls_info; + gnutls_session_t session = (gnutls_session_t)contact->state.tls_info; if (session && CT_IS_CONNECTED (contact)) { ret = gnutls_record_send (session, data, size); @@ -185,7 +224,7 @@ tls_send (contact_t *contact, const void *data, size_t size) else #endif { - /* connection is not crypted */ + /* connection is not encrypted */ ret = write (contact->state.socket, data, size); } @@ -198,7 +237,7 @@ tls_recv (contact_t *contact, void *data, size_t size) ssize_t ret; #if HAVE_GNUTLS - gnutls_session session = (gnutls_session)contact->state.tls_info; + gnutls_session_t session = (gnutls_session_t)contact->state.tls_info; /* TODO implement functionality of net_read() in transport.c and remove that */ @@ -223,7 +262,7 @@ tls_recv (contact_t *contact, void *data, size_t size) else #endif { - /* connection is not crypted */ + /* connection is not encrypted */ ret = read (contact->state.socket, data, size); if (ret == 0) { ret = ERR; /* disconnect */ @@ -245,10 +284,11 @@ void tls_session_info (contact_t *contact) { #if HAVE_GNUTLS - gnutls_session session = (gnutls_session)contact->state.tls_info; + gnutls_session_t session = (gnutls_session_t)contact->state.tls_info; const char *tmp; - gnutls_credentials_type cred; - gnutls_kx_algorithm kx; + gnutls_credentials_type_t cred; + gnutls_kx_algorithm_t kx; + int dh_bits; if (!session) { ui_output_info ("\\b\\2-\\0 SSL/TLS session not established"); @@ -268,8 +308,14 @@ tls_session_info (contact_t *contact) gnutls_srp_server_get_username (session)); break; case GNUTLS_CRD_ANON: /* anonymous authentication */ - ui_output_info ("\\b\\2-\\0 Anonymous DH using prime of " - "%d bits", gnutls_dh_get_prime_bits (session)); + dh_bits = gnutls_dh_get_prime_bits (session); + if (dh_bits) { + ui_output_info ("\\b\\2-\\0 Anonymous DH using prime " + "of %d bits", dh_bits); + } + else { + ui_output_info ("\\b\\2-\\0 Anonymous authentication"); + } break; case GNUTLS_CRD_CERTIFICATE: /* certificate authentication */ /* check if we have been using ephemeral Diffie Hellman */ @@ -293,10 +339,6 @@ tls_session_info (contact_t *contact) (gnutls_certificate_type_get (session)); ui_output_info ("\\b\\2-\\0 Certificate Type: %s", tmp); - /* print the compression algorithm (if any) */ - tmp = gnutls_compression_get_name (gnutls_compression_get (session)); - ui_output_info ("\\b\\2-\\0 Compression: %s", tmp); - /* print the name of the cipher used. ie 3DES */ tmp = gnutls_cipher_get_name (gnutls_cipher_get (session)); ui_output_info ("\\b\\2-\\0 Cipher: %s", tmp); @@ -309,23 +351,54 @@ tls_session_info (contact_t *contact) #if HAVE_GNUTLS -static int -generate_dh_params (void) +static void +cb_continue_handshake (int fd, void *data) { - /* Generate Diffie Hellman parameters - for use with DHE - kx algorithms. These should be discarded and regenerated - once a day, once a week or once a month. Depending on the - security requirements. */ - gnutls_dh_params_init (&dh_params); - gnutls_dh_params_generate2 (dh_params, DH_BITS); - - return 0; + tls_handshake ((contact_t *)data); } +#ifdef TLS_DEBUG + static void -cb_continue_handshake (int fd, void *data) +print_cipher_suite_list (const char *priorities) { - tls_handshake ((contact_t *)data); + size_t i; + int ret; + unsigned int idx; + const char *name; + const char *err; + unsigned char id[2]; + gnutls_protocol_t version; + gnutls_priority_t pcache; + + ui_output_info("Cipher suites for %s", priorities); + + ret = gnutls_priority_init(&pcache, priorities, &err); + if (ret < 0) { + ui_output_err("Syntax error at: %s", err); + return; + } + + for (i = 0;; i++) { + ret = gnutls_priority_get_cipher_suite_index(pcache, i, &idx); + if (ret == GNUTLS_E_REQUESTED_DATA_NOT_AVAILABLE) + break; + if (ret == GNUTLS_E_UNKNOWN_CIPHER_SUITE) + continue; + + name = gnutls_cipher_suite_info(idx, id, NULL, NULL, NULL, + &version); + + if (name != NULL) { + ui_output_info("%-50s\t0x%02x, 0x%02x\t%s", + name, (unsigned char) id[0], + (unsigned char) id[1], + gnutls_protocol_get_name(version)); + } + } + + return; } #endif +#endif @@ -1,5 +1,5 @@ /* tls.h -- encryption and authentication code - Copyright (C) 2006 Maximiliano Pin + Copyright (C) 2006-2020 Maximiliano Pin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -29,14 +29,14 @@ extern void tls_init (void); extern void tls_finish (void); /* Is TLS enabled? */ -extern int tls_enabled (void); +extern BOOL tls_enabled (void); /* Initialize TLS session for a connected contact. This involves no traffic at all, it only initializes the session structure, so tls_handshake() can be called later to "upgrade" the connection to SSL/TLS. Parameter 'server' indicates whether connection was initiated by us or by the peer. */ -extern void tls_session_init (contact_t *contact, int server); +extern BOOL tls_session_init (contact_t *contact, int server); /* Release TLS session. If a handshake was performed, tls_session_finish() should be called first. */ diff --git a/src/transport.c b/src/transport.c index 00a2ee0..65d5737 100644 --- a/src/transport.c +++ b/src/transport.c @@ -1,5 +1,5 @@ /* transport.c -- implements the server, and transports messages - Copyright (C) 2004 Maximiliano Pin + Copyright (C) 2004-2020 Maximiliano Pin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -287,11 +287,14 @@ cb_server_data (int fd, void *data) c->state.socket = s; c->state.cn_state = CS_HELLO_PENDING; - tls_session_init (c, TRUE); - dmx_add_input_fd (s, cb_net_input, (void *)c); - create_hello_timeout (c); - pr_send_hello (c); - + if (tls_session_init (c, TRUE)) { + dmx_add_input_fd (s, cb_net_input, (void *)c); + create_hello_timeout (c); + pr_send_hello (c); + } + else { + tr_disconnect (c); + } error: return; } @@ -336,8 +339,7 @@ cb_out_connection (int fd, void *data) } dmx_remove_output_fd (fd); - if (tcp_connect_result (fd) == OK) { - tls_session_init (c, FALSE); + if (tcp_connect_result (fd) == OK && tls_session_init (c, FALSE)) { c->state.cn_state = CS_HELLO_PENDING; dmx_add_input_fd (fd, cb_net_input, data); create_hello_timeout (c); diff --git a/src/ui_common.h b/src/ui_common.h index f34bd0c..d844c0a 100644 --- a/src/ui_common.h +++ b/src/ui_common.h @@ -1,5 +1,5 @@ /* ui_common.h -- common header for the ncurses user interface - Copyright (C) 2004 Maximiliano Pin + Copyright (C) 2004-2020 Maximiliano Pin This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License @@ -18,26 +18,15 @@ #include "common.h" -#include <ncursesw/ncurses.h> -#include <wchar.h> +#define NCURSES_WIDECHAR 1 -/* we could adapt the code to work with or without wide-char ncurses */ -#if 0 -#ifdef HAVE_NCURSES_H -#include <ncurses.h> -#elif HAVE_NCURSES_NCURSES_H -#include <ncurses/ncurses.h> -#elif HAVE_NCURSES_CURSES_H +#if HAVE_NCURSES_NCURSES_H #include <ncurses/ncurses.h> -#elif HAVE_CURSES_H -#include <curses.h> -#elif HAVE_CONFIG_H -#error Missing ncurses header! #else -/* most common place */ #include <ncurses.h> #endif -#endif + +#include <wchar.h> #include "user_iface.h" #include "contact_list.h" diff --git a/src/ui_input.c b/src/ui_input.c index 0aef7af..6899919 100644 --- a/src/ui_input.c +++ b/src/ui_input.c @@ -22,6 +22,7 @@ #include <stdio.h> /* stdlib.h (on some systems) */ #include <stdlib.h> /* malloc, realloc, free, atoi */ #include <string.h> /* memcpy, memcmp */ +#include <wctype.h> /* iswdigit */ #include "ui_common.h" #include "uconfig.h" #include "misc.h" |
