/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: Teddy Hogeborn
  • Date: 2008-01-18 22:04:19 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080118220419-z95418owrporioo5
* Makefile (client_debug): New.
* client.cpp (CERT_ROOT): New.

(Tested)

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
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
 
6
#include <unistd.h>             // close, STDIN_FILENO, STDOUT_FILENO
 
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>
 
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
}
 
15
 
 
16
#include <cerrno>               // perror
 
17
#include <cstring>              // memset
 
18
#include <string>               // std::string, std::getline
 
19
#include <iostream>             // cin, cout, cerr
 
20
#include <ostream>              // <<
 
21
 
 
22
#define SOCKET_ERR(err,s) if(err<0) {perror(s); status = 1; goto quit;}
 
23
#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"
 
31
 
 
32
gnutls_certificate_credentials_t x509_cred;
 
33
 
 
34
gnutls_session_t
 
35
initgnutls(){
 
36
  gnutls_session_t session;
 
37
 
 
38
#ifdef DEBUG
 
39
  std::cerr << "Initiate certificates\n";
 
40
#endif
 
41
 
 
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 (){
 
59
  int udp_sd, tcp_sd, ret;
 
60
  char buffer[4096];
 
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
 
 
67
  struct termios t_old, t_new;
 
68
  int status = 0;
 
69
 
 
70
  session = initgnutls ();
 
71
 
 
72
#ifdef DEBUG
 
73
  std::cerr << "Open ipv6 UDP\n";
 
74
#endif
 
75
 
 
76
  udp_sd = socket(PF_INET6, SOCK_DGRAM, 0);
 
77
  SOCKET_ERR(udp_sd,"socket");
 
78
  
 
79
#ifdef DEBUG
 
80
  std::cerr << "Open socket with socket nr: " << udp_sd << '\n';
 
81
#endif
 
82
  
 
83
  {
 
84
    int flag = 1;
 
85
    ret = setsockopt(udp_sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
 
86
    SOCKET_ERR(ret,"setsockopt broadcast");
 
87
  }
 
88
 
 
89
  ret = setsockopt(udp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
 
90
  SOCKET_ERR(ret,"setsockopt bindtodevice");
 
91
 
 
92
  memset (&to, '\0', sizeof (to));
 
93
  to.sin6_family = AF_INET6;
 
94
  ret = inet_pton(AF_INET6, "ff02::1" , &to.sin6_addr);
 
95
  SOCKET_ERR(ret,"inet_pton");
 
96
  to.sin6_port = htons (PORT);  // Server Port number
 
97
 
 
98
  struct ifreq network;
 
99
 
 
100
  strcpy(network.ifr_name, "eth0");
 
101
 
 
102
  ret = ioctl(udp_sd, SIOCGIFFLAGS, &network);
 
103
  SOCKET_ERR(ret,"ioctl SIOCGIFFLAGS");
 
104
 
 
105
  network.ifr_flags |= IFF_UP;
 
106
 
 
107
  ret = ioctl(udp_sd, SIOCSIFFLAGS, &network);
 
108
  SOCKET_ERR(ret,"ioctl SIOCSIFFLAGS");
 
109
    
 
110
  FD_ZERO(&rfds_orig);
 
111
  FD_SET(udp_sd, &rfds_orig);
 
112
  FD_SET(STDIN_FILENO, &rfds_orig);
 
113
 
 
114
 
 
115
  if (tcgetattr (STDIN_FILENO, &t_old) != 0){
 
116
    return 1;
 
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
  
 
124
  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;
 
207
  }
 
208
  close(udp_sd);
 
209
 
 
210
 quit:
 
211
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &t_old);
 
212
  return status;
 
213
}