/mandos/trunk

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/trunk
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
1
extern "C" {
2
#include <sys/types.h>		// getaddrinfo, gai_strerror, socket, inet_pton
3
				// connect
4
#include <sys/socket.h>		// getaddrinfo, gai_strerror, socket, inet_pton
5
				// connect
2.1.1 by Björn Påhlsson
Client:
6
#include <unistd.h>		// close, STDIN_FILENO, STDOUT_FILENO
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
7
#include <netdb.h>		// getaddrinfo, gai_strerror
8
#include <arpa/inet.h>		// inet_pton
9
#include <sys/select.h> 	// select
10
#include <gnutls/gnutls.h>
2.1.1 by Björn Påhlsson
Client:
11
#include <sys/ioctl.h> 		// ioctl, ifreq, SIOCGIFFLAGS, IFF_UP, SIOCSIFFLAGS
12
#include <net/if.h> 		// ioctl, ifreq, SIOCGIFFLAGS, IFF_UP, SIOCSIFFLAGS
13
#include <termios.h> 		// struct termios, tcsetattr, tcgetattr, TCSAFLUSH, ECHO
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
14
}
15
16
#include <cerrno>		// perror
17
#include <cstring> 		// memset
2.1.1 by Björn Påhlsson
Client:
18
#include <string> 		// std::string, std::getline
19
#include <iostream> 		// cin, cout, cerr
20
#include <ostream> 		// <<
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
21
2.1.1 by Björn Påhlsson
Client:
22
#define SOCKET_ERR(err,s) if(err<0) {perror(s); status = 1; goto quit;}
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
23
#define PORT 49001
7 by Teddy Hogeborn
* Makefile (client_debug): New.
24
25
#ifndef CERT_ROOT
26
#define CERT_ROOT "/conf/conf.d/cryptkeyreq/"
27
#endif
28
#define CERTFILE CERT_ROOT "client-cert.pem"
29
#define KEYFILE CERT_ROOT "client-key.pem"
30
#define CAFILE CERT_ROOT "ca.pem"
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
31
32
gnutls_certificate_credentials_t x509_cred;
33
34
gnutls_session_t
35
initgnutls(){
36
  gnutls_session_t session;
37
2.1.1 by Björn Påhlsson
Client:
38
#ifdef DEBUG
39
  std::cerr << "Initiate certificates\n";
40
#endif
41
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
42
  gnutls_global_init ();
43
44
  /* X509 stuff */
45
  gnutls_certificate_allocate_credentials (&x509_cred);
46
  gnutls_certificate_set_x509_trust_file (x509_cred, CAFILE, GNUTLS_X509_FMT_PEM);
47
  gnutls_certificate_set_x509_key_file (x509_cred, CERTFILE, KEYFILE,
48
					GNUTLS_X509_FMT_PEM);
49
50
  //Gnutls stuff
51
  gnutls_init (&session, GNUTLS_CLIENT);
52
  gnutls_set_default_priority (session);
53
  gnutls_credentials_set (session, GNUTLS_CRD_CERTIFICATE, x509_cred);
54
  return session;
55
}
56
57
58
int main (){
2.1.1 by Björn Påhlsson
Client:
59
  int udp_sd, tcp_sd, ret;
2 by Björn Påhlsson
Working client and server and password system
60
  char buffer[4096];
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
61
  struct sockaddr_in6 to;
62
  struct sockaddr_in6 from;
63
  gnutls_session_t session;
64
  fd_set rfds_orig;
65
  struct timeval timeout;
66
2.1.1 by Björn Påhlsson
Client:
67
  struct termios t_old, t_new;
68
  int status = 0;
9 by Teddy Hogeborn
* client.cpp (main): Get t_old early since it is used on error exits.
69
  
70
  if (tcgetattr (STDIN_FILENO, &t_old) != 0){
71
    return 1;
72
  }
73
  
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
74
  session = initgnutls ();
75
2.1.1 by Björn Påhlsson
Client:
76
#ifdef DEBUG
77
  std::cerr << "Open ipv6 UDP\n";
78
#endif
79
80
  udp_sd = socket(PF_INET6, SOCK_DGRAM, 0);
81
  SOCKET_ERR(udp_sd,"socket");
82
  
83
#ifdef DEBUG
84
  std::cerr << "Open socket with socket nr: " << udp_sd << '\n';
85
#endif
86
  
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
87
  {
88
    int flag = 1;
2.1.1 by Björn Påhlsson
Client:
89
    ret = setsockopt(udp_sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
90
    SOCKET_ERR(ret,"setsockopt broadcast");
91
  }
92
2.1.1 by Björn Påhlsson
Client:
93
  ret = setsockopt(udp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
94
  SOCKET_ERR(ret,"setsockopt bindtodevice");
95
96
  memset (&to, '\0', sizeof (to));
97
  to.sin6_family = AF_INET6;
98
  ret = inet_pton(AF_INET6, "ff02::1" , &to.sin6_addr);
2.1.1 by Björn Påhlsson
Client:
99
  SOCKET_ERR(ret,"inet_pton");
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
100
  to.sin6_port = htons (PORT);	// Server Port number
101
2.1.1 by Björn Påhlsson
Client:
102
  struct ifreq network;
103
104
  strcpy(network.ifr_name, "eth0");
105
106
  ret = ioctl(udp_sd, SIOCGIFFLAGS, &network);
107
  SOCKET_ERR(ret,"ioctl SIOCGIFFLAGS");
108
109
  network.ifr_flags |= IFF_UP;
110
111
  ret = ioctl(udp_sd, SIOCSIFFLAGS, &network);
112
  SOCKET_ERR(ret,"ioctl SIOCSIFFLAGS");
113
    
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
114
  FD_ZERO(&rfds_orig);
2.1.1 by Björn Påhlsson
Client:
115
  FD_SET(udp_sd, &rfds_orig);
116
  FD_SET(STDIN_FILENO, &rfds_orig);
9 by Teddy Hogeborn
* client.cpp (main): Get t_old early since it is used on error exits.
117
  
2.1.1 by Björn Påhlsson
Client:
118
  t_new = t_old;
119
  t_new.c_lflag &= ~ECHO;
120
  if (tcsetattr (STDIN_FILENO, TCSAFLUSH, &t_new) != 0){
121
    return 1;
122
  }
123
  
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
124
  for(;;){
2.1.1 by Björn Påhlsson
Client:
125
    for(;;){
126
127
#ifdef DEBUG
128
      std::cerr << "Sending Marco on UDP\n";
129
#endif
130
      ret = sendto(udp_sd, "Marco", 5, 0, reinterpret_cast<const sockaddr*>(&to), sizeof(to));
131
      if (ret < 0){
132
	perror("sendto");
133
      }
134
      
135
      fd_set rfds = rfds_orig;
136
      timeout.tv_sec = 10;
137
      timeout.tv_usec = 0;
138
      
139
      std::cerr << "Password: ";
140
      
141
      ret = select(udp_sd+1, &rfds, 0, 0, & timeout);
142
      SOCKET_ERR(udp_sd,"select");
143
      
144
      if (ret){
145
	if (FD_ISSET(STDIN_FILENO, &rfds)){
146
	  std::string buffer;
147
	  std::getline(std::cin, buffer);
148
	  std::cerr << '\n';
149
	  std::cout << buffer;
150
	  goto quit;
151
	}
152
	
153
	socklen_t from_len = sizeof(from);
154
	ret = recvfrom(udp_sd,buffer,512,0, reinterpret_cast<sockaddr *>(& from),
155
		       & from_len);
156
	SOCKET_ERR(ret,"recv");
157
	
158
	if (strncmp(buffer,"Polo", 4) == 0){
159
	  break;
160
	}
161
      }
162
      std::cerr << '\r';
163
    }
164
    
165
    
166
    tcp_sd = socket(PF_INET6, SOCK_STREAM, 0);
167
    SOCKET_ERR(tcp_sd,"socket");
168
    
169
    setsockopt(tcp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
170
    SOCKET_ERR(ret,"setsockopt bindtodevice");
171
    
172
    memset(&to,0,sizeof(to));
173
    to.sin6_family = from.sin6_family;
174
    to.sin6_port   = from.sin6_port;
175
    to.sin6_addr   = from.sin6_addr;
176
    to.sin6_scope_id   = from.sin6_scope_id;
177
    
178
    ret = connect(tcp_sd,reinterpret_cast<struct sockaddr *>(&to),sizeof(to));
179
    if (ret < 0){
180
      perror("connect");
181
      continue;
182
    }
183
    
184
    gnutls_transport_set_ptr (session, reinterpret_cast<gnutls_transport_ptr_t> (tcp_sd));
185
    
186
    ret = gnutls_handshake (session);
187
    
188
    if (ret < 0)
189
      {
190
	std::cerr << "\n*** Handshake failed ***\n";
191
	gnutls_perror (ret);
192
	continue;
193
      }
194
    
195
    //retrive password
196
    ret = gnutls_record_recv (session, buffer, sizeof(buffer));
197
    
198
    write(STDOUT_FILENO,buffer,ret);
199
    
200
    //shutdown procedure
201
    gnutls_bye (session, GNUTLS_SHUT_RDWR);
202
    close(tcp_sd);
203
    gnutls_deinit (session);
204
    gnutls_certificate_free_credentials (x509_cred);
205
    gnutls_global_deinit ();
206
    break;
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
207
  }
2.1.1 by Björn Påhlsson
Client:
208
  close(udp_sd);
209
210
 quit:
211
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &t_old);
212
  return status;
1 by Björn Påhlsson
First working version with: IPv6, GnuTLS, X.509 certificates, DN
213
}