Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]
Groups > comp.sys.acorn.programmer > #2733 > unrolled thread
| Started by | Alexander Ausserstorfer <bavariasound@chiemgau-net.de> |
|---|---|
| First post | 2013-05-20 09:18 +0200 |
| Last post | 2013-05-24 11:38 +0100 |
| Articles | 5 — 3 participants |
Back to article view | Back to comp.sys.acorn.programmer
E-Mail-fetcher for RISC OS using GnuTLS Alexander Ausserstorfer <bavariasound@chiemgau-net.de> - 2013-05-20 09:18 +0200
Re: E-Mail-fetcher for RISC OS using GnuTLS Streuner <utellan@yahoo.de> - 2013-05-23 08:29 +0200
Re: E-Mail-fetcher for RISC OS using GnuTLS Chris Gransden <chrisg@care4free.net> - 2013-05-23 14:41 +0100
Re: E-Mail-fetcher for RISC OS using GnuTLS Alexander Ausserstorfer <bavariasound@chiemgau-net.de> - 2013-05-24 10:05 +0200
Re: E-Mail-fetcher for RISC OS using GnuTLS Chris Gransden <chrisg@care4free.net> - 2013-05-24 11:38 +0100
| From | Alexander Ausserstorfer <bavariasound@chiemgau-net.de> |
|---|---|
| Date | 2013-05-20 09:18 +0200 |
| Subject | E-Mail-fetcher for RISC OS using GnuTLS |
| Message-ID | <e903ae4e53.Alex@bavariasound.chiemgau-net.de> |
Hello, the first part is taken: The secure connection to a POP-server with digital certificates using GnuTLS. The document of the project is in German, though. Take a look at http://home.chiemgau-net.de/ausserstorfer/Studium/ or directly at http://home.chiemgau-net.de/ausserstorfer/Studium/Fetcher/GnuTLS/Arbeit(26).pdf if you want know more the way I'm going. The next part is to write the e-mail-fetching mechanism. The thirt part will be cross-compiling to RISC OS then. And the fourth and last part the implemention to WIMP. It is just a project for me to learn... A. -- http://home.chiemgau-net.de/ausserstorfer/
[toc] | [next] | [standalone]
| From | Streuner <utellan@yahoo.de> |
|---|---|
| Date | 2013-05-23 08:29 +0200 |
| Message-ID | <knkd0b$66a$1@geiz-ist-geil.priv.at> |
| In reply to | #2733 |
Am 20.05.2013 09:18, schrieb Alexander Ausserstorfer:
> the first part is taken: The secure connection to a POP-server with
> digital certificates using GnuTLS. The document of the project is in
> German, though. Take a look at
>
> http://home.chiemgau-net.de/ausserstorfer/Studium/
Juste un question, plus. Currently I'm looking for a computer on which I
can edit, compile and run the code native(lly) (means that it runs Unix
/ Linux instead of Cygwin on Windows). I'm also thinking for a Rasperry
Pi, Beagle or Pandora-board but I'm not sure about if you can do it there.
So, can somebody here try to compile and test the following code on a
machine under Linux like the Rasperry PI, please? Or what is a good
portable machine (laptop) with Unix / Linux?
The programme connects to a POP-Server using STARTTLS and fetchs from
there the first e-mail (not complettely now, it is just for
demonstrating). To make things more difficult, you must also have
installed the required certificates for the server in .PEM-format in
"usr/ssl/certs/E-Mail-Chain.crt".
To compile press the keys
gcc -<file name>.c -o <file name> -lgnutls
-------------------------------------------------------------------------
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif
#include <stdio.h> // printf, scanf
#include <stdlib.h> // Fehlercodes wie EXIT_FAILURE
#include <sys/socket.h> // AF_INET, SOCK_STREAM, connect(...)
#include <netdb.h> // struct hostent
#include <netinet/in.h> // struct sockadd_in
#include <gnutls/gnutls.h> // GnuTLS
#include <gnutls/x509.h> // GnuTLS x.509-Zertifikate
#include <string.h> // strcat(...)
#define MAX_BUF 1024 // Groesse des Zwischenspeichers
// fuer die verschluesselte
// Uebertragung
#define MAXMSG 512 // Groesse des Zwischenspeichers
// fuer die Klartextuebertragung
// fuer die vom Server
// uebermittelten Daten
// Folgende Datei muss die zur Ueberprüfung
// notwendigen Zertifikate (BASE64-codiert!) bereitstellen
#define CAFILE "/usr/ssl/certs/E-Mail-Chain.crt"
struct hostent *hostinfo; // enthaelt Zuordnung von Host-
// Addressen und -namen
struct sockaddr_in name; // enthaelt Verbindungsinfor-
// mationen des verwendeten Sockets
// (Prototyp) Funktion ueberprueft das vom Server geschickte
// Zertifikat an Hand des Zertifikatsspeichers
static int _verify_certificate_callback(gnutls_session_t session);
// (Prototyp) Funktion ermittelt die binaere IP-Nummer aus dem
// Hostnamen
void IP_number(struct sockaddr_in *name, char *servername, uint16_t
port);
main()
{
int ret; // Rueckgabewert Handshake
int ii; // Schleifenzaehler
// Folgende Struktur nimmt die fuer eine verschluesselte
// Sitzung notwendigen Angaben auf
gnutls_session_t session;
// Folgende Struktur nimmt die fuer den Client notwendigen
// Ausweisungsangaben ("Ausweispapiere") auf:
// hier: Benutzername und Passwort
// (englisch: Secure Remote Password authentication)
gnutls_srp_client_credentials_t srp_cred;
// Folgende Struktur speichert die spaeter vom Server
// geschickten Ausweispapiere; in diesem Fall ein digitales
// Zertifikat:
gnutls_certificate_credentials_t cert_cred;
char buffer2[MAX_BUF + 1]; // Puffer fuer verschluesselte
// Uebertragung (empfangen)
const char *err; // enthaelt beim Auftritt eines
// Fehlers die Position in der
// Zeichenkette; Verwendung
// fuer
// gnutls_priority_set_direct()
// Eingabe der benoetigten Daten
char server[30];
printf("Server: ");
scanf("%s",server);
char user[30]="";
printf("User: ");
scanf("%s",user);
char USER[30]="USER "; // Zusammenfuegen des POP-
strcat(USER,user); // Befehls USER username
strcat(USER,"\r\n"); // Anfuegen von <Return>
char *password;
password=(char *)getpass("Password: "); // Eingabe ohne
// Bildschirm-
// Ausgabe
char PASSWORD[30]="PASS "; // Zusammenfuegen des POP-
strcat(PASSWORD,password); // Befehls PASS passwort
strcat(PASSWORD,"\r\n"); // Anfuegen von <Return>
char buffer[MAXMSG]; // Puffer fuer Nachrichten
// (empfangener Klartext)
uint16_t port=110; // Portnummer POP
int sock=-1; // Fehlerwert fuer Socket
// vordefinieren
// size_t size;
// IP_number() ermittelt die binaere IP-Nummer aus dem
// Servername mittels DNS und schreibt diese in die Struktur
// name vom Typ sockaddr_in, um sie fuer das Socket zur
// Verfuegung zu stellen. Gleichzeitig wird die Port
// Nummer dem Socket bereitgestellt.
IP_number(&name, server, port);
// Geeignetes Socket fuer Verbindung zum Server einrichten
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
perror("socket");
exit (EXIT_FAILURE);
}
// Mit Host verbinden
if (connect(sock, (struct sockaddr *) &name, sizeof (struct
sockaddr_in)) < 0)
{
perror ("connect");
exit (EXIT_FAILURE);
}
// Servermeldung auslesen
int amount = read(sock, buffer, MAXMSG);
printf("%.*s", amount, buffer);
// Fähigkeiten des Servers abrufen (STARTTLS)
write(sock,"CAPA\r\n",6);
amount = read(sock, buffer, MAXMSG);
printf("%.*s", amount, buffer);
// verschluesselten Verbindungsaufbau mit dem Befehl
// 'STLS' starten (STARTTLS)
write(sock,"STLS\r\n",6);
amount = read(sock, buffer, MAXMSG);
printf("%.*s", amount, buffer);
// GnuTLS aktivieren
gnutls_global_init();
// Ausweisdatenspeicher des Clients initialisieren
gnutls_srp_allocate_client_credentials (&srp_cred);
// Ausweisdatenspeicher des Servers (Zertifikat) initialisieren
gnutls_certificate_allocate_credentials (&cert_cred);
// Zertifikate aus Datei in Zertifikatsspeicher laden
printf("Anzahl der verarbeiteten Zertifikate: %d\n",
gnutls_certificate_set_x509_trust_file (cert_cred, CAFILE,
GNUTLS_X509_FMT_PEM));
// Funktion und Speicher zur Ueberpruefung des vom Server
// geschickten Zertifikats festlegen
// Diese Funktion wird tatsaechlich erst aufgerufen, nachdem
// das Server-Zertifikat empfangen worden ist
// Aufruf erfolgt noch vor dem handshake
gnutls_certificate_set_verify_function
(cert_cred,_verify_certificate_callback);
// Folgende Funktion schreibt Benutzername und Passwort
// des Clients in den dafuer eingerichteten Speicher:
gnutls_srp_set_client_credentials (srp_cred, user, password);
// Folgende Funktion legt fest, dass das System, auf welchem
// das Programm laueft, als CLIENT arbeiten soll. Es
// initialisiert die Sitzung:
gnutls_init (&session, GNUTLS_CLIENT);
// Folgende Funktion schreibt Servername (Hostname) in die
// Struktur session:
gnutls_session_set_ptr (session, (void *) server);
// Folgende Funktion schickt den als Hostname verwendeten
// Distinguished Name vor dem handshake an den Server,
// damit der Client das richtige Zertifikat erhaelt.
gnutls_server_name_set (session, GNUTLS_NAME_DNS, server,
strlen(server));
// Grundeinstellungen der zu bevorzugenden chiper suite fuer
// den handshake
ret = gnutls_priority_set_direct (session,
"NORMAL:+SRP:+SRP-RSA:+SRP-DSS", &err);
if (ret < 0)
{
if (ret == GNUTLS_E_INVALID_REQUEST)
{
fprintf (stderr, "Fehler an der Stelle: %s\n", err);
}
exit(1);
}
// Folgende zwei Zeilen uebernehmen die Ausweisangaben von
// Client und Server in die Struktur session:
gnutls_credentials_set (session, GNUTLS_CRD_SRP, srp_cred);
gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, cert_cred);
// Folgende Funktion stellt die Verbindung von eingerichtetem
// Socket und der aktuellen TLS-Sitzung her:
gnutls_transport_set_ptr (session, (gnutls_transport_ptr_t) sock);
// handshake durchfuehren; an dieser Stelle erfolgt der
// verschluesselte Verbindungsaufbau
do
{
ret = gnutls_handshake (session);
} while (ret < 00 && gnutls_error_is_fatal (ret) == 0);
// handshake erfolgreich?
if (ret < 0)
{
fprintf (stderr, "*** Fehler bei der verschluesselten
Verbindungsherstellung.\n");
gnutls_perror (ret);
goto end;
}
else
{
printf ("Herstellung der verschluesselten Verbindung erfolgreich.\n");
}
// Verschluesseltes Senden des POP-Befehls
// USER username <Return>
gnutls_record_send(session, USER,strlen(USER));
// Auslesen der verschluesselten Serverantwort
ret = gnutls_record_recv(session,buffer2,MAX_BUF);
if (gnutls_error_is_fatal (ret) != 0 || ret == 0)
{
if (ret == 0)
{
printf ("Kommunikationspartner hat die verschluesselte Verbindung
abgebrochen.\n");
goto end;
}
else
{
fprintf (stderr, "**** Fehler: %s\n", gnutls_strerror(ret));
goto end;
}
}
if (ret > 0)
{
printf ("%d Bytes empfangen: ", ret);
for (ii = 0 ; ii < ret; ii++)
{
fputc (buffer2[ii], stdout);
}
}
// Verschluesseltes Senden des POP-Befehls
// PASS password <Return>
gnutls_record_send(session, PASSWORD,strlen(PASSWORD));
// Auslesen der verschluesselten Serverantwort
ret = gnutls_record_recv(session,buffer2,MAX_BUF);
if (gnutls_error_is_fatal (ret) != 0 || ret == 0)
{
if (ret == 0)
{
printf ("Kommunikationspartner hat die verschluesselte
Verbindung abgebrochen.\n");
goto end;
}
else
{
fprintf (stderr, "**** Fehler: %s\n", gnutls_strerror(ret));
goto end;
}
}
if (ret > 0)
{
printf ("%d Bytes empfangen: ", ret);
for (ii = 0 ; ii < ret; ii++)
{
fputc (buffer2[ii], stdout);
}
}
// Verschluesseltes Senden des POP-Befehls
// RETR 1 <Return>
// ruft 1. E-Mail vom Server ab
gnutls_record_send(session, "RETR 1\r\n", 8);
// Auslesen der verschluesselten Serverantwort
ret = gnutls_record_recv(session,buffer2,MAX_BUF);
if (gnutls_error_is_fatal (ret) != 0 || ret == 0)
{
if (ret == 0)
{
printf ("Kommunikationspartner hat die verschluesselte
Verbindung abgebrochen.\n");
goto end;
}
else
{
fprintf (stderr, "**** Fehler: %s\n", gnutls_strerror(ret));
goto end;
}
}
if (ret > 0)
{
printf ("%d Bytes empfangen: ", ret);
for (ii = 0 ; ii < ret; ii++)
{
fputc (buffer2[ii], stdout);
}
}
// Folgende Funktion teilt dem Kommunikationspartner (hier
// POP-Server) mit, dass und wie die Verbindung
// abgebrochen werden soll. Damit ist der Verbindungs-
// abbruch von einer arglistigen Unterbrechung unter-
// scheidbar.
gnutls_bye (session, GNUTLS_SHUT_RDWR);
end: // Marke
// Eingerichtetes Socket schliessen (beenden)
close(sock);
// Sitzungsdaten loeschen und damit Speicher freigeben
gnutls_deinit(session);
// Ausweisspeicher des Clients freigeben
gnutls_srp_free_client_credentials (srp_cred);
// Ausweisspeicher des Servers freigeben
gnutls_certificate_free_credentials (cert_cred);
// GnuTLS beenden und damit Speicher freigeben
gnutls_global_deinit();
}
// IP_number(...) ermittelt die binaere IP-Adresse aus dem
// gegebenen Hostnamen und wandelt diese in eine für Menschen
// schreibbare Version um. Die ermittelte binaere IP-Adresse
// wird ausserdem in die Struktur name vom Typ sockaddr_in
// geschrieben, damit sie dem Socket zur Verfuegung steht.
// Gleichzeitig wird mit Hilfe von htons(...) die Portnummer in
// die vom System verwendete binaere Form umgewandelt,
// damit sie in die Struktur name geschrieben werden kann.
void IP_number(struct sockaddr_in *name, char *servername, uint16_t port)
{
char serverIP[16];
// Die Funktion
// struct hostent * gethostbyname (const char *name)
// ermittelt binaere IP-Nummer
if(hostinfo=gethostbyname(servername))
{
// inet_ntop() wandelt _binaere IP-Nummer in die
// fuer Menschen lesbare Nummern-Punkt-Schreibweise
// um. (Beispiel: 193.175.141.61).
inet_ntop(PF_INET, hostinfo->h_addr_list[0], serverIP, 16);
printf("IP: %s\n", serverIP);
// Im Folgenden werden Adressformat, binaere
// Portnummer und binaere IP-Adresse in die Struktur
// name vom Typ sockaddr_in geschrieben, damit diese
// Angaben dem Socket zum Verbindungsaufbau zur
// Verfuegung stehen.
name->sin_family = PF_INET;
name->sin_port = htons(port);
name->sin_addr = *(struct in_addr *) hostinfo->h_addr;
}
else
{
fprintf(stderr, "Unbekannter Host %s.\n", servername);
exit (EXIT_FAILURE);
}
}
// Unterprogramm zur Ueberprüfung des Server-Zertifikats
static int _verify_certificate_callback (gnutls_session_t session)
{
unsigned int status;
const gnutls_datum_t *cert_list;
unsigned int cert_list_size;
int ret;
gnutls_x509_crt_t cert;
const char *hostname;
// Hostname auslesen
hostname = gnutls_session_get_ptr (session);
// Folgende Funktion ueberprueft das vom Server geschickte Zertifikat
// an Hand der zuvor in den Zertifizierungsspeicher der Sitzung
// geladenen Zertifikate
ret = gnutls_certificate_verify_peers2 (session, &status);
if (ret < 0)
{
printf ("Fehler. Zertifikat konnte nicht ueberprueft werden.\n");
return (GNUTLS_E_CERTIFICATE_ERROR);
}
// &: bitweises UND: 1 UND 1 = 1 (sonst immer 0);
// if (0); 0 entspricht FALSCH (FALSE), damit Bedingung nicht erfuellt.
// Jeder andere Wert entspricht WAHR (TRUE), damit Bedingung erfuellt.
if (status & GNUTLS_CERT_SIGNER_NOT_FOUND)
printf ("Das Zertifikat hat keinen bekannten Aussteller.\n");
if (status & GNUTLS_CERT_REVOKED)
printf ("Das Zertifikat wurde widerrufen.\n");
if (status & GNUTLS_CERT_EXPIRED)
printf ("Das Zertifikat ist abgelaufen.\n");
if (status & GNUTLS_CERT_NOT_ACTIVATED)
printf ("Das Zertifikat wurde bis jetzt nicht aktiviert.\n");
if (status & GNUTLS_CERT_INVALID)
{
printf ("Dem Zertifikat wird nicht vertraut.\n");
return (GNUTLS_E_CERTIFICATE_ERROR);
}
if (gnutls_certificate_type_get (session) != GNUTLS_CRT_X509)
return (GNUTLS_E_CERTIFICATE_ERROR);
if (gnutls_x509_crt_init (&cert) < 0 )
{
printf ("Initialisierungsfehler.\n");
return (GNUTLS_E_CERTIFICATE_ERROR);
}
// Die vom Server geschickten Zertifikate speichern
cert_list = gnutls_certificate_get_peers (session, &cert_list_size);
if (cert_list == NULL)
{
printf ("Kein Zertifikat erhalten!\n");
return (GNUTLS_E_CERTIFICATE_ERROR);
}
// Umwandlung des Zertifikatformats von .DER in gnutls_x509_crt_t
// gnutls_x509_crt_t ist GnuTLS-internes Format.
if (gnutls_x509_crt_import (cert, &cert_list[0],
GNUTLS_X509_FMT_DER) < 0)
{
printf ("error parsing certificate\n");
return (GNUTLS_E_CERTIFICATE_ERROR);
}
if (!gnutls_x509_crt_check_hostname (cert, hostname))
{
printf ("Zertifikatstraeger stimmt nicht mit Hostnamen
ueberein. '%s'\n", hostname);
return (GNUTLS_E_CERTIFICATE_ERROR);
}
gnutls_x509_crt_deinit (cert);
// Normaler Programmablauf, d. h. Handshake durchfuehren.
return (0);
}
--
http://home.chiemgau-net.de/ausserstorfer7
[toc] | [prev] | [next] | [standalone]
| From | Chris Gransden <chrisg@care4free.net> |
|---|---|
| Date | 2013-05-23 14:41 +0100 |
| Message-ID | <53505c8d40chrisg@care4free.net> |
| In reply to | #2734 |
In article <knkd0b$66a$1@geiz-ist-geil.priv.at>, Streuner <utellan@yahoo.de> wrote: > Am 20.05.2013 09:18, schrieb Alexander Ausserstorfer: > > the first part is taken: The secure connection to a POP-server with > > digital certificates using GnuTLS. The document of the project is in > > German, though. Take a look at > > > > http://home.chiemgau-net.de/ausserstorfer/Studium/ > Juste un question, plus. Currently I'm looking for a computer on which I > can edit, compile and run the code native(lly) (means that it runs Unix > / Linux instead of Cygwin on Windows). I'm also thinking for a Rasperry > Pi, Beagle or Pandora-board but I'm not sure about if you can do it there. > So, can somebody here try to compile and test the following code on a > machine under Linux like the Rasperry PI, please? Or what is a good > portable machine (laptop) with Unix / Linux? > The programme connects to a POP-Server using STARTTLS and fetchs from > there the first e-mail (not complettely now, it is just for > demonstrating). To make things more difficult, you must also have > installed the required certificates for the server in .PEM-format in > "usr/ssl/certs/E-Mail-Chain.crt". It builds and runs fine natively on RISC OS. Although I get the following when I tested it with gmail, Anzahl der verarbeiteten Zertifikate: 2 *** Fehler bei der verschluesselten Verbindungsherstellung. GnuTLS error: A TLS packet with unexpected length was received. * Chris.
[toc] | [prev] | [next] | [standalone]
| From | Alexander Ausserstorfer <bavariasound@chiemgau-net.de> |
|---|---|
| Date | 2013-05-24 10:05 +0200 |
| Message-ID | <3b9dc15053.Alex@bavariasound.chiemgau-net.de> |
| In reply to | #2735 |
In message <53505c8d40chrisg@care4free.net>
Chris Gransden <chrisg@care4free.net> wrote:
[programm code]
> It builds and runs fine natively on RISC OS.
Did you build it _natively_ on RISC OS?
> Although I get the following when I tested it with gmail,
>
> Anzahl der verarbeiteten Zertifikate: 2
> *** Fehler bei der verschluesselten Verbindungsherstellung.
> GnuTLS error: A TLS packet with unexpected length was received.
Many thanks for the hint! Will try and examine that, soon.
A.
--
http://home.chiemgau-net.de/ausserstorfer/
[toc] | [prev] | [next] | [standalone]
| From | Chris Gransden <chrisg@care4free.net> |
|---|---|
| Date | 2013-05-24 11:38 +0100 |
| Message-ID | <5350cfad90chrisg@care4free.net> |
| In reply to | #2737 |
In article <3b9dc15053.Alex@bavariasound.chiemgau-net.de>, Alexander Ausserstorfer <bavariasound@chiemgau-net.de> wrote: > In message <53505c8d40chrisg@care4free.net> > Chris Gransden <chrisg@care4free.net> wrote: > [programm code] > > It builds and runs fine natively on RISC OS. > Did you build it _natively_ on RISC OS? Once I got all the required library dependancies built it builds fine on RISC OS with GCC. Hopefully all the libraries you need will be available for download from riscos.info in the next few days. Chris.
[toc] | [prev] | [standalone]
Back to top | Article view | comp.sys.acorn.programmer
csiph-web