/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-07-19 18:43:24 UTC
  • Revision ID: teddy@fukt.bsnet.se-20080719184324-iwhoa5in75xa0u2u
* mandos-clients.conf ([foo]/dn, [foo]/password, [braxen_client]/dn,
                       [braxen_client]/password): Removed.
  ([foo]/fingerprint, [braxen_client]/fingerprint): New.
  ([foo]/checker): New.
  ([foo]/secfile): New.
  ([braxen_client]/secret): New.

* server.py: New "--debug" option to set debug flag.  Removed "cert",
             "key", "ca", "crl", and "cred" variables.  Added default
             value for "checker" config file setting.  Do not pass
             credentials to IPv6_TCPServer constructor.
  (debug): New global debug flag.  Used by most debugging output code.
  (Client.__init__): Keyword argument "dn" replaced by "fingerprint",
                     "password" renamed to "secret", and "passfile"
                     renamed to "secfile".  New keyword argument
                     "checker". All callers changed.
  (Client.dn): Removed.
  (Client.fingerprint): New.
  (Client.password): Renamed to "secret"; all users changed.
  (Client.passfile): Renamed to "secfile"; all users changed.
  (Client.timeout, Client.interval): Changed to be properties; now
                                     automatically updates the
                                     "_timeout_milliseconds" and
                                     "_interval_milliseconds" values.
  (Client.timeout_milliseconds): Renamed to "_timeout_milliseconds".
  (Client.interval_milliseconds): Renamed to "_interval_milliseconds".
  (Client.check_command): New.
  (Client.start_checker): Use the new "check_command" attribute.
  (peer_certificate, fingerprint): New functions.

  (tcp_handler.handle): Use ClientSession with empty credentials
                        object instead of ServerSession.  Set gnutls
                        priority string.  Do not verify peer.  Use
                        fingerprint instead of DN when searching for
                        clients.  Bug fix: Loop sending data so even large
                        secret data strings are sent.
  (IPv6_TCPServer.credentials): Removed.
  (if_nametoindex): Do not import ctypes since that is now imported
                    globally.

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
 
 
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"
22
31
 
23
32
gnutls_certificate_credentials_t x509_cred;
24
33
 
26
35
initgnutls(){
27
36
  gnutls_session_t session;
28
37
 
 
38
#ifdef DEBUG
 
39
  std::cerr << "Initiate certificates\n";
 
40
#endif
 
41
 
29
42
  gnutls_global_init ();
30
43
 
31
44
  /* X509 stuff */
43
56
 
44
57
 
45
58
int main (){
46
 
  int sd, ret;
47
 
  char buffer[512];
 
59
  int udp_sd, tcp_sd, ret;
 
60
  char buffer[4096];
48
61
  struct sockaddr_in6 to;
49
62
  struct sockaddr_in6 from;
50
63
  gnutls_session_t session;
51
64
  fd_set rfds_orig;
52
65
  struct timeval timeout;
53
66
 
 
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
  
54
74
  session = initgnutls ();
55
75
 
56
 
  sd = socket(PF_INET6, SOCK_DGRAM, 0);
57
 
  SOCKET_ERR(sd,"socket");
58
 
 
 
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
  
59
87
  {
60
88
    int flag = 1;
61
 
    ret = setsockopt(sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
 
89
    ret = setsockopt(udp_sd, SOL_SOCKET, SO_BROADCAST, & flag, sizeof(flag));
62
90
    SOCKET_ERR(ret,"setsockopt broadcast");
63
91
  }
64
92
 
65
 
  setsockopt(sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
 
93
  ret = setsockopt(udp_sd, SOL_SOCKET, SO_BINDTODEVICE, "eth0", 5);
66
94
  SOCKET_ERR(ret,"setsockopt bindtodevice");
67
95
 
68
96
  memset (&to, '\0', sizeof (to));
69
97
  to.sin6_family = AF_INET6;
70
98
  ret = inet_pton(AF_INET6, "ff02::1" , &to.sin6_addr);
71
 
  SOCKET_ERR(ret,"setsockopt bindtodevice");
 
99
  SOCKET_ERR(ret,"inet_pton");
72
100
  to.sin6_port = htons (PORT);  // Server Port number
73
101
 
 
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
    
74
114
  FD_ZERO(&rfds_orig);
75
 
  FD_SET(sd, &rfds_orig);
76
 
 
77
 
  timeout.tv_sec = 10;
78
 
  timeout.tv_usec = 0;
79
 
 
80
 
 
 
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
  
81
124
  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
 
    }
 
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;
99
207
  }
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;
 
208
  close(udp_sd);
 
209
 
 
210
 quit:
 
211
  tcsetattr (STDIN_FILENO, TCSAFLUSH, &t_old);
 
212
  return status;
149
213
}