I need to run GnuTLS with X509 in Server/Client (doubts and needs fixing) - ssl

GnuTLS suffered drastic changes as I see in the examples mentioned in the following websites with respect to my version of code that previously worked based on almost the same examples as before:
Echo server with X.509 authentication
Client example with X.509 certificate support
the problem is that before you had to use the authority certificate for the client program, now you need the certificate and the key that was only used on the server side. What is this drastic change? In the end which side belongs as private and public among the generated certificates? (according to the example, I have to replace gnutls_certificate_set_x509_trust_file by gnutls_certificate_set_x509_key_file)
What are the lines with the parameters for the openssl command that I have to use to generate all the necessary certificates in this example of Server and Client?
It is also very confusing the issue of the file names for the generated certificates, sometimes it is .pem and sometimes .crt/.key, tell you how I should create these names exactly (if you think some of this is wrong).
Because of the updates of GnuTLS it has stopped working and now the Handshake fails, causing the server to fail the handshake and in the client continue believing that the connection is fine.
this is the code:
Server:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <gnutls/gnutls.h>
int main(){
const char*txterr;
int lsck;
gnutls_certificate_credentials_t xcred;
gnutls_priority_t pcache;
gnutls_session_t sesion;
sockaddr_in _cli;
//INICIO GLOBAL
//if(!gnutls_check_version("3.6.15"))return -1;
if(!gnutls_check_version("3.5.10"))return -1;
if(gnutls_global_init()<0)return -2;
if(gnutls_certificate_allocate_credentials(&xcred)<0)return -3;
if(gnutls_certificate_set_x509_trust_file(xcred,"cert/ca.crt",GNUTLS_X509_FMT_PEM)<0)return -4;
//if(gnutls_certificate_set_x509_crl_file(xcred,"cert/revocar.crl",GNUTLS_X509_FMT_PEM)<0)return -5;
if(gnutls_certificate_set_x509_key_file(
xcred,"cert/serv.crt","cert/serv.key",GNUTLS_X509_FMT_PEM)<0)return -6;
//if(gnutls_certificate_set_ocsp_status_request_file(xcred,"reqocsp.der",0)<0)return -4;
if(gnutls_priority_init(&pcache,"PERFORMANCE:%SERVER_PRECEDENCE",&txterr)<0){printf("TLS: %s\n",txterr);return -7;}
if(gnutls_certificate_set_known_dh_params(xcred,GNUTLS_SEC_PARAM_MEDIUM)<0)return -8;
//ABRE PUERTO SERVIDOR
lsck=socket(AF_INET,SOCK_STREAM,0);
if(lsck==-1){lsck=0;printf("Imposible usar Puerto\n");return -1;}
{int optval=1;setsockopt(lsck,SOL_SOCKET,SO_REUSEADDR,(void*)&optval,sizeof(int));}
//Convierte el puerto en Escucha
{
struct sockaddr_in dsrv;
dsrv.sin_family=AF_INET;
dsrv.sin_port=htons(9080);
dsrv.sin_addr.s_addr=INADDR_ANY;
if(bind(lsck,(struct sockaddr*)&dsrv,sizeof(dsrv))!=0)
{printf("Imposible bindear Puerto\n");return -2;}
if(listen(lsck,10)!=0)
{printf("Imposible abrir Puerto\n");return -3;}
}
printf("Abriendo Puerto\n");
//ESCUCHA PUERTO
if(gnutls_init(&sesion,GNUTLS_SERVER)<0)return -6;
if(gnutls_priority_set(sesion,pcache)<0)return -6;
if(gnutls_credentials_set(sesion,GNUTLS_CRD_CERTIFICATE,xcred)<0)return -6;
gnutls_certificate_server_set_request(sesion,GNUTLS_CERT_IGNORE);
gnutls_handshake_set_timeout(sesion,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
int _scli=sizeof(sockaddr_in);
int nsck=accept(lsck,(sockaddr*)&_cli,(socklen_t*)&_scli);
if(nsck<0)return -3;
gnutls_transport_set_int(sesion,nsck);
int tm;
do{
tm=gnutls_handshake(sesion);
}while(tm<0&&gnutls_error_is_fatal(tm)==0);
if(tm<0){close(nsck);gnutls_deinit(sesion);return -6;}
printf("Entrando Usuario: %x:%d\n",_cli.sin_addr,_cli.sin_port);
//CIFRA PUERTO CLIENTE
gnutls_datum_t out;
gnutls_session_t tls_sesion;
if(gnutls_init(&tls_sesion,GNUTLS_CLIENT)<0)return -6;
if(gnutls_server_name_set(tls_sesion,GNUTLS_NAME_DNS,"blackrook.ddns.net",strlen("blackrook.ddns.net"))<0)return -7;
if(gnutls_set_default_priority(tls_sesion)<0)return -8;
int ret=gnutls_priority_set_direct(tls_sesion,"NORMAL",&txterr);
if(ret<0){
switch(ret){
case GNUTLS_E_INVALID_REQUEST:
printf("Error tipo %s\n",txterr);
return -9;
}
}
if(gnutls_credentials_set(tls_sesion,GNUTLS_CRD_CERTIFICATE,xcred)<0)return -10;
gnutls_session_set_verify_cert(tls_sesion,"blackrook.ddns.net",0);
//Toma el FD Socket
gnutls_transport_set_int(tls_sesion,nsck);
gnutls_handshake_set_timeout(tls_sesion,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
do{ret=gnutls_handshake(tls_sesion);
}while(ret<0&&!gnutls_error_is_fatal(ret));
if(ret<0){
gnutls_certificate_type_t type;
int status;
switch(ret){
case GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR:
type=gnutls_certificate_type_get(tls_sesion);
status=gnutls_session_get_verify_cert_status(tls_sesion);
if(gnutls_certificate_verification_status_print(status,type,&out,0)<0)return -255;
printf("TLS: cert verify output: %s\n",out.data);
gnutls_free(out.data);
}
printf("TLS: Handshake fallado: %s\n",gnutls_strerror(ret));
return -11;
}{
char*desc=gnutls_session_get_desc(tls_sesion);
printf("TLS: Session info: %s\n",desc);
gnutls_free(desc);
}
//Envia mensaje cifrado
char*msg="Este es canal abierto.";
gnutls_record_send(tls_sesion,msg,strlen(msg)+1);
//CIERRA
if(gnutls_bye(tls_sesion,GNUTLS_SHUT_WR)<0)printf("TLS: Falla cerrando\n");
close(nsck);
gnutls_deinit(tls_sesion);
close(lsck);
gnutls_certificate_free_credentials(xcred);
gnutls_priority_deinit(pcache);
gnutls_global_deinit();
return 0;
}
Cliente:
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <gnutls/gnutls.h>
int main(){
int fd;
const char*txterr;
gnutls_certificate_credentials_t xcred;
gnutls_session_t tls_sesion;
//INICIA TLS
if(!gnutls_check_version("3.5.10"))return -1;
if(gnutls_global_init()<0)return -2;
if(gnutls_certificate_allocate_credentials(&xcred)<0)return -3;
if(gnutls_certificate_set_x509_system_trust(xcred)<0)return -4;
if(gnutls_certificate_set_x509_trust_file(xcred,"cert/ca.crt",GNUTLS_X509_FMT_PEM)<0)return -5;
//if(gnutls_certificate_set_x509_key_file(xcred,"cert/cert.pem","cert/key.pem",GNUTLS_X509_FMT_PEM)<0)return -5;
//ABRE SOCKET
fd=socket(AF_INET,SOCK_STREAM,0);
if(fd==-1){printf("Imposible abrir nuevo E/S\n");return -1;}
struct addrinfo hints,*serv,*p;
char*zip="blackrook.ddns.net",*zprt="9080";
memset(&hints,0,sizeof(hints));
hints.ai_family=AF_UNSPEC;
hints.ai_socktype=SOCK_STREAM;
int i,ip;
if(i=getaddrinfo(zip,zprt,&hints,&serv)){
printf("Conexion no establecida\n");return 0;}
for(p=serv;p!=0;p=p->ai_next){
if(p->ai_addr->sa_family==AF_INET){
ip=((struct sockaddr_in*)p->ai_addr)->sin_addr.s_addr;
if(connect(fd,p->ai_addr,p->ai_addrlen)==-1)continue;
freeaddrinfo(serv);
printf("Conexion establecida\n");goto JmpConti;
}
}freeaddrinfo(serv);printf("Conexion no establecida2\n");return 0;
JmpConti:
//CIFRA PUERTO
gnutls_datum_t out;
if(gnutls_init(&tls_sesion,GNUTLS_CLIENT)<0)return -6;
if(gnutls_server_name_set(tls_sesion,GNUTLS_NAME_DNS,"blackrook.ddns.net",strlen("blackrook.ddns.net"))<0)return -7;
if(gnutls_set_default_priority(tls_sesion)<0)return -8;
int ret=gnutls_priority_set_direct(tls_sesion,"NORMAL",&txterr);
if(ret<0){
switch(ret){
case GNUTLS_E_INVALID_REQUEST:
printf("Error tipo %s\n",txterr);
return -9;
}
}
if(gnutls_credentials_set(tls_sesion,GNUTLS_CRD_CERTIFICATE,xcred)<0)return -10;
gnutls_session_set_verify_cert(tls_sesion,"blackrook.ddns.net",0);
//Toma el FD Socket
gnutls_transport_set_int(tls_sesion,fd);
gnutls_handshake_set_timeout(tls_sesion,GNUTLS_DEFAULT_HANDSHAKE_TIMEOUT);
do{ret=gnutls_handshake(tls_sesion);
}while(ret<0&&!gnutls_error_is_fatal(ret));
if(ret<0){
printf("RET:%d\n",ret);
gnutls_certificate_type_t type;
int status;
switch(ret){
case GNUTLS_E_CERTIFICATE_VERIFICATION_ERROR:
type=gnutls_certificate_type_get(tls_sesion);
status=gnutls_session_get_verify_cert_status(tls_sesion);
if(gnutls_certificate_verification_status_print(status,type,&out,0)<0)return -255;
printf("TLS: cert verify output: %s\n",out.data);
gnutls_free(out.data);
}
printf("TLS: Handshake fallado: %s\n",gnutls_strerror(ret));
return -11;
}{
char*desc=gnutls_session_get_desc(tls_sesion);
printf("TLS: Session info: %s\n",desc);
gnutls_free(desc);
}
//Recibe mensaje
char msg[16387];long max=16387,nres;
sleep(4);
nres=gnutls_record_recv(tls_sesion,msg,max);
printf("R:%s\n",msg);
//CIERRA PUERTO
if(gnutls_bye(tls_sesion,GNUTLS_SHUT_RDWR)<0)printf("TLS: Falla cerrando\n");
close(fd);
gnutls_deinit(tls_sesion);
gnutls_certificate_free_credentials(xcred);
gnutls_global_deinit();
return 0;
}

Related

How can I modify my code to read from a file input in client and then communicate it to a server?

Code:
//server.c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <WinSock2.h>
#include <Windows.h>
#define SCK_VERSION 0x0202
int main()
{
//declare sockets first
SOCKET ConSock; // used for connection, hence the name
SOCKET ListenSock; // used for listening from the server
SOCKADDR_IN address; //socket address
int addrsize = sizeof(address);
long ok;
char MESSAGE[200];
char reply[200];
WSADATA WSD;
WORD DllVersion;
DllVersion = MAKEWORD(2,1);
ok = WSAStartup(DllVersion, &WSD);
//start creating our sockets
ConSock = socket(AF_INET, SOCK_STREAM, NULL);
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_family = AF_INET;
address.sin_port = htons(10103);
ListenSock = socket(AF_INET, SOCK_STREAM, NULL);
bind(ListenSock, (SOCKADDR*)&address, sizeof(address));
listen(ListenSock, SOMAXCONN);
printf("Server waiting for connections\n\n");
for(;;){
if (ConSock = accept(ListenSock, (SOCKADDR*)&address, &addrsize))
{
ok = recv(ConSock, MESSAGE, sizeof(MESSAGE),NULL);
printf("\nClient says:\t %s", MESSAGE);
printf("\nEnter reply:\t");
gets(reply);
ok = send(ConSock,reply,200,NULL);
}
}
}
//client.c
#include <stdio.h>
#include <stdlib.h>
#include <conio.h>
#include <WinSock2.h>
#include <Windows.h>
#define SCK_VERSION 0x0202
int main()
{
SOCKET sock;
SOCKADDR_IN address;
long ok;
char MESSAGE[200];
char reply[200];
WSADATA WSD;
WORD DllVersion;
DllVersion = MAKEWORD(2,1);
ok = WSAStartup(DllVersion, &WSD);
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_family = AF_INET;
address.sin_port = htons(10103);
for(;;)
{
sock = socket(AF_INET,SOCK_STREAM,NULL);
connect(sock, (SOCKADDR*)&address, sizeof(address));
printf("\nEnter Message:\t");
gets(MESSAGE);
ok = send(sock,MESSAGE,200,NULL);
ok = recv(sock,reply,sizeof(reply),NULL);
printf("\nServer says:\t %s",reply);
}
}
//makefile
server:
g++ server.c -o server
client:
g++ client.c -o client
clean:
rm server
rm client
all: server client
This runs with -lwsock32 and it does a good job, but I need to adjust it now to comunicate some data from a file, the data is mostly values of voltages, currents, active reactive power, etc.
I have been trying for quite some time and I cannot seem to adjust it.
If you can rewrite it in terms of the client communicating the values(that are stored in a file) to the server, that will be great. Any help is greatly appreciated, as I am not being succesful currently.

Find CPU times and system times of process in linux

I have a main program that creates two children and each children calls execlv. At the end of the program how do I calculate the CPU times and system times of the parent and two process?
#include <sys/types.h>
#include <sys/wait.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <stdlib.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <signal.h>
int main()
{
pid_t pid1,pid2,wid; // variable for parent and two children
char *my_args[3]; // strign array for containing the arguments for executing sigShooter1
// int aInt = 368; //
char str[15]; // strign to contain the pids of children when passing as command line arguments
pid1 = fork();
if (pid1 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid1 == 0)
{
my_args[0] = "sigperf1";
my_args[1] = "0";
my_args[2] = NULL;
execv("sigshooter1",my_args);
fprintf(stderr,"sigshooter1 cannot be executed by first child...");
exit(-1);
}
pid2 = fork();
if(pid2 < 0)
{
fprintf(stderr, ": fork failed: %s\n", strerror(errno));
exit(1);
}
if(pid2 == 0)
{
sprintf(str, "%d", pid1);
my_args[0] = "sigperf1";
my_args[1] = str;
my_args[2] = NULL;
// printf("this is converted = %s\n",my_args[1]);
//sleep(1);
execv("sigshooter1",my_args);
fprintf(stderr,"sigshooter1 cannot be executed by second child...");
exit(-1);
}
wid = wait(NULL);
}
You'll need a profiler for that. For starters, you can run perf stat ./a.out to get the total CPU time of all three processes, and perf stat -i ./a.out to get the CPU time of parent process only.
If you need something more detailed, take a look at more serious tools like valgrind or gprof.

how to perform ssdp communicationbetween upnp devices

i am trying to implement the upnp level communication between the devices .. but facing problem in getting the response message .and more over on sending the ssdp:discovery multicast not able to recieve the messages from the devices ... please guide me through i am completely newto this topic
pre-requisite done by me :
1.able to send the M-Search ..and notify message on the network .. and have confirmed via wireshark
2.gone through the upnp architecture related pdf
response got in wireshark :
when ever i am sending the message i am getting the icmp error message that destination is not reachable ..
< client side code > is the first one and second one is the for time being i am just sending up the data on local host
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define SRV_IP "127.0.0.1"
/* diep(), #includes and #defines like in the server */
#define BUFLEN 512
#define NPACK 10
#define PORT 1900
void diep(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SRV_IP, &si_other.sin_addr)==0) {
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
for (i=0; i<NPACK; i++) {
printf("Sending packet %d\n", i);
sprintf(buf, "\n");
if (sendto(s, buf, BUFLEN, 0, &si_other, slen)==-1)
diep("sendto()");
}
close(s);
return 0;
}
#include <arpa/inet.h>
#include <netinet/in.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#define BUFLEN 512
#define NPACK 10
#define PORT 1900
void diep(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other;
int s, i, slen=sizeof(si_other);
char buf[BUFLEN];
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
diep("socket");
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
if (bind(s, &si_me, sizeof(si_me))==-1)
diep("bind");
for (i=0; i<NPACK; i++) {
if (recvfrom(s, buf, BUFLEN, 0, &si_other, &slen)==-1)
diep("recvfrom()");
printf("Received packet from %s:%d\nData: %s\n\n",
inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port), buf);
}
close(s);
return 0;
}
The individual lines in you M-SEARCH need to have "\r\n" at the end of each line, not just a "\n". Your system may just be sending "\n" across the wire. Check the bytes you're sending for a 13 followed by a 10. That's "\r\n".

getaddrinfo on raspbian returns only loopback IP, same code on OS X multiple

I have a short test program to fetch the IP address of the local machine. On Raspbian, only the loopback address is returned, while the same code on OS X return both normal and loopback IPs.
The code is
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <iostream>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <errno.h>
using namespace std;
int main (int argc, char * const argv[]) {
char hostname[128];
int result = gethostname(hostname, 127);
if (result != 0) {
cout << "FATAL: gethostname failed: " << result << errno;
return -1;
}
cout << "Host name is " << hostname << endl;
struct addrinfo hints, *res;
int errcode;
char addrstr[100];
void *ptr;
memset(&hints, 0, sizeof(hints));
hints.ai_family = PF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags |= AI_CANONNAME;
errcode = getaddrinfo(hostname, NULL, &hints, &res);
if (errcode != 0) {
perror("getaddrinfo");
return -1;
}
while(res) {
inet_ntop(res->ai_family, res->ai_addr->sa_data, addrstr, 100);
switch(res->ai_family) {
case AF_INET:
ptr = &((struct sockaddr_in *)res->ai_addr)->sin_addr;
break;
case AF_INET6:
ptr = &((struct sockaddr_in6 *)res->ai_addr)->sin6_addr;
break;
default:
cout << "Unknown family" << endl;
}
inet_ntop(res->ai_family, ptr, addrstr, 100);
printf("IPV%d address: %s (%s)\n", res->ai_family == PF_INET6 ? 6 : 4, addrstr, res->ai_canonname);
res = res->ai_next;
}
return 0;
}
On OS X I get:
[Coyote]collector$ ./quick
Host name is Coyote.local
IPV4 address: 192.168.1.108 (coyote.local)
IPV6 address: fe80::223:dfff:fea0:a230 (coyote.local)
But on Raspbian I only get:
pi:~$ ./quick
Host name is pi
IPV4 address: 127.0.1.1 (pi)
yet
pi:~$ ifconfig
eth0 Link encap:Ethernet HWaddr b8:27:eb:62:15:fc
inet addr:192.168.1.162 Bcast:192.168.1.255 Mask:255.255.255.0
[...]
What do I need to do on Raspbian to get the correct result?
This is probably due to the contents of your /etc/hosts file. If your goal is to obtain the ip addresses of the system, consider using getifaddrs instead. It's of BSD origin, but works on Linux as well.
If you want for sure to know which address will be used when you connect somewhere, the best way to do it than to connect and then obtain the address using getsockname. The other option would be to read the routing tables.
Also, getnameinfo is usually a better choice than inet_ntop.

How to print HFS Volume header

Any one please give code snippet for how to print volume header of HFS+ disk.
I’ve written a small program (based on hfs-183.1) that prints some of the information declared in struct HFSPlusVolumeHeader. The program must be run as root — for instance, via sudo(8):
#include <fcntl.h>
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/stat.h>
#include <hfs/hfs_format.h>
#include <libkern/OSByteOrder.h>
int main(void) {
int fd;
struct stat stat_buf;
struct HFSPlusVolumeHeader vheader;
const char *vname = "/dev/rdisk0s2";
if (lstat(vname, &stat_buf) == -1) {
fprintf(stderr, "Couldn't stat %s\n", vname);
perror(NULL);
exit(1);
}
if ((stat_buf.st_mode & S_IFMT) != S_IFCHR) {
fprintf(stderr, "%s is not a raw char device\n", vname);
perror(NULL);
exit(2);
}
fd = open(vname, O_RDONLY);
if (fd == -1) {
fprintf(stderr, "%s couldn't be opened for reading\n", vname);
perror(NULL);
exit(3);
}
// The volume header starts at offset 1024
if (pread(fd, &vheader, sizeof vheader, 1024) != sizeof vheader) {
fprintf(stderr, "couldn't read %s's volume header\n", vname);
perror(NULL);
exit(4);
}
printf("fileCount = %u\n"
"folderCount = %u\n"
"blockSize = %u\n"
"totalBlocks = %u\n"
"freeBlocks = %u\n",
OSSwapBigToHostInt32(vheader.fileCount),
OSSwapBigToHostInt32(vheader.folderCount),
OSSwapBigToHostInt32(vheader.blockSize),
OSSwapBigToHostInt32(vheader.totalBlocks),
OSSwapBigToHostInt32(vheader.freeBlocks));
close(fd);
return 0;
}
The header file <hfs/hfs_format.h> declares struct HFSPlusVolumeHeader. See this file for the complete list of fields inside a HFS+ volume header.
The system call getattrlist() might give you the information you need.