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