irods  4.2.8
About: iRODS (the integrated Rule Oriented Data System) is a distributed data-management system for creating data grids, digital libraries, persistent archives, and real-time data systems.
  Fossies Dox: irods-4.2.8.tar.gz  ("unofficial" and yet experimental doxygen-generated source code documentation)  

libssl.cpp
Go to the documentation of this file.
1 // =-=-=-=-=-=-=-
2 // irods includes
3 #include "rodsDef.h"
4 #include "msParam.h"
5 #include "rcConnect.h"
6 #include "sockComm.h"
7 
8 // =-=-=-=-=-=-=-
11 #include "irods_ssl_object.hpp"
12 #include "irods_stacktrace.hpp"
15 
16 // =-=-=-=-=-=-=-
17 // stl includes
18 #include <sstream>
19 #include <string>
20 #include <iostream>
21 
22 // =-=-=-=-=-=-=-
23 // ssl includes
24 #include <openssl/ssl.h>
25 #include <openssl/x509v3.h>
26 #include <openssl/err.h>
27 
28 // =-=-=-=-=-=-=-
29 // work around for SSL Macro version issues
30 #if OPENSSL_VERSION_NUMBER < 0x10100000
31 #define ASN1_STRING_get0_data ASN1_STRING_data
32 #define DH_set0_pqg(dh_, p_, q_, g_) \
33  dh_->p = p_; \
34  dh_->q = q_; \
35  dh_->g = g_;
36 #endif
37 
38 // =-=-=-=-=-=-=-
39 //
40 #define SSL_CIPHER_LIST "ALL:!ADH:!LOW:!EXP:!MD5:@STRENGTH"
41 
42 // =-=-=-=-=-=-=-
43 // key for ssl shared secret property
44 const std::string SHARED_KEY( "ssl_network_plugin_shared_key" );
45 
46 // =-=-=-=-=-=-=-
47 //
48 static void ssl_log_error(
49  const char *msg ) {
50  unsigned long err;
51  char buf[512];
52 
53  while ( ( err = ERR_get_error() ) ) {
54  ERR_error_string_n( err, buf, 512 );
55  rodsLog( LOG_ERROR, "%s. SSL error: %s", msg, buf );
56  }
57 
58 } // ssl_log_error
59 
60 // =-=-=-=-=-=-=-
61 //
63  std::string& _str ) {
64  unsigned long err;
65  char buf[512];
66 
67  while ( ( err = ERR_get_error() ) ) {
68  ERR_error_string_n( err, buf, 512 );
69  _str += " | ";
70  _str += buf;
71  }
72 
73 } //ssl_build_error_string
74 
75 /* This function returns a set of built-in Diffie-Hellman
76  parameters. We could read the parameters from a file instead,
77  but this is a reasonably strong prime. The parameters come from
78  the openssl distribution's 'apps' sub-directory. Comment from
79  the source file is:
80 
81  These are the 2048 bit DH parameters from "Assigned Number for SKIP Protocols"
82  (http://www.skip-vpn.org/spec/numbers.html).
83  See there for how they were generated. */
84 
85 static DH* ssl_get_dh2048() {
86  static unsigned char dh2048_p[] = {
87  0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17, 0x72, 0xA2, 0xBA, 0xD6,
88  0xA9, 0x42, 0xF3, 0x05, 0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
89  0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7, 0x56, 0xA3, 0x14, 0xE9,
90  0x8F, 0x40, 0x55, 0xF3, 0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
91  0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83, 0xBD, 0x65, 0xE9, 0x17,
92  0xD4, 0xA1, 0xD3, 0x50, 0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
93  0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57, 0x92, 0x59, 0xCD, 0xFD,
94  0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
95  0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9, 0xBB, 0xFD, 0x91, 0x5E,
96  0xC7, 0x01, 0xAA, 0xD3, 0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
97  0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88, 0xFD, 0x58,
98  0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
99  0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C, 0x88, 0xB3, 0x1C, 0x7C,
100  0x5B, 0x2D, 0x8E, 0xF6, 0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
101  0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD,
102  0x7C, 0x17, 0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
103  0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18, 0x11, 0x8D, 0x7C,
104  0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
105  0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x50, 0x9B,
106  0x02, 0x46, 0xD3, 0x08, 0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
107  0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2, 0x5E, 0xC3, 0x55,
108  0xE9, 0x32, 0x0B, 0x3B,
109  };
110  static unsigned char dh2048_g[] = {
111  0x02,
112  };
113  auto *dh = DH_new();
114 
115  if ( !dh ) {
116  return NULL;
117  }
118  auto* p = BN_bin2bn( dh2048_p, sizeof( dh2048_p ), NULL );
119  auto* g = BN_bin2bn( dh2048_g, sizeof( dh2048_g ), NULL );
120  if ( !p || !g ) {
121  DH_free( dh );
122  return NULL;
123  }
124  DH_set0_pqg(dh, p, nullptr, g);
125  return dh;
126 
127 } // ssl_get_dh2048
128 
129 // =-=-=-=-=-=-=-
130 //
132  SSL_CTX* ctx,
133  char* file ) {
134  DH* dhparams = 0;
135  BIO* bio = 0;
136 
137  if ( file ) {
138  bio = BIO_new_file( file, "r" );
139  if ( bio ) {
140  dhparams = PEM_read_bio_DHparams( bio, NULL, NULL, NULL );
141  BIO_free( bio );
142  }
143  }
144 
145  if ( dhparams == NULL ) {
146  ssl_log_error( "ssl_load_hd_params: can't load DH parameter file. Falling back to built-ins." );
147  dhparams = ssl_get_dh2048();
148  if ( dhparams == NULL ) {
149  rodsLog( LOG_ERROR, "ssl_load_hd_params: can't load built-in DH params" );
150  return -1;
151  }
152  }
153 
154  if ( SSL_CTX_set_tmp_dh( ctx, dhparams ) < 0 ) {
155  ssl_log_error( "ssl_load_hd_params: couldn't set DH parameters" );
156  return -1;
157  }
158  return 0;
159 }
160 
161 // =-=-=-=-=-=-=-
162 //
164  int ok,
165  X509_STORE_CTX* store ) {
166  char data[256];
167 
168  /* log any verification problems, even if we'll still accept the cert */
169  if ( !ok ) {
170  X509 *cert = X509_STORE_CTX_get_current_cert( store );
171  int depth = X509_STORE_CTX_get_error_depth( store );
172  int err = X509_STORE_CTX_get_error( store );
173 
174  rodsLog( LOG_NOTICE, "ssl_verify_callback: problem with certificate at depth: %i", depth );
175  X509_NAME_oneline( X509_get_issuer_name( cert ), data, 256 );
176  rodsLog( LOG_NOTICE, "ssl_verify_callback: issuer = %s", data );
177  X509_NAME_oneline( X509_get_subject_name( cert ), data, 256 );
178  rodsLog( LOG_NOTICE, "ssl_verify_callback: subject = %s", data );
179  rodsLog( LOG_NOTICE, "ssl_verify_callback: err %i:%s", err,
180  X509_verify_cert_error_string( err ) );
181  }
182 
183  return ok;
184 }
185 
186 
187 // =-=-=-=-=-=-=-
188 //
189 static SSL_CTX* ssl_init_context(
190  char *certfile,
191  char *keyfile ) {
192  static int init_done = 0;
193  SSL_CTX *ctx = 0;
194  char *verify_server = 0;
195 
196  rodsEnv env;
197  int status = getRodsEnv( &env );
198  if ( status < 0 ) {
199  rodsLog(
200  LOG_ERROR,
201  "ssl_init_context - failed in getRodsEnv : %d",
202  status );
203  return NULL;
204 
205  }
206 
207  if ( !init_done ) {
208  SSL_library_init();
209  SSL_load_error_strings();
210  init_done = 1;
211  }
212 
213  ctx = SSL_CTX_new( SSLv23_method() );
214 
215  SSL_CTX_set_options( ctx, SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1 | SSL_OP_SINGLE_DH_USE );
216 
217  /* load our keys and certificates if provided */
218  if ( certfile ) {
219  if ( SSL_CTX_use_certificate_chain_file( ctx, certfile ) != 1 ) {
220  ssl_log_error( "sslInit: couldn't read certificate chain file" );
221  SSL_CTX_free( ctx );
222  return NULL;
223  }
224  else {
225  if ( SSL_CTX_use_PrivateKey_file( ctx, keyfile, SSL_FILETYPE_PEM ) != 1 ) {
226  ssl_log_error( "sslInit: couldn't read key file" );
227  SSL_CTX_free( ctx );
228  return NULL;
229  }
230  }
231  }
232 
233  /* set up CA paths and files here */
234  const char *ca_path = strcmp( env.irodsSSLCACertificatePath, "" ) ? env.irodsSSLCACertificatePath : NULL;
235  const char *ca_file = strcmp( env.irodsSSLCACertificateFile, "" ) ? env.irodsSSLCACertificateFile : NULL;
236  if ( ca_path || ca_file ) {
237  if ( SSL_CTX_load_verify_locations( ctx, ca_file, ca_path ) != 1 ) {
238  ssl_log_error( "sslInit: error loading CA certificate locations" );
239  }
240  }
241  if ( SSL_CTX_set_default_verify_paths( ctx ) != 1 ) {
242  ssl_log_error( "sslInit: error loading default CA certificate locations" );
243  }
244 
245  /* Set up the default certificate verification */
246  /* if "none" is specified, we won't stop the SSL handshake
247  due to certificate error, but will log messages from
248  the verification callback */
249  verify_server = env.irodsSSLVerifyServer;
250  if ( strlen( verify_server ) > 0 && !strcmp( verify_server, "none" ) ) {
251  SSL_CTX_set_verify( ctx, SSL_VERIFY_NONE, ssl_verify_callback );
252  }
253  else {
254  SSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, ssl_verify_callback );
255  }
256  /* default depth is nine ... leave this here in case it needs modification */
257  SSL_CTX_set_verify_depth( ctx, 9 );
258 
259  /* ciphers */
260  if ( SSL_CTX_set_cipher_list( ctx, SSL_CIPHER_LIST ) != 1 ) {
261  ssl_log_error( "sslInit: couldn't set the cipher list (no valid ciphers)" );
262  SSL_CTX_free( ctx );
263  return NULL;
264  }
265 
266  return ctx;
267 
268 } // ssl_init_context
269 
270 // =-=-=-=-=-=-=-
271 //
272 static SSL* ssl_init_socket(
273  SSL_CTX* _ctx,
274  int _socket_handle ) {
275 
276  BIO* bio = BIO_new_socket(
277  _socket_handle,
278  BIO_NOCLOSE );
279  if ( bio == NULL ) {
280  ssl_log_error( "sslInitSocket: BIO allocation error" );
281  return NULL;
282  }
283 
284  SSL* ssl = SSL_new( _ctx );
285  if ( ssl == NULL ) {
286  ssl_log_error( "sslInitSocket: couldn't create a new SSL socket" );
287  BIO_free( bio );
288  return NULL;
289  }
290  SSL_set_bio( ssl, bio, bio );
291 
292  return ssl;
293 
294 } // ssl_init_socket
295 
297  SSL *ssl,
298  const char *peer ) {
299 
300  rodsEnv env;
301  int status = getRodsEnv( &env );
302  if ( status < 0 ) {
303  rodsLog(
304  LOG_ERROR,
305  "ssl_init_context - failed in getRodsEnv : %d",
306  status );
307  return 0;
308 
309  }
310 
311  char *verify_server = env.irodsSSLVerifyServer;
312  if ( strlen( verify_server ) > 0 && strcmp( verify_server, "hostname" ) ) {
313  /* not being asked to verify that the peer hostname
314  is in the certificate. */
315  return 1;
316  }
317 
318  X509 *cert = SSL_get_peer_certificate( ssl );
319  if ( cert == NULL ) {
320  /* no certificate presented */
321  return 0;
322  }
323 
324  if ( peer == NULL ) {
325  /* no hostname passed to verify */
326  X509_free( cert );
327  return 0;
328  }
329 
330  /* check if the peer name matches any of the subjectAltNames
331  listed in the certificate */
332  bool match = false;
333  auto* names = static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i( cert, NID_subject_alt_name, NULL, NULL ));
334  int num_names = sk_GENERAL_NAME_num( names );
335  for ( int i = 0; i < num_names; i++ ) {
336  auto* name = sk_GENERAL_NAME_value( names, i );
337  if ( name && name->type == GEN_DNS ) {
338  if ( !strcasecmp( reinterpret_cast<const char*>(ASN1_STRING_get0_data( name->d.dNSName )), peer ) ) {
339  match = true;
340  break;
341  }
342  }
343  }
344  sk_GENERAL_NAME_free( names );
345 
346  /* if no match above, check the common name in the certificate */
347  char name_text[256];
348  if ( !match &&
349  ( X509_NAME_get_text_by_NID( X509_get_subject_name( cert ),
350  NID_commonName, name_text, sizeof( name_text ) ) != -1 ) ) {
351  if ( !strcasecmp( name_text, peer ) ) {
352  match = true;
353  }
354  else if ( name_text[0] == '*' ) { /* wildcard domain */
355  const char *tmp = strchr( peer, '.' );
356  if ( tmp && !strcasecmp( tmp, name_text + 1 ) ) {
357  match = true;
358  }
359  }
360  }
361 
362  X509_free( cert );
363 
364  if ( match ) {
365  return 1;
366  }
367  else {
368  return 0;
369  }
370 
371 } // ssl_post_connection_check
372 
373 // =-=-=-=-=-=-=-
374 // local function to read a buffer from a socket
376  int _socket,
377  void* _buffer,
378  int _length,
379  int& _bytes_read,
380  struct timeval* _time_value,
381  SSL* _ssl ) {
382  irods::error result = SUCCESS();
383 
384  // =-=-=-=-=-=-=-
385  // check incoming pointers
386  if ( ( result = ASSERT_ERROR( _buffer && _ssl, SYS_INVALID_INPUT_PARAM, "Null buffer or ssl pointer." ) ).ok() ) {
387 
388  // =-=-=-=-=-=-=-
389  // Initialize the file descriptor set
390  fd_set set;
391  FD_ZERO( &set );
392  FD_SET( _socket, &set );
393 
394  // =-=-=-=-=-=-=-
395  // local copy of time value?
396  struct timeval timeout;
397  if ( _time_value != NULL ) {
398  timeout = ( *_time_value );
399  }
400 
401  // =-=-=-=-=-=-=-
402  // local working variables
403  int len_to_read = _length;
404  char* read_ptr = static_cast<char*>( _buffer );
405 
406  // =-=-=-=-=-=-=-
407  // reset bytes read
408  _bytes_read = 0;
409 
410  // =-=-=-=-=-=-=-
411  // loop while there is data to read
412  while ( result.ok() && len_to_read > 0 ) {
413 
414  // =-=-=-=-=-=-=-
415  // do a time out managed select of the socket fd
416  if ( SSL_pending( _ssl ) == 0 && NULL != _time_value ) {
417  int status = select( _socket + 1, &set, NULL, NULL, &timeout );
418  if ( status == 0 ) {
419  // =-=-=-=-=-=-=-
420  // the select has timed out
421  if ( ( _length - len_to_read ) > 0 ) {
422  result = ERROR( _length - len_to_read, "failed to read requested number of bytes" );
423  }
424  else {
425  result = ERROR( SYS_SOCK_READ_TIMEDOUT, "socket timeout error" );
426  }
427 
428  }
429  else if ( status < 0 ) {
430 
431  // =-=-=-=-=-=-=-
432  // keep trying on interrupt or just error out
433  int err_status = SYS_SOCK_READ_ERR - errno;
434  result = ASSERT_ERROR( errno != EINTR, err_status, "Error on select." );
435 
436  } // else
437 
438  } // if tv
439 
440  // =-=-=-=-=-=-=-
441  // select has been done, finally do the read
442  int num_bytes = SSL_read( _ssl, ( void * ) read_ptr, len_to_read );
443 
444  // =-=-=-=-=-=-=-
445  // error trapping the read
446  if ( SSL_get_error( _ssl, num_bytes ) != SSL_ERROR_NONE ) {
447  // =-=-=-=-=-=-=-
448  // gracefully handle an interrupt
449  if ( EINTR == errno ) {
450  errno = 0;
451  num_bytes = 0;
452  }
453  else {
454  result = ERROR( _length - len_to_read, "Failed to in SSL read." );
455  }
456  }
457 
458  // =-=-=-=-=-=-=-
459  // all has gone well, do byte book keeping
460  len_to_read -= num_bytes;
461  read_ptr += num_bytes;
462  _bytes_read += num_bytes;
463 
464 
465  } // while
466 
467  } // if assert_error
468 
469  // =-=-=-=-=-=-=-
470  // and were done? report length not read
471  // return CODE( _length - len_to_read );
472  return result;
473 
474 } // ssl_socket_read
475 
476 // =-=-=-=-=-=-=-
477 // local function to write a buffer to a socket
479  void* _buffer,
480  int _length,
481  int& _bytes_written,
482  SSL* _ssl ) {
483  irods::error result = SUCCESS();
484 
485  // =-=-=-=-=-=-=-
486  // check incoming pointers
487  if ( ( result = ASSERT_ERROR( _buffer && _ssl, SYS_INVALID_INPUT_PARAM, "Buffer or ssl pointer are null." ) ).ok() ) {
488 
489  // =-=-=-=-=-=-=-
490  // local variables for write
491  int len_to_write = _length;
492  char* write_ptr = static_cast<char*>( _buffer );
493 
494  // =-=-=-=-=-=-=-
495  // reset bytes written
496  _bytes_written = 0;
497 
498  // =-=-=-=-=-=-=-
499  // loop while there is data to read
500  while ( result.ok() && len_to_write > 0 ) {
501  int num_bytes = SSL_write( _ssl, static_cast<void*>( write_ptr ), len_to_write );
502 
503  // =-=-=-=-=-=-=-
504  // error trapping the write
505  if ( SSL_get_error( _ssl, num_bytes ) != SSL_ERROR_NONE ) {
506  // =-=-=-=-=-=-=-
507  // gracefully handle an interrupt
508  if ( errno == EINTR ) {
509  errno = 0;
510  num_bytes = 0;
511 
512  }
513  else {
514  result = ERROR( _length - len_to_write, "Failed to write to SSL" );
515  }
516  }
517 
518  // =-=-=-=-=-=-=-
519  // increment working variables
520  len_to_write -= num_bytes;
521  write_ptr += num_bytes;
522  _bytes_written += num_bytes;
523 
524  }
525  }
526 
527  // =-=-=-=-=-=-=-
528  // and were done? report length not written
529  // return CODE( _length - len_to_write );
530  return result;
531 
532 } // ssl_socket_write
533 
534 // =-=-=-=-=-=-=-
535 //
537  irods::plugin_context& _ctx,
538  void* _buffer,
539  struct timeval* _time_val ) {
540  irods::error result = SUCCESS();
541 
542  // =-=-=-=-=-=-=-
543  // check the context
544  irods::error ret = _ctx.valid< irods::ssl_object >();
545  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
546 
547  // =-=-=-=-=-=-=-
548  // extract the useful bits from the context
549  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
550  int socket_handle = ssl_obj->socket_handle();
551 
552  // =-=-=-=-=-=-=-
553  // read the header length packet */
554  int header_length = 0;
555  int bytes_read = 0;
556  ret = ssl_socket_read( socket_handle, static_cast<void*>( &header_length ), sizeof( int ), bytes_read,
557  _time_val, ssl_obj->ssl() );
558  if ( !ret.ok() || bytes_read != sizeof( header_length ) ) {
559 
560  int status = 0;
561  if ( bytes_read < 0 ) {
562  status = bytes_read - errno;
563  }
564  else {
566  }
567  std::stringstream msg;
568  msg << "read "
569  << bytes_read
570  << " expected " << sizeof( header_length );
571  return ERROR( status, msg.str() );
572  }
573 
574  // =-=-=-=-=-=-=-
575  // convert from network to host byte order
576  header_length = ntohl( header_length );
577 
578  // =-=-=-=-=-=-=-
579  // check head length against expected size range
580  if ( ( result = ASSERT_ERROR( header_length <= MAX_NAME_LEN && header_length > 0, SYS_HEADER_READ_LEN_ERR,
581  "Header length is out of range: %d expected >= 0 and < %d.", header_length, MAX_NAME_LEN ) ).ok() ) {
582 
583  // =-=-=-=-=-=-=-
584  // now read the actual header
585  ret = ssl_socket_read( socket_handle, _buffer, header_length, bytes_read, _time_val, ssl_obj->ssl() );
586  if ( !ret.ok() ||
587  bytes_read != header_length ) {
588  int status = 0;
589  if ( bytes_read < 0 ) {
590  status = bytes_read - errno;
591  }
592  else {
594  }
595  std::stringstream msg;
596  msg << "read "
597  << bytes_read
598  << " expected " << header_length;
599  return ERROR( status, msg.str() );
600 
601  }
602 
603  // =-=-=-=-=-=-=-
604  // log debug information if appropriate
605  if ( getRodsLogLevel() >= LOG_DEBUG8 ) {
606  printf( "received header: len = %d\n%s\n",
607  header_length,
608  static_cast<char*>( _buffer ) );
609  }
610  }
611  }
612 
613  return result;
614 
615 } // ssl_read_msg_header
616 
617 // =-=-=-=-=-=-=-
618 //
620  irods::plugin_context& _ctx,
621  rodsEnv* _env ) {
622  irods::error result = SUCCESS();
623 
624  // =-=-=-=-=-=-=-
625  // check the context
626  irods::error ret = _ctx.valid< irods::ssl_object >();
627  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
628 
629  // =-=-=-=-=-=-=-
630  // extract the useful bits from the context
631  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
632  SSL* ssl = ssl_obj->ssl();
633  SSL_CTX* ctx = ssl_obj->ssl_ctx();
634 
635  /* shut down the SSL connection. First SSL_shutdown() sends "close notify" */
636  int status = SSL_shutdown( ssl );
637  if ( status == 0 ) {
638  /* do second phase of shutdown */
639  status = SSL_shutdown( ssl );
640  }
641 
642  std::string err_str = "error shutting down the SSL connection";
643  ssl_build_error_string( err_str );
644  if ( ( result = ASSERT_ERROR( status == 1, SSL_SHUTDOWN_ERROR, err_str.c_str() ) ).ok() ) {
645 
646  /* clean up the SSL state */
647  SSL_free( ssl );
648  SSL_CTX_free( ctx );
649 
650  ssl_obj->ssl( 0 );
651  ssl_obj->ssl_ctx( 0 );
652  }
653  }
654 
655  return result;
656 
657 } // ssl_client_stop
658 
659 // =-=-=-=-=-=-=-
660 //
662  irods::plugin_context& _ctx,
663  rodsEnv* _env ) {
664  irods::error result = SUCCESS();
665 
666  // =-=-=-=-=-=-=-
667  // check the context
668  irods::error ret = _ctx.valid< irods::ssl_object >();
669  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
670 
671  // =-=-=-=-=-=-=-
672  // extract the useful bits from the context
673  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
674 
675  // =-=-=-=-=-=-=-
676  // set up SSL on our side of the socket
677  SSL_CTX* ctx = ssl_init_context( NULL, NULL );
678  std::string err_str = "failed to initialize SSL context";
679  ssl_build_error_string( err_str );
680  if ( ( result = ASSERT_ERROR( ctx, SSL_INIT_ERROR, err_str.c_str() ) ).ok() ) {
681  SSL* ssl = ssl_init_socket( ctx, ssl_obj->socket_handle() );
682  std::string err_str = "couldn't initialize SSL socket";
683  ssl_build_error_string( err_str );
684  if ( !( result = ASSERT_ERROR( ssl, SSL_INIT_ERROR, err_str.c_str() ) ).ok() ) {
685  SSL_CTX_free( ctx );
686  }
687  else {
688  int status = SSL_connect( ssl );
689  std::string err_str = "error in SSL_connect";
690  ssl_build_error_string( err_str );
691  if ( !( result = ASSERT_ERROR( status >= 1, SSL_HANDSHAKE_ERROR, err_str.c_str() ) ).ok() ) {
692  SSL_free( ssl );
693  SSL_CTX_free( ctx );
694  }
695  else {
696  ssl_obj->ssl( ssl );
697  ssl_obj->ssl_ctx( ctx );
698 
699  int status = ssl_post_connection_check( ssl, ssl_obj->host().c_str() );
700 
701  std::string err_str = "post connection certificate check failed";
702  ssl_build_error_string( err_str );
703  if ( !( result = ASSERT_ERROR( status, SSL_CERT_ERROR, err_str.c_str() ) ).ok() ) {
704  ssl_client_stop( _ctx, _env );
705  }
706  else {
707  // =-=-=-=-=-=-=-
708  // check to see if a key has already been placed
709  // in the property map
711  ret = _ctx.prop_map().get< irods::buffer_crypt::array_t >( SHARED_KEY, key );
712  if ( !ret.ok() ) {
713  // =-=-=-=-=-=-=-
714  // if no key exists then ship a new key and set the
715  // property
717  if ( !ret.ok() ) {
718  irods::log( PASS( ret ) );
719  }
720 
721  ret = _ctx.prop_map().set< irods::buffer_crypt::array_t >( SHARED_KEY, key );
722  if ( !ret.ok() ) {
723  irods::log( PASS( ret ) );
724  }
725  }
726 
727  if ( ( result = ASSERT_ERROR( _ctx.prop_map().has_entry( SHARED_KEY ),
728  -1, "irodsEncryption error. Failed to generate key." ) ).ok() ) {
729  // =-=-=-=-=-=-=-
730  // send a message to the agent containing the client
731  // size encryption environment variables
732  msgHeader_t msg_header;
733  memset( &msg_header, 0, sizeof( msg_header ) );
734  memcpy( msg_header.type, _env->rodsEncryptionAlgorithm, HEADER_TYPE_LEN );
735  msg_header.msgLen = _env->rodsEncryptionKeySize;
736  msg_header.errorLen = _env->rodsEncryptionSaltSize;
737  msg_header.bsLen = _env->rodsEncryptionNumHashRounds;
738 
739  // =-=-=-=-=-=-=-
740  // error check the encryption envrionment
741  if ( ( result = ASSERT_ERROR( 0 != msg_header.msgLen && 0 != msg_header.errorLen && 0 != msg_header.bsLen,
742  -1, "irodsEncryption error. Key size, salt size or num hash rounds is 0." ) ).ok() ) {
743 
744  if ( ( result = ASSERT_ERROR( EVP_get_cipherbyname( msg_header.type ), -1, "irods_encryption_algorithm \"%s\" is invalid.",
745  msg_header.type ) ).ok() ) {
746 
747  // =-=-=-=-=-=-=-
748  // use a message header to contain the encryption environment
749  ret = writeMsgHeader( ssl_obj, &msg_header );
750  if ( ( result = ASSERT_PASS( ret, "writeMsgHeader failed." ) ).ok() ) {
751 
752  // =-=-=-=-=-=-=-
753  // send a message to the agent containing the shared secret
754  bytesBuf_t key_bbuf;
755  key_bbuf.len = key.size();
756  key_bbuf.buf = &key[0];
757  char msg_type[] = { "SHARED_SECRET" };
758  ret = sendRodsMsg( ssl_obj, msg_type, &key_bbuf, 0, 0, 0, XML_PROT );
759  if ( ( result = ASSERT_PASS( ret, "writeMsgHeader failed." ) ).ok() ) {
760 
761  // =-=-=-=-=-=-=-
762  // set the key and env for this ssl object
763  ssl_obj->shared_secret( key );
764  ssl_obj->key_size( _env->rodsEncryptionKeySize );
765  ssl_obj->salt_size( _env->rodsEncryptionSaltSize );
766  ssl_obj->num_hash_rounds( _env->rodsEncryptionNumHashRounds );
767  ssl_obj->encryption_algorithm( _env->rodsEncryptionAlgorithm );
768  }
769  }
770  }
771  }
772  }
773  }
774  }
775  }
776  }
777  }
778 
779  return result;
780 
781 } // ssl_client_start
782 
783 // =-=-=-=-=-=-=-
784 //
786  irods::plugin_context& _ctx ) {
787  irods::error result = SUCCESS();
788  rodsEnv env;
789  int status = getRodsEnv( &env );
790  if ( status < 0 ) {
791  rodsLog(
792  LOG_ERROR,
793  "ssl_init_context - failed in getRodsEnv : %d",
794  status );
795  return ERROR(
796  status,
797  "failed in getRodsEnv" );
798 
799  }
800 
801  // =-=-=-=-=-=-=-
802  // check the context
803  irods::error ret = _ctx.valid< irods::ssl_object >();
804  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
805 
806  // =-=-=-=-=-=-=-
807  // extract the useful bits from the context
808  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
809 
810  // =-=-=-=-=-=-=-
811  // set up the context using a certificate file and separate
812  // keyfile passed through environment variables
813  SSL_CTX* ctx = ssl_init_context( env.irodsSSLCertificateChainFile,
814  env.irodsSSLCertificateKeyFile );
815  std::string err_str = "couldn't initialize SSL context";
816  ssl_build_error_string( err_str );
817  if ( ( result = ASSERT_ERROR( ctx, SSL_INIT_ERROR, err_str.c_str() ) ).ok() ) {
818 
819  int status = ssl_load_hd_params( ctx, env.irodsSSLDHParamsFile );
820  std::string err_str = "error setting Diffie-Hellman parameters";
821  ssl_build_error_string( err_str );
822  if ( !( result = ASSERT_ERROR( status >= 0, SSL_INIT_ERROR, err_str.c_str() ) ).ok() ) {
823  SSL_CTX_free( ctx );
824  }
825  else {
826 
827  SSL* ssl = ssl_init_socket( ctx, ssl_obj->socket_handle() );
828  std::string err_str = "couldn't initialize SSL socket";
829  ssl_build_error_string( err_str );
830  if ( !( result = ASSERT_ERROR( ssl, SSL_INIT_ERROR, err_str.c_str() ) ).ok() ) {
831  SSL_CTX_free( ctx );
832  }
833  else {
834 
835  status = SSL_accept( ssl );
836  std::string err_str = "error calling SSL_accept";
837  ssl_build_error_string( err_str );
838  if ( ( result = ASSERT_ERROR( status >= 1, SSL_HANDSHAKE_ERROR, err_str.c_str() ) ).ok() ) {
839 
840  ssl_obj->ssl( ssl );
841  ssl_obj->ssl_ctx( ctx );
842 
843  rodsLog( LOG_DEBUG, "sslAccept: accepted SSL connection" );
844 
845  // =-=-=-=-=-=-=-
846  // message header variables
847  struct timeval tv;
848  tv.tv_sec = READ_VERSION_TOUT_SEC;
849  tv.tv_usec = 0;
850  msgHeader_t msg_header;
851 
852  // =-=-=-=-=-=-=-
853  // wait for a message header containing the encryption environment
854  bzero( &msg_header, sizeof( msg_header ) );
855  ret = readMsgHeader( ssl_obj, &msg_header, &tv );
856  if ( ( result = ASSERT_PASS( ret, "Read message header failed." ) ).ok() ) {
857 
858  // =-=-=-=-=-=-=-
859  // set encryption parameters
860  ssl_obj->key_size( msg_header.msgLen );
861  ssl_obj->salt_size( msg_header.errorLen );
862  ssl_obj->num_hash_rounds( msg_header.bsLen );
863  ssl_obj->encryption_algorithm( msg_header.type );
864 
865  // =-=-=-=-=-=-=-
866  // wait for a message header containing a shared secret
867  bzero( &msg_header, sizeof( msg_header ) );
868  ret = readMsgHeader( ssl_obj, &msg_header, &tv );
869  if ( ( result = ASSERT_PASS( ret, "Read message header failed." ) ).ok() ) {
870 
871  // =-=-=-=-=-=-=-
872  // call interface to read message body
873  bytesBuf_t msg_buf;
874  ret = readMsgBody( ssl_obj, &msg_header, &msg_buf, 0, 0, XML_PROT, NULL );
875  if ( ( result = ASSERT_PASS( ret, "Read message body failed." ) ).ok() ) {
876 
877  // =-=-=-=-=-=-=-
878  // we cannot check to see if the key property has been set,
879  // as the resource servers connect to the icat and init the
880  // the key first, so we need to repave it with the client
881  // connection. leaving this here for debugging if necessary
882  //std::string key;
883  //ret = _ctx.prop_map().get< std::string >( SHARED_KEY, key );
884  //if( ret.ok() ) {
885  // std::stringstream msg;
886  // return ERROR( -1, "shared secret already exists" );
887  //}
888 
889  // =-=-=-=-=-=-=-
890  // set the incoming shared secret
891  unsigned char* secret_ptr = static_cast< unsigned char* >( msg_buf.buf );
893  key.assign(
894  secret_ptr,
895  &secret_ptr[ msg_buf.len ] );
896 
897  ssl_obj->shared_secret( key );
898  ret = _ctx.prop_map().set< irods::buffer_crypt::array_t >( SHARED_KEY, key );
899  result = ASSERT_PASS( ret, "Shared key property not found." );
900  }
901  }
902  }
903  }
904  }
905  }
906  }
907  }
908 
909  return result;
910 
911 } // ssl_agent_start
912 
913 // =-=-=-=-=-=-=-
914 //
916  irods::plugin_context& _ctx ) {
917  irods::error result = SUCCESS();
918 
919  // =-=-=-=-=-=-=-
920  // check the context
921  irods::error ret = _ctx.valid< irods::ssl_object >();
922  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
923 
924  // =-=-=-=-=-=-=-
925  // extract the useful bits from the context
926  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
927  SSL* ssl = ssl_obj->ssl();
928  SSL_CTX* ctx = ssl_obj->ssl_ctx();
929 
930  // =-=-=-=-=-=-=-
931  // shut down the SSL connection. Might need to call SSL_shutdown()
932  // twice to allow the protocol to notify and then complete
933  // the shutdown.
934  int status = SSL_shutdown( ssl_obj->ssl() );
935  if ( status == 0 ) {
936  // =-=-=-=-=-=-=-
937  // second phase of shutdown
938  status = SSL_shutdown( ssl_obj->ssl() );
939  }
940  std::string err_str = "error completing shutdown of SSL connection";
941  ssl_build_error_string( err_str );
942  if ( ( result = ASSERT_ERROR( status == 1, SSL_SHUTDOWN_ERROR, err_str.c_str() ) ).ok() ) {
943 
944  // =-=-=-=-=-=-=-
945  // clean up the SSL state
946  SSL_free( ssl );
947  SSL_CTX_free( ctx );
948  ssl_obj->ssl( 0 );
949  ssl_obj->ssl_ctx( 0 );
950 
951  rodsLog( LOG_DEBUG, "sslShutdown: shut down SSL connection" );
952  }
953  }
954 
955  return result;
956 
957 } // ssl_agent_stop
958 
959 // =-=-=-=-=-=-=-
960 //
962  irods::plugin_context& _ctx,
963  bytesBuf_t* _header ) {
964  irods::error result = SUCCESS();
965 
966  // =-=-=-=-=-=-=-
967  // check the context
968  irods::error ret = _ctx.valid< irods::ssl_object >();
969  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
970 
971  // =-=-=-=-=-=-=-
972  // log debug information if appropriate
973  if ( getRodsLogLevel() >= LOG_DEBUG8 ) {
974  printf( "sending header: len = %d\n%s\n", _header->len, ( char * ) _header->buf );
975  }
976 
977  // =-=-=-=-=-=-=-
978  // extract the useful bits from the context
979  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
980 
981  // =-=-=-=-=-=-=-
982  // convert host byte order to network byte order
983  int header_length = htonl( _header->len );
984 
985  // =-=-=-=-=-=-=-
986  // write the length of the header to the socket
987  int bytes_written = 0;
988  ret = ssl_socket_write( &header_length, sizeof( header_length ), bytes_written, ssl_obj->ssl() );
989  int status = SYS_HEADER_WRITE_LEN_ERR - errno;
990  if ( ( result = ASSERT_ERROR( ret.ok() && bytes_written == sizeof( header_length ), status, "Wrote %d expected %d.",
991  bytes_written, header_length ) ).ok() ) {
992 
993  // =-=-=-=-=-=-=-
994  // now send the actual header
995  ret = ssl_socket_write( _header->buf, _header->len, bytes_written, ssl_obj->ssl() );
997  result = ASSERT_ERROR( ret.ok() && bytes_written == _header->len, status, "Wrote %d expected %d.",
998  bytes_written, _header->len );
999  }
1000  }
1001 
1002  return result;
1003 
1004 } // ssl_write_msg_header
1005 
1006 // =-=-=-=-=-=-=-
1007 //
1009  irods::plugin_context& _ctx,
1010  const char* _msg_type,
1011  bytesBuf_t* _msg_buf,
1012  bytesBuf_t* _stream_bbuf,
1013  bytesBuf_t* _error_buf,
1014  int _int_info,
1015  irodsProt_t _protocol ) {
1016  irods::error result = SUCCESS();
1017 
1018  // =-=-=-=-=-=-=-
1019  // check the context
1020  irods::error ret = _ctx.valid< irods::ssl_object >();
1021  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
1022 
1023  // =-=-=-=-=-=-=-
1024  // check the params
1025  if ( ( result = ASSERT_ERROR( _msg_type, SYS_INVALID_INPUT_PARAM, "Null msg type." ) ).ok() ) {
1026 
1027  // =-=-=-=-=-=-=-
1028  // extract the useful bits from the context
1029  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
1030 
1031  // =-=-=-=-=-=-=-
1032  // initialize a new header
1033  msgHeader_t msg_header;
1034  memset( &msg_header, 0, sizeof( msg_header ) );
1035 
1036  snprintf( msg_header.type, HEADER_TYPE_LEN, "%s", _msg_type );
1037  msg_header.intInfo = _int_info;
1038 
1039  // =-=-=-=-=-=-=-
1040  // initialize buffer lengths
1041  if ( _msg_buf ) {
1042  msg_header.msgLen = _msg_buf->len;
1043  }
1044  if ( _stream_bbuf ) {
1045  msg_header.bsLen = _stream_bbuf->len;
1046  }
1047  if ( _error_buf ) {
1048  msg_header.errorLen = _error_buf->len;
1049  }
1050 
1051  // =-=-=-=-=-=-=-
1052  // send the header
1053  irods::network_object_ptr net_obj = boost::dynamic_pointer_cast< irods::network_object >( _ctx.fco() );
1054  ret = writeMsgHeader( net_obj, &msg_header );
1055  if ( ( result = ASSERT_PASS( ret, "Write message header failed." ) ).ok() ) {
1056 
1057  // =-=-=-=-=-=-=-
1058  // send the message buffer
1059  int bytes_written = 0;
1060  if ( NULL != _msg_buf &&
1061  msg_header.msgLen > 0 ) {
1062  if ( XML_PROT == _protocol &&
1063  getRodsLogLevel() >= LOG_DEBUG8 ) {
1064  printf( "sending msg: \n%s\n", ( char* ) _msg_buf->buf );
1065  }
1066  ret = ssl_socket_write( _msg_buf->buf, _msg_buf->len, bytes_written, ssl_obj->ssl() );
1067  result = ASSERT_PASS( ret, "Failed writing SSL message to socket." );
1068  } // if msgLen > 0
1069 
1070  if ( result.ok() ) {
1071 
1072  // =-=-=-=-=-=-=-
1073  // send the error buffer
1074  if ( NULL != _error_buf &&
1075  msg_header.errorLen > 0 ) {
1076  if ( XML_PROT == _protocol &&
1077  getRodsLogLevel() >= LOG_DEBUG8 ) {
1078  printf( "sending msg: \n%s\n", ( char* ) _error_buf->buf );
1079 
1080  }
1081 
1082  ret = ssl_socket_write( _error_buf->buf, _error_buf->len, bytes_written, ssl_obj->ssl() );
1083  result = ASSERT_PASS( ret, "Failed writing SSL message to socket." );
1084  } // if errorLen > 0
1085 
1086  if ( result.ok() ) {
1087 
1088  // =-=-=-=-=-=-=-
1089  // send the stream buffer
1090  if ( NULL != _stream_bbuf &&
1091  msg_header.bsLen > 0 ) {
1092  if ( XML_PROT == _protocol &&
1093  getRodsLogLevel() >= LOG_DEBUG8 ) {
1094  printf( "sending msg: \n%s\n", ( char* ) _stream_bbuf->buf );
1095  }
1096 
1097  ret = ssl_socket_write( _stream_bbuf->buf, _stream_bbuf->len, bytes_written, ssl_obj->ssl() );
1098  result = ASSERT_PASS( ret, "Failed writing SSL message to socket." );
1099 
1100  } // if bsLen > 0
1101  }
1102  }
1103  }
1104  }
1105  }
1106 
1107  return result;
1108 
1109 } // ssl_send_rods_msg
1110 
1111 // =-=-=-=-=-=-=-
1112 // helper fcn to read a bytes buf
1114  int _socket_handle,
1115  int _length,
1116  bytesBuf_t* _buffer,
1117  irodsProt_t _protocol,
1118  struct timeval* _time_val,
1119  SSL* _ssl ) {
1120  irods::error result = SUCCESS();
1121 
1122  // =-=-=-=-=-=-=-
1123  // trap input buffer ptr
1124  if ( ( result = ASSERT_ERROR( _buffer, SYS_READ_MSG_BODY_INPUT_ERR, "Null buffer pointer." ) ).ok() ) {
1125 
1126  // =-=-=-=-=-=-=-
1127  // read buffer
1128  int bytes_read = 0;
1129  irods::error ret = ssl_socket_read( _socket_handle, _buffer->buf, _length, bytes_read, _time_val, _ssl );
1130  _buffer->len = bytes_read;
1131 
1132  // =-=-=-=-=-=-=-
1133  // log transaction if requested
1134  if ( _protocol == XML_PROT &&
1135  getRodsLogLevel() >= LOG_DEBUG8 ) {
1136  printf( "received msg: \n%s\n",
1137  ( char* ) _buffer->buf );
1138  }
1139 
1140  // =-=-=-=-=-=-=-
1141  // trap failed read
1142  if ( !( result = ASSERT_ERROR( ret.ok() && bytes_read == _length, SYS_READ_MSG_BODY_LEN_ERR,
1143  "Read %d expected %d.", bytes_read, _length ) ).ok() ) {
1144  free( _buffer->buf );
1145  }
1146  }
1147 
1148  return result;
1149 
1150 } // read_bytes_buf
1151 
1152 // =-=-=-=-=-=-=-
1153 // read a message body off of the socket
1155  irods::plugin_context& _ctx,
1156  msgHeader_t* _header,
1157  bytesBuf_t* _input_struct_buf,
1158  bytesBuf_t* _bs_buf,
1159  bytesBuf_t* _error_buf,
1160  irodsProt_t _protocol,
1161  struct timeval* _time_val ) {
1162  irods::error result = SUCCESS();
1163 
1164  // =-=-=-=-=-=-=-
1165  // check the context
1166  irods::error ret = _ctx.valid< irods::ssl_object >();
1167  if ( ( result = ASSERT_PASS( ret, "Invalid SSL plugin context." ) ).ok() ) {
1168 
1169  // =-=-=-=-=-=-=-
1170  // extract the useful bits from the context
1171  irods::ssl_object_ptr ssl_obj = boost::dynamic_pointer_cast< irods::ssl_object >( _ctx.fco() );
1172  int socket_handle = ssl_obj->socket_handle();
1173 
1174  // =-=-=-=-=-=-=-
1175  // trap header ptr
1176  if ( ( result = ASSERT_ERROR( _header, SYS_READ_MSG_BODY_INPUT_ERR, "Null header pointer." ) ).ok() ) {
1177 
1178  // =-=-=-=-=-=-=-
1179  // reset error buf - assumed by the client code
1180  // NOTE :: do not reset bs buf as it can be reused
1181  // on the client side
1182  if ( _error_buf ) {
1183  memset( _error_buf, 0, sizeof( bytesBuf_t ) );
1184  }
1185 
1186  // =-=-=-=-=-=-=-
1187  // read input buffer
1188  if ( 0 != _input_struct_buf ) {
1189  if ( _header->msgLen > 0 ) {
1190  _input_struct_buf->buf = malloc( _header->msgLen + 1 );
1191  ret = read_bytes_buf( socket_handle, _header->msgLen, _input_struct_buf, _protocol, _time_val, ssl_obj->ssl() );
1192  result = ASSERT_PASS( ret, "Failed reading from SSL buffer." );
1193 
1194  }
1195  else {
1196  // =-=-=-=-=-=-=-
1197  // ensure msg len is 0 as this can cause issues
1198  // in the agent
1199  _input_struct_buf->len = 0;
1200 
1201  }
1202 
1203  } // input buffer
1204 
1205  if ( result.ok() ) {
1206 
1207  // =-=-=-=-=-=-=-
1208  // read error buffer
1209  if ( 0 != _error_buf ) {
1210  if ( _header->errorLen > 0 ) {
1211  _error_buf->buf = malloc( _header->errorLen + 1 );
1212  ret = read_bytes_buf( socket_handle, _header->errorLen, _error_buf, _protocol, _time_val, ssl_obj->ssl() );
1213  result = ASSERT_PASS( ret, "Failed reading from SSL buffer." );
1214 
1215  }
1216  else {
1217  _error_buf->len = 0;
1218 
1219  }
1220 
1221  } // error buffer
1222 
1223  if ( result.ok() ) {
1224 
1225  // =-=-=-=-=-=-=-
1226  // read bs buffer
1227  if ( 0 != _bs_buf ) {
1228  if ( _header->bsLen > 0 ) {
1229  // do not repave bs buf as it can be
1230  // reused by the client
1231  if ( _bs_buf->buf == NULL ) {
1232  _bs_buf->buf = malloc( _header->bsLen + 1 );
1233 
1234  }
1235  else if ( _header->bsLen > _bs_buf->len ) {
1236  free( _bs_buf->buf );
1237  _bs_buf->buf = malloc( _header->bsLen + 1 );
1238 
1239  }
1240 
1241  ret = read_bytes_buf( socket_handle, _header->bsLen, _bs_buf, _protocol, _time_val, ssl_obj->ssl() );
1242  result = ASSERT_PASS( ret, "Failed reading from SSL buffer." );
1243  }
1244  else {
1245  _bs_buf->len = 0;
1246 
1247  }
1248 
1249  } // bs buffer
1250  }
1251  }
1252  }
1253  }
1254 
1255  return result;
1256 
1257 } // ssl_read_msg_body
1258 
1259 // =-=-=-=-=-=-=-
1260 // stub for ops that the ssl plug does
1261 // not need to support - accept etc
1264  return SUCCESS();
1265 
1266 } // ssl_success_stub
1267 
1268 
1269 // =-=-=-=-=-=-=-
1270 // derive a new ssl network plugin from
1271 // the network plugin base class for handling
1272 // ssl communications
1274  public:
1276  const std::string& _nm,
1277  const std::string& _ctx ) :
1278  irods::network(
1279  _nm,
1280  _ctx ) {
1281  } // ctor
1282 
1284  }
1285 
1286 }; // class ssl_network_plugin
1287 
1288 
1289 
1290 // =-=-=-=-=-=-=-
1291 // factory function to provide instance of the plugin
1292 extern "C"
1294  const std::string& _inst_name,
1295  const std::string& _context ) {
1296  // =-=-=-=-=-=-=-
1297  // create a ssl network object
1299  _inst_name,
1300  _context );
1301 
1302  // =-=-=-=-=-=-=-
1303  // fill in the operation table mapping call
1304  // names to function names
1305  using namespace irods;
1306  using namespace std;
1307  ssl->add_operation<rodsEnv*>(
1309  function<error(plugin_context&,rodsEnv*)>(
1310  ssl_client_start ) );
1311  ssl->add_operation<rodsEnv*>(
1313  function<error(plugin_context&,rodsEnv*)>(
1314  ssl_client_stop ) );
1315  ssl->add_operation(
1317  function<error(plugin_context&)>(
1318  ssl_agent_start ) );
1319  ssl->add_operation(
1321  function<error(plugin_context&)>(
1322  ssl_agent_stop ) );
1323  ssl->add_operation<void*, struct timeval*>(
1325  function<error(plugin_context&,void*, struct timeval*)>(
1326  ssl_read_msg_header ) );
1329  function<error(plugin_context&,msgHeader_t*,bytesBuf_t*,bytesBuf_t*,bytesBuf_t*,irodsProt_t,struct timeval*)>(
1330  ssl_read_msg_body ) );
1331  ssl->add_operation<bytesBuf_t*>(
1333  function<error(plugin_context&,bytesBuf_t*)>(
1337  function<error(plugin_context&,const char*,bytesBuf_t*,bytesBuf_t*,bytesBuf_t*,int,irodsProt_t)>(
1338  ssl_send_rods_msg ) );
1339 
1340  irods::network* net = dynamic_cast< irods::network* >( ssl );
1341 
1342  return net;
1343 
1344 } // plugin_factory
msgHeader::errorLen
int errorLen
Definition: rodsDef.h:213
rodsLog
void rodsLog(int level, const char *formatStr,...)
Definition: rodsLog.cpp:86
msgHeader::bsLen
int bsLen
Definition: rodsDef.h:214
NULL
#define NULL
Definition: rodsDef.h:70
irods::ssl_object
Definition: irods_ssl_object.hpp:20
rodsEnv::rodsEncryptionKeySize
int rodsEncryptionKeySize
Definition: getRodsEnv.h:27
ssl_client_stop
irods::error ssl_client_stop(irods::plugin_context &_ctx, rodsEnv *_env)
Definition: libssl.cpp:619
ssl_verify_callback
static int ssl_verify_callback(int ok, X509_STORE_CTX *store)
Definition: libssl.cpp:163
ssl_read_msg_header
irods::error ssl_read_msg_header(irods::plugin_context &_ctx, void *_buffer, struct timeval *_time_val)
Definition: libssl.cpp:536
msgHeader
Definition: rodsDef.h:210
getRodsEnv
int getRodsEnv(rodsEnv *myRodsEnv)
Definition: getRodsEnv.cpp:112
irods::buffer_crypt::array_t
std::vector< unsigned char > array_t
Definition: irods_buffer_encryption.hpp:30
readMsgBody
irods::error readMsgBody(irods::network_object_ptr, msgHeader_t *, bytesBuf_t *, bytesBuf_t *, bytesBuf_t *, irodsProt_t, struct timeval *)
Definition: sockComm.cpp:236
irods::NETWORK_OP_WRITE_BODY
const std::string NETWORK_OP_WRITE_BODY("network_write_body")
BytesBuf::buf
void * buf
Definition: rodsDef.h:199
msParam.h
irods::plugin_context::valid
virtual error valid()
Definition: irods_plugin_context.hpp:77
ssl_post_connection_check
static int ssl_post_connection_check(SSL *ssl, const char *peer)
Definition: libssl.cpp:296
HEADER_TYPE_LEN
#define HEADER_TYPE_LEN
Definition: rodsDef.h:53
irods_stacktrace.hpp
PASS
#define PASS(prev_error_)
Definition: irods_error.hpp:118
msgHeader::type
char type[128]
Definition: rodsDef.h:211
irods_ssl_object.hpp
ssl_load_hd_params
static int ssl_load_hd_params(SSL_CTX *ctx, char *file)
Definition: libssl.cpp:131
SHARED_KEY
const std::string SHARED_KEY("ssl_network_plugin_shared_key")
irods::NETWORK_OP_AGENT_STOP
const std::string NETWORK_OP_AGENT_STOP("network_agent_stop")
SSL_HANDSHAKE_ERROR
@ SSL_HANDSHAKE_ERROR
Definition: rodsErrorTable.h:825
env
Definition: restructs.hpp:226
XML_PROT
@ XML_PROT
Definition: rodsDef.h:149
irods::NETWORK_OP_CLIENT_START
const std::string NETWORK_OP_CLIENT_START("network_client_start")
rcConnect.h
pid_age.p
p
Definition: pid_age.py:13
irods::network
Definition: irods_network_plugin.hpp:18
SSL_INIT_ERROR
@ SSL_INIT_ERROR
Definition: rodsErrorTable.h:824
LOG_DEBUG8
#define LOG_DEBUG8
Definition: rodsLog.h:21
ssl_build_error_string
static void ssl_build_error_string(std::string &_str)
Definition: libssl.cpp:62
ssl_send_rods_msg
irods::error ssl_send_rods_msg(irods::plugin_context &_ctx, const char *_msg_type, bytesBuf_t *_msg_buf, bytesBuf_t *_stream_bbuf, bytesBuf_t *_error_buf, int _int_info, irodsProt_t _protocol)
Definition: libssl.cpp:1008
readMsgHeader
irods::error readMsgHeader(irods::network_object_ptr, msgHeader_t *, struct timeval *)
Definition: sockComm.cpp:173
irods::NETWORK_OP_WRITE_HEADER
const std::string NETWORK_OP_WRITE_HEADER("network_write_header")
irods::plugin_context
Definition: irods_plugin_context.hpp:18
LOG_ERROR
#define LOG_ERROR
Definition: rodsLog.h:43
generate_iadmin_commands_for_41_to_42_upgrade.name
name
Definition: generate_iadmin_commands_for_41_to_42_upgrade.py:23
irods::lookup_table::get
error get(const std::string &_key, ValueType &_val)
Definition: irods_lookup_table.hpp:71
SYS_INVALID_INPUT_PARAM
@ SYS_INVALID_INPUT_PARAM
Definition: rodsErrorTable.h:195
ssl_socket_write
irods::error ssl_socket_write(void *_buffer, int _length, int &_bytes_written, SSL *_ssl)
Definition: libssl.cpp:478
BytesBuf::len
int len
Definition: rodsDef.h:198
SYS_READ_MSG_BODY_INPUT_ERR
@ SYS_READ_MSG_BODY_INPUT_ERR
Definition: rodsErrorTable.h:79
ssl_get_dh2048
static DH * ssl_get_dh2048()
Definition: libssl.cpp:85
ASSERT_ERROR
#define ASSERT_ERROR(expr_, code_, format_,...)
Definition: irods_error.hpp:123
ssl_init_context
static SSL_CTX * ssl_init_context(char *certfile, char *keyfile)
Definition: libssl.cpp:189
msgHeader::msgLen
int msgLen
Definition: rodsDef.h:212
ssl_socket_read
irods::error ssl_socket_read(int _socket, void *_buffer, int _length, int &_bytes_read, struct timeval *_time_value, SSL *_ssl)
Definition: libssl.cpp:375
ssl_network_plugin
Definition: libssl.cpp:1273
SUCCESS
#define SUCCESS()
Definition: irods_error.hpp:121
SYS_HEADER_READ_LEN_ERR
@ SYS_HEADER_READ_LEN_ERR
Definition: rodsErrorTable.h:72
irodsProt_t
irodsProt_t
Definition: rodsDef.h:147
SYS_READ_MSG_BODY_LEN_ERR
@ SYS_READ_MSG_BODY_LEN_ERR
Definition: rodsErrorTable.h:156
irods_buffer_encryption.hpp
irods::plugin_context::prop_map
virtual irods::plugin_property_map & prop_map()
Definition: irods_plugin_context.hpp:99
SYS_SOCK_READ_ERR
@ SYS_SOCK_READ_ERR
Definition: rodsErrorTable.h:181
ssl_init_socket
static SSL * ssl_init_socket(SSL_CTX *_ctx, int _socket_handle)
Definition: libssl.cpp:272
LOG_DEBUG
#define LOG_DEBUG
Definition: rodsLog.h:23
getRodsLogLevel
int getRodsLogLevel()
Definition: rodsLog.cpp:344
irods
Definition: apiHandler.hpp:35
rodsDef.h
read_bytes_buf
irods::error read_bytes_buf(int _socket_handle, int _length, bytesBuf_t *_buffer, irodsProt_t _protocol, struct timeval *_time_val, SSL *_ssl)
Definition: libssl.cpp:1113
ssl_client_start
irods::error ssl_client_start(irods::plugin_context &_ctx, rodsEnv *_env)
Definition: libssl.cpp:661
irods_network_constants.hpp
MAX_NAME_LEN
#define MAX_NAME_LEN
Definition: rodsDef.h:61
ASSERT_PASS
#define ASSERT_PASS(prev_error_, format_,...)
Definition: irods_error.hpp:124
irods::lookup_table::has_entry
bool has_entry(KeyType _k) const
Definition: irods_lookup_table.hpp:41
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
sendRodsMsg
irods::error sendRodsMsg(irods::network_object_ptr, const char *, bytesBuf_t *, bytesBuf_t *, bytesBuf_t *, int, irodsProt_t)
Definition: sockComm.cpp:1221
irods::NETWORK_OP_READ_HEADER
const std::string NETWORK_OP_READ_HEADER("network_read_header")
ssl_agent_stop
irods::error ssl_agent_stop(irods::plugin_context &_ctx)
Definition: libssl.cpp:915
irods::log
void log(const error &)
Definition: irods_log.cpp:13
SSL_CERT_ERROR
@ SSL_CERT_ERROR
Definition: rodsErrorTable.h:827
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
ERROR
#define ERROR(code_, message_)
Definition: irods_error.hpp:117
BytesBuf
Definition: rodsDef.h:197
irods::error
Definition: irods_error.hpp:23
ssl_write_msg_header
irods::error ssl_write_msg_header(irods::plugin_context &_ctx, bytesBuf_t *_header)
Definition: libssl.cpp:961
writeMsgHeader
irods::error writeMsgHeader(irods::network_object_ptr, msgHeader_t *)
Definition: sockComm.cpp:435
int
typedef int((*funcPtr)())
ssl_network_plugin::~ssl_network_plugin
~ssl_network_plugin()
Definition: libssl.cpp:1283
irods::buffer_crypt::generate_key
static irods::error generate_key(array_t &, int)
Definition: irods_buffer_encryption.cpp:98
irods::network::network
network(const std::string &_inst, const std::string &_ctx)
Definition: irods_network_plugin.hpp:22
irods::NETWORK_OP_CLIENT_STOP
const std::string NETWORK_OP_CLIENT_STOP("network_client_stop")
SYS_SOCK_READ_TIMEDOUT
@ SYS_SOCK_READ_TIMEDOUT
Definition: rodsErrorTable.h:180
irods::NETWORK_OP_READ_BODY
const std::string NETWORK_OP_READ_BODY("network_read_body")
plugin_factory
irods::network * plugin_factory(const std::string &_inst_name, const std::string &_context)
Definition: libssl.cpp:1293
match
int match(char *pattern, char *text)
DH_set0_pqg
#define DH_set0_pqg(dh_, p_, q_, g_)
Definition: libssl.cpp:32
msgHeader::intInfo
int intInfo
Definition: rodsDef.h:215
irods::network_object_ptr
boost::shared_ptr< network_object > network_object_ptr
Definition: irods_network_object.hpp:78
update_schema_ids_for_cmake.file
file
Definition: update_schema_ids_for_cmake.py:21
ssl_network_plugin::ssl_network_plugin
ssl_network_plugin(const std::string &_nm, const std::string &_ctx)
Definition: libssl.cpp:1275
error
int error
Definition: filesystem.cpp:101
ssl_success_stub
irods::error ssl_success_stub(irods::plugin_context &)
Definition: libssl.cpp:1262
irods::plugin_base::add_operation
error add_operation(const std::string &_op, std::function< error(plugin_context &)> _f)
Definition: irods_plugin_base.hpp:122
irods::plugin_context::fco
virtual first_class_object_ptr fco()
Definition: irods_plugin_context.hpp:102
rodsEnv::rodsEncryptionNumHashRounds
int rodsEncryptionNumHashRounds
Definition: getRodsEnv.h:29
sockComm.h
ASN1_STRING_get0_data
#define ASN1_STRING_get0_data
Definition: libssl.cpp:31
irods::ssl_object_ptr
boost::shared_ptr< ssl_object > ssl_object_ptr
Definition: irods_ssl_object.hpp:129
irods::lookup_table::set
error set(const std::string &_key, const ValueType &_val)
Definition: irods_lookup_table.hpp:83
rodsEnv
Definition: getRodsEnv.h:8
rodsEnv::rodsEncryptionSaltSize
int rodsEncryptionSaltSize
Definition: getRodsEnv.h:28
SYS_HEADER_WRITE_LEN_ERR
@ SYS_HEADER_WRITE_LEN_ERR
Definition: rodsErrorTable.h:73
sockCommNetworkInterface.hpp
irods::error::ok
bool ok()
Definition: irods_error.cpp:258
buf
static char buf[64+50+1]
Definition: rsAuthRequest.cpp:21
ssl_log_error
static void ssl_log_error(const char *msg)
Definition: libssl.cpp:48
rodsEnv::rodsEncryptionAlgorithm
char rodsEncryptionAlgorithm[128]
Definition: getRodsEnv.h:30
ssl_read_msg_body
irods::error ssl_read_msg_body(irods::plugin_context &_ctx, msgHeader_t *_header, bytesBuf_t *_input_struct_buf, bytesBuf_t *_bs_buf, bytesBuf_t *_error_buf, irodsProt_t _protocol, struct timeval *_time_val)
Definition: libssl.cpp:1154
SSL_CIPHER_LIST
#define SSL_CIPHER_LIST
Definition: libssl.cpp:40
READ_VERSION_TOUT_SEC
#define READ_VERSION_TOUT_SEC
Definition: sockComm.h:25
irods_network_plugin.hpp
ssl_agent_start
irods::error ssl_agent_start(irods::plugin_context &_ctx)
Definition: libssl.cpp:785
irods::NETWORK_OP_AGENT_START
const std::string NETWORK_OP_AGENT_START("network_agent_start")
SSL_SHUTDOWN_ERROR
@ SSL_SHUTDOWN_ERROR
Definition: rodsErrorTable.h:826