/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: Björn Påhlsson
  • Date: 2008-01-18 21:18:26 UTC
  • mto: This revision was merged to the branch mainline in revision 6.
  • Revision ID: belorn@legolas-20080118211826-5rbwo54l4bwim5x2
Client:
        [Working version in initrd for booting]
        Added #ifdef DEBUG statements through out the program
        Added support to keep bouth tcp and udp up at the same time
        Catching several more error return codes that was unchecked.
        Starts the Network interface during startup.
        Added support for entering password on console
        Added error handling, like looping until a password has been received.
        Added cleanup handling so console state is always restored
                
removed:
        Old server.cpp [see next version]
        Test certificates

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