/mandos/release

To get this branch, use:
bzr branch http://bzr.recompile.se/loggerhead/mandos/release

« back to all changes in this revision

Viewing changes to client.cpp

  • Committer: Björn Påhlsson
  • Date: 2007-10-20 21:38:25 UTC
  • Revision ID: belorn@tower-20071020213825-abf6f0d1c33ee961
First working version with: IPv6, GnuTLS, X.509 certificates, DN
retrieval.

Show diffs side-by-side

added added

removed removed

Lines of Context:
3
3
                                // connect
4
4
#include <sys/socket.h>         // getaddrinfo, gai_strerror, socket, inet_pton
5
5
                                // connect
6
 
#include <unistd.h>             // close, STDIN_FILENO, STDOUT_FILENO
 
6
#include <unistd.h>             // close
7
7
#include <netdb.h>              // getaddrinfo, gai_strerror
8
8
#include <arpa/inet.h>          // inet_pton
9
9
#include <sys/select.h>         // select
10
10
#include <gnutls/gnutls.h>
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
14
11
}
15
12
 
 
13
#include <cstdio>               // fprintf
16
14
#include <cerrno>               // perror
17
15
#include <cstring>              // memset
18
 
#include <string>               // std::string, std::getline
19
 
#include <iostream>             // cin, cout, cerr
20
 
#include <ostream>              // <<
21
16
 
22
 
#define SOCKET_ERR(err,s) if(err<0) {perror(s); status = 1; goto quit;}
 
17
#define SOCKET_ERR(err,s) if(err<0) {perror(s);return(1);}
23
18
#define PORT 49001
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"
 
19
#define CERTFILE "client-cert.pem"
 
20
#define KEYFILE "client-key.pem"
 
21
#define CAFILE "ca.pem"
31
22
 
32
23
gnutls_certificate_credentials_t x509_cred;
33
24
 
35
26
initgnutls(){
36
27
  gnutls_session_t session;
37
28
 
38
 
#ifdef DEBUG
39
 
  std::cerr << "Initiate certificates\n";
40
 
#endif
41
 
 
42
29
  gnutls_global_init ();
43
30
 
44
31
  /* X509 stuff */
56
43
 
57
44
 
58
45
int main (){
59
 
  int udp_sd, tcp_sd, ret;
60
 
  char buffer[4096];
 
46
  int sd, ret;
 
47
  char buffer[512];
61
48
  struct sockaddr_in6 to;
62
49
  struct sockaddr_in6 from;
63
50
  gnutls_session_t session;
64
51
  fd_set rfds_orig;
65
52
  struct timeval timeout;
66
53
 
67
 
  struct termios t_old, t_new;
68
 
  int status = 0;
69
 
  
70
 
  if (tcgetattr (STDIN_FILENO, &t_old) != 0){
71
 
    return 1;
72
 
  }
73
 
  
74
54
  session = initgnutls ();
75
55
 
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
 
  
 
56
  sd = socket(PF_INET6, SOCK_DGRAM, 0);
 
57
  SOCKET_ERR(sd,"socket");
 
58
 
87
59
  {
88
60
    int flag = 1;
89
 
    ret = setsockopt(udp_sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
 
61
    ret = setsockopt(sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
90
62
    SOCKET_ERR(ret,"setsockopt broadcast");
91
63
  }
92
64
 
93
 
  ret = setsockopt(udp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
 
65
  setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
94
66
  SOCKET_ERR(ret,"setsockopt bindtodevice");
95
67
 
96
68
  memset (&to, '\0', sizeof (to));
97
69
  to.sin6_family = AF_INET6;
98
70
  ret = inet_pton(AF_INET6, "ff02::1" , &to.sin6_addr);
99
 
  SOCKET_ERR(ret,"inet_pton");
 
71
  SOCKET_ERR(ret,"setsockopt bindtodevice");
100
72
  to.sin6_port = htons (PORT);  // Server Port number
101
73
 
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
 
    
114
74
  FD_ZERO(&rfds_orig);
115
 
  FD_SET(udp_sd, &rfds_orig);
116
 
  FD_SET(STDIN_FILENO, &rfds_orig);
117
 
  
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
 
  
 
75
  FD_SET(sd, &rfds_orig);
 
76
 
 
77
  timeout.tv_sec = 10;
 
78
  timeout.tv_usec = 0;
 
79
 
 
80
 
124
81
  for(;;){
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;
 
82
    sendto(sd, "Marco", 5, 0, reinterpret_cast<const sockaddr*>(&to), sizeof(to));
 
83
 
 
84
    fd_set rfds = rfds_orig;
 
85
 
 
86
    ret = select(sd+1, &rfds, 0, 0, & timeout);
 
87
    SOCKET_ERR(sd,"select");
 
88
 
 
89
    if (ret){
 
90
      socklen_t from_len = sizeof(from);
 
91
      ret = recvfrom(sd,buffer,512,0, reinterpret_cast<sockaddr *>(& from),
 
92
                     & from_len);
 
93
      SOCKET_ERR(ret,"recv");
 
94
 
 
95
      if (strncmp(buffer,"Polo", 4) == 0){
 
96
        break;
 
97
      }
 
98
    }
207
99
  }
208
 
  close(udp_sd);
209
 
 
210
 
 quit:
211
 
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &t_old);
212
 
  return status;
 
100
 
 
101
  write(1,buffer,ret);
 
102
  write(1,"\n",1);
 
103
 
 
104
  //shutdown procedure
 
105
  close(sd);
 
106
 
 
107
  sleep(1);
 
108
 
 
109
  sd = socket(PF_INET6, SOCK_STREAM, 0);
 
110
  SOCKET_ERR(sd,"socket");
 
111
 
 
112
  setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
 
113
  SOCKET_ERR(ret,"setsockopt bindtodevice");
 
114
 
 
115
  memset(&to,0,sizeof(to));
 
116
  to.sin6_family = from.sin6_family;
 
117
  to.sin6_port   = from.sin6_port;
 
118
  to.sin6_addr   = from.sin6_addr;
 
119
  to.sin6_scope_id   = from.sin6_scope_id;
 
120
 
 
121
  ret = connect(sd,reinterpret_cast<struct sockaddr *>(&to),sizeof(to));
 
122
  SOCKET_ERR(ret,"connect");
 
123
 
 
124
  gnutls_transport_set_ptr (session, reinterpret_cast<gnutls_transport_ptr_t> (sd));
 
125
 
 
126
  ret = gnutls_handshake (session);
 
127
 
 
128
  if (ret < 0)
 
129
    {
 
130
      fprintf (stderr, "*** Handshake failed\n");
 
131
      gnutls_perror (ret);
 
132
      return 1;
 
133
    }
 
134
  printf ("- Handshake was completed\n");
 
135
 
 
136
  //message to be seent
 
137
  gnutls_record_send (session, "The secret message is \"squeamish ossifrage\"\n", 44);
 
138
 
 
139
  //shutdown procedure
 
140
  gnutls_bye (session, GNUTLS_SHUT_RDWR);
 
141
  close(sd);
 
142
  gnutls_deinit (session);
 
143
  gnutls_certificate_free_credentials (x509_cred);
 
144
  gnutls_global_deinit ();
 
145
 
 
146
  close(sd);
 
147
 
 
148
  return 0;
213
149
}