/mandos/trunk

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

« back to all changes in this revision

Viewing changes to client.cpp

  • Committer: Teddy Hogeborn
  • Date: 2008-01-18 21:23:46 UTC
  • mfrom: (2.1.1 Project)
  • Revision ID: teddy@fukt.bsnet.se-20080118212346-qo103d6o8r7xs4za
Merged from Björn.

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
#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"
 
27
 
 
28
gnutls_certificate_credentials_t x509_cred;
 
29
 
 
30
gnutls_session_t
 
31
initgnutls(){
 
32
  gnutls_session_t session;
 
33
 
 
34
#ifdef DEBUG
 
35
  std::cerr << "Initiate certificates\n";
 
36
#endif
 
37
 
 
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 (){
 
55
  int udp_sd, tcp_sd, ret;
 
56
  char buffer[4096];
 
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
 
 
63
  struct termios t_old, t_new;
 
64
  int status = 0;
 
65
 
 
66
  session = initgnutls ();
 
67
 
 
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
  
 
79
  {
 
80
    int flag = 1;
 
81
    ret = setsockopt(udp_sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
 
82
    SOCKET_ERR(ret,"setsockopt broadcast");
 
83
  }
 
84
 
 
85
  ret = setsockopt(udp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
 
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);
 
91
  SOCKET_ERR(ret,"inet_pton");
 
92
  to.sin6_port = htons (PORT);  // Server Port number
 
93
 
 
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
    
 
106
  FD_ZERO(&rfds_orig);
 
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
  
 
120
  for(;;){
 
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;
 
203
  }
 
204
  close(udp_sd);
 
205
 
 
206
 quit:
 
207
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &t_old);
 
208
  return status;
 
209
}