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)  

sslSockComm.cpp
Go to the documentation of this file.
1 
3 /* sslSockComm.c - SSL socket communication routines
4  */
5 
6 
7 #include "rodsClient.h"
8 #include "sslSockComm.h"
10 #include "rcGlobalExtern.h"
11 #include "packStruct.h"
12 
13 // =-=-=-=-=-=-=-
14 // work around for SSL Macro version issues
15 #if OPENSSL_VERSION_NUMBER < 0x10100000
16 #define ASN1_STRING_get0_data ASN1_STRING_data
17 #define DH_set0_pqg(dh_, p_, q_, g_) \
18  dh_->p = p_; \
19  dh_->q = q_; \
20  dh_->g = g_;
21 #endif
22 
23 
24 
25 /* module internal functions */
26 static SSL_CTX *sslInit( char *certfile, char *keyfile );
27 static SSL *sslInitSocket( SSL_CTX *ctx, int sock );
28 static void sslLogError( char *msg );
29 static DH *get_dh2048();
30 static int sslLoadDHParams( SSL_CTX *ctx, char *file );
31 static int sslVerifyCallback( int ok, X509_STORE_CTX *store );
32 static int sslPostConnectionCheck( SSL *ssl, char *peer );
33 
34 int
35 sslStart( rcComm_t *rcComm ) {
36  int status;
37  sslStartInp_t sslStartInp;
38 
39  if ( rcComm == NULL ) {
40  return USER__NULL_INPUT_ERR;
41  }
42 
43  if ( rcComm->ssl_on ) {
44  /* SSL connection turned on ... return */
45  return 0;
46  }
47 
48  /* ask the server if we can start SSL */
49  memset( &sslStartInp, 0, sizeof( sslStartInp ) );
50  status = rcSslStart( rcComm, &sslStartInp );
51  if ( status < 0 ) {
52  rodsLogError( LOG_ERROR, status, "sslStart: server refused our request to start SSL" );
53  return status;
54  }
55 
56  /* we have the go-ahead ... set up SSL on our side of the socket */
57  rcComm->ssl_ctx = sslInit( NULL, NULL );
58  if ( rcComm->ssl_ctx == NULL ) {
59  rodsLog( LOG_ERROR, "sslStart: couldn't initialize SSL context" );
60  return SSL_INIT_ERROR;
61  }
62 
63  rcComm->ssl = sslInitSocket( rcComm->ssl_ctx, rcComm->sock );
64  if ( rcComm->ssl == NULL ) {
65  rodsLog( LOG_ERROR, "sslStart: couldn't initialize SSL socket" );
66  SSL_CTX_free( rcComm->ssl_ctx );
67  rcComm->ssl_ctx = NULL;
68  return SSL_INIT_ERROR;
69  }
70 
71  status = SSL_connect( rcComm->ssl );
72  if ( status < 1 ) {
73  sslLogError( "sslStart: error in SSL_connect" );
74  SSL_free( rcComm->ssl );
75  rcComm->ssl = NULL;
76  SSL_CTX_free( rcComm->ssl_ctx );
77  rcComm->ssl_ctx = NULL;
78  return SSL_HANDSHAKE_ERROR;
79  }
80 
81  rcComm->ssl_on = 1;
82 
83  if ( !sslPostConnectionCheck( rcComm->ssl, rcComm->host ) ) {
84  rodsLog( LOG_ERROR, "sslStart: post connection certificate check failed" );
85  sslEnd( rcComm );
86  return SSL_CERT_ERROR;
87  }
88 
89  snprintf( rcComm->negotiation_results, sizeof( rcComm->negotiation_results ),
90  "%s", irods::CS_NEG_USE_SSL.c_str() );
91  return 0;
92 }
93 
94 int
95 sslEnd( rcComm_t *rcComm ) {
96  int status;
97  sslEndInp_t sslEndInp;
98 
99  if ( rcComm == NULL ) {
100  return USER__NULL_INPUT_ERR;
101  }
102 
103  if ( !rcComm->ssl_on ) {
104  /* no SSL connection turned on ... return */
105  return 0;
106  }
107 
108  memset( &sslEndInp, 0, sizeof( sslEndInp ) );
109  status = rcSslEnd( rcComm, &sslEndInp );
110  if ( status < 0 ) {
111  rodsLogError( LOG_ERROR, status, "sslEnd: server refused our request to stop SSL" );
112  return status;
113  }
114 
115  /* shut down the SSL connection. First SSL_shutdown() sends "close notify" */
116  status = SSL_shutdown( rcComm->ssl );
117  if ( status == 0 ) {
118  /* do second phase of shutdown */
119  status = SSL_shutdown( rcComm->ssl );
120  }
121  if ( status != 1 ) {
122  sslLogError( "sslEnd: error shutting down the SSL connection" );
123  return SSL_SHUTDOWN_ERROR;
124  }
125 
126  /* clean up the SSL state */
127  SSL_free( rcComm->ssl );
128  rcComm->ssl = NULL;
129  SSL_CTX_free( rcComm->ssl_ctx );
130  rcComm->ssl_ctx = NULL;
131  rcComm->ssl_on = 0;
132 
133  snprintf( rcComm->negotiation_results, sizeof( rcComm->negotiation_results ),
134  "%s", irods::CS_NEG_USE_TCP.c_str() );
135  rodsLog( LOG_DEBUG, "sslShutdown: shut down SSL connection" );
136 
137 
138  return 0;
139 }
140 
141 int
142 sslAccept( rsComm_t *rsComm ) {
143  rodsEnv env;
144  int status = getRodsEnv( &env );
145  if ( status < 0 ) {
146  rodsLog(
147  LOG_ERROR,
148  "sslAccept - failed in getRodsEnv : %d",
149  status );
150  return status;
151  }
152 
153  /* set up the context using a certificate file and separate
154  keyfile passed through environment variables */
155  rsComm->ssl_ctx = sslInit( env.irodsSSLCertificateChainFile,
156  env.irodsSSLCertificateKeyFile );
157  if ( rsComm->ssl_ctx == NULL ) {
158  rodsLog( LOG_ERROR, "sslAccept: couldn't initialize SSL context" );
159  return SSL_INIT_ERROR;
160  }
161 
162  status = sslLoadDHParams( rsComm->ssl_ctx, env.irodsSSLDHParamsFile );
163  if ( status < 0 ) {
164  rodsLog( LOG_ERROR, "sslAccept: error setting Diffie-Hellman parameters" );
165  SSL_CTX_free( rsComm->ssl_ctx );
166  rsComm->ssl_ctx = NULL;
167  return SSL_INIT_ERROR;
168  }
169 
170  rsComm->ssl = sslInitSocket( rsComm->ssl_ctx, rsComm->sock );
171  if ( rsComm->ssl == NULL ) {
172  rodsLog( LOG_ERROR, "sslAccept: couldn't initialize SSL socket" );
173  SSL_CTX_free( rsComm->ssl_ctx );
174  rsComm->ssl_ctx = NULL;
175  return SSL_INIT_ERROR;
176  }
177 
178  status = SSL_accept( rsComm->ssl );
179  if ( status < 1 ) {
180  sslLogError( "sslAccept: error calling SSL_accept" );
181  return SSL_HANDSHAKE_ERROR;
182  }
183 
184  rsComm->ssl_on = 1;
185  snprintf( rsComm->negotiation_results, sizeof( rsComm->negotiation_results ),
186  "%s", irods::CS_NEG_USE_SSL.c_str() );
187 
188  rodsLog( LOG_DEBUG, "sslAccept: accepted SSL connection" );
189 
190  return 0;
191 }
192 
193 int
194 sslShutdown( rsComm_t *rsComm ) {
195  int status;
196 
197  /* shut down the SSL connection. Might need to call SSL_shutdown()
198  twice to allow the protocol to notify and then complete
199  the shutdown. */
200  status = SSL_shutdown( rsComm->ssl );
201  if ( status == 0 ) {
202  /* second phase of shutdown */
203  status = SSL_shutdown( rsComm->ssl );
204  }
205  if ( status != 1 ) {
206  sslLogError( "sslShutdown: error completing shutdown of SSL connection" );
207  return SSL_SHUTDOWN_ERROR;
208  }
209 
210  /* clean up the SSL state */
211  SSL_free( rsComm->ssl );
212  rsComm->ssl = NULL;
213  SSL_CTX_free( rsComm->ssl_ctx );
214  rsComm->ssl_ctx = NULL;
215  rsComm->ssl_on = 0;
216 
217  snprintf( rsComm->negotiation_results, sizeof( rsComm->negotiation_results ),
218  "%s", irods::CS_NEG_USE_TCP.c_str() );
219  rodsLog( LOG_DEBUG, "sslShutdown: shut down SSL connection" );
220 
221  return 0;
222 }
223 
224 
225 int
226 sslReadMsgHeader( int sock, msgHeader_t *myHeader, struct timeval *tv, SSL *ssl ) {
227  int nbytes;
228  int myLen;
229  char tmpBuf[MAX_NAME_LEN];
230  msgHeader_t *outHeader;
231  int status;
232 
233  /* read the header length packet */
234 
235  nbytes = sslRead( sock, ( void * ) &myLen, sizeof( myLen ),
236  NULL, tv, ssl );
237  if ( nbytes != sizeof( myLen ) ) {
238  if ( nbytes < 0 ) {
239  status = nbytes - errno;
240  }
241  else {
243  }
245  "sslReadMsgHeader:header read- read %d bytes, expect %d, status = %d",
246  nbytes, sizeof( myLen ), status );
247  return status;
248  }
249 
250  myLen = ntohl( myLen );
251  if ( myLen > MAX_NAME_LEN || myLen <= 0 ) {
253  "sslReadMsgHeader: header length %d out of range",
254  myLen );
256  }
257 
258  nbytes = sslRead( sock, ( void * ) tmpBuf, myLen, NULL, tv, ssl );
259 
260  if ( nbytes != myLen ) {
261  if ( nbytes < 0 ) {
262  status = nbytes - errno;
263  }
264  else {
266  }
268  "sslReadMsgHeader:header read- read %d bytes, expect %d, status = %d",
269  nbytes, myLen, status );
270  return status;
271  }
272 
273  if ( getRodsLogLevel() >= LOG_DEBUG8 ) {
274  printf( "received header: len = %d\n%s\n", myLen, tmpBuf );
275  }
276 
277  /* always use XML_PROT for the startup pack */
278  status = unpackStruct( ( void * ) tmpBuf, ( void ** )( static_cast<void *>( &outHeader ) ),
279  "MsgHeader_PI", RodsPackTable, XML_PROT );
280 
281  if ( status < 0 ) {
283  "sslReadMsgHeader:unpackStruct error. status = %d",
284  status );
285  return status;
286  }
287 
288  *myHeader = *outHeader;
289 
290  free( outHeader );
291 
292  return 0;
293 }
294 
295 int
296 sslReadMsgBody( int sock, msgHeader_t *myHeader, bytesBuf_t *inputStructBBuf,
297  bytesBuf_t *bsBBuf, bytesBuf_t *errorBBuf, irodsProt_t irodsProt,
298  struct timeval *tv, SSL *ssl ) {
299  int nbytes;
300  int bytesRead;
301 
302  if ( myHeader == NULL ) {
304  }
305  if ( inputStructBBuf != NULL ) {
306  memset( inputStructBBuf, 0, sizeof( bytesBuf_t ) );
307  }
308 
309  /* Don't memset bsBBuf because bsBBuf can be reused on the client side */
310 
311  if ( errorBBuf != NULL ) {
312  memset( errorBBuf, 0, sizeof( bytesBuf_t ) );
313  }
314 
315  if ( myHeader->msgLen > 0 ) {
316  if ( inputStructBBuf == NULL ) {
318  }
319 
320  inputStructBBuf->buf = malloc( myHeader->msgLen );
321 
322  nbytes = sslRead( sock, inputStructBBuf->buf, myHeader->msgLen,
323  NULL, tv, ssl );
324 
325  if ( irodsProt == XML_PROT && getRodsLogLevel() >= LOG_DEBUG8 ) {
326  printf( "received msg: \n%s\n", ( char * ) inputStructBBuf->buf );
327  }
328 
329  if ( nbytes != myHeader->msgLen ) {
331  "sslReadMsgBody: inputStruct read error, read %d bytes, expect %d",
332  nbytes, myHeader->msgLen );
333  free( inputStructBBuf->buf );
335  }
336  inputStructBBuf->len = myHeader->msgLen;
337  }
338 
339  if ( myHeader->errorLen > 0 ) {
340  if ( errorBBuf == NULL ) {
342  }
343 
344  errorBBuf->buf = malloc( myHeader->errorLen );
345 
346  nbytes = sslRead( sock, errorBBuf->buf, myHeader->errorLen,
347  NULL, tv, ssl );
348 
349  if ( irodsProt == XML_PROT && getRodsLogLevel() >= LOG_DEBUG8 ) {
350  printf( "received error msg: \n%s\n", ( char * ) errorBBuf->buf );
351  }
352 
353  if ( nbytes != myHeader->errorLen ) {
355  "sslReadMsgBody: errorBbuf read error, read %d bytes, expect %d, errno = %d",
356  nbytes, myHeader->msgLen, errno );
357  free( errorBBuf->buf );
358  return SYS_READ_MSG_BODY_LEN_ERR - errno;
359  }
360  errorBBuf->len = myHeader->errorLen;
361  }
362 
363  if ( myHeader->bsLen > 0 ) {
364  if ( bsBBuf == NULL ) {
366  }
367 
368  if ( bsBBuf->buf == NULL ) {
369  bsBBuf->buf = malloc( myHeader->bsLen );
370  }
371  else if ( myHeader->bsLen > bsBBuf->len ) {
372  free( bsBBuf->buf );
373  bsBBuf->buf = malloc( myHeader->bsLen );
374  }
375 
376  nbytes = sslRead( sock, bsBBuf->buf, myHeader->bsLen,
377  &bytesRead, tv, ssl );
378 
379  if ( nbytes != myHeader->bsLen ) {
381  "sslReadMsgBody: bsBBuf read error, read %d bytes, expect %d, errno = %d",
382  nbytes, myHeader->bsLen, errno );
383  free( bsBBuf->buf );
384  return SYS_READ_MSG_BODY_INPUT_ERR - errno;
385  }
386  bsBBuf->len = myHeader->bsLen;
387  }
388 
389  return 0;
390 }
391 
392 int
393 sslWriteMsgHeader( msgHeader_t *myHeader, SSL *ssl ) {
394  int nbytes;
395  int status;
396  int myLen;
397  bytesBuf_t *headerBBuf = NULL;
398 
399  /* always use XML_PROT for the Header */
400  status = packStruct( ( void * ) myHeader, &headerBBuf,
401  "MsgHeader_PI", RodsPackTable, 0, XML_PROT );
402 
403  if ( status < 0 ) {
405  "sslWriteMsgHeader: packStruct error, status = %d", status );
406  return status;
407  }
408 
409  if ( getRodsLogLevel() >= LOG_DEBUG8 ) {
410  printf( "sending header: len = %d\n%s\n", headerBBuf->len,
411  ( char * ) headerBBuf->buf );
412  }
413 
414  myLen = htonl( headerBBuf->len );
415 
416  nbytes = sslWrite( ( void * ) &myLen, sizeof( myLen ), NULL, ssl );
417 
418  if ( nbytes != sizeof( myLen ) ) {
420  "sslWriteMsgHeader: wrote %d bytes for myLen , expect %d, status = %d",
421  nbytes, sizeof( myLen ), SYS_HEADER_WRITE_LEN_ERR - errno );
422  freeBBuf( headerBBuf );
423  return SYS_HEADER_WRITE_LEN_ERR - errno;
424  }
425 
426  /* now send the header */
427 
428  nbytes = sslWrite( headerBBuf->buf, headerBBuf->len, NULL, ssl );
429 
430  if ( headerBBuf->len != nbytes ) {
432  "sslWriteMsgHeader: wrote %d bytes, expect %d, status = %d",
433  nbytes, headerBBuf->len, SYS_HEADER_WRITE_LEN_ERR - errno );
434  freeBBuf( headerBBuf );
435  return SYS_HEADER_WRITE_LEN_ERR - errno;
436  }
437 
438  freeBBuf( headerBBuf );
439 
440  return 0;
441 }
442 
443 int
444 sslSendRodsMsg( char *msgType, bytesBuf_t *msgBBuf,
445  bytesBuf_t *byteStreamBBuf, bytesBuf_t *errorBBuf, int intInfo,
446  irodsProt_t irodsProt, SSL *ssl ) {
447  int status;
449  int bytesWritten;
450 
451  memset( &msgHeader, 0, sizeof( msgHeader ) );
452 
453  rstrcpy( msgHeader.type, msgType, HEADER_TYPE_LEN );
454 
455  msgHeader.msgLen = msgBBuf ? msgBBuf->len : 0;
456  msgHeader.bsLen = byteStreamBBuf ? byteStreamBBuf->len : 0;
457  msgHeader.errorLen = errorBBuf ? errorBBuf->len : 0;
458 
459  msgHeader.intInfo = intInfo;
460 
462 
463  if ( status < 0 ) {
464  return status;
465  }
466 
467  /* send the rest */
468 
469  if ( msgBBuf && msgBBuf->len > 0 ) {
470  if ( irodsProt == XML_PROT && getRodsLogLevel() >= LOG_DEBUG8 ) {
471  printf( "sending msg: \n%s\n", ( char * ) msgBBuf->buf );
472  }
473  status = sslWrite( msgBBuf->buf, msgBBuf->len, NULL, ssl );
474  if ( status < 0 ) {
475  return status;
476  }
477  }
478 
479  if ( errorBBuf && errorBBuf->len > 0 ) {
480  if ( irodsProt == XML_PROT && getRodsLogLevel() >= LOG_DEBUG8 ) {
481  printf( "sending error msg: \n%s\n", ( char * ) errorBBuf->buf );
482  }
483  status = sslWrite( errorBBuf->buf, errorBBuf->len,
484  NULL, ssl );
485  if ( status < 0 ) {
486  return status;
487  }
488  }
489  if ( byteStreamBBuf && byteStreamBBuf->len > 0 ) {
490  status = sslWrite( byteStreamBBuf->buf, byteStreamBBuf->len,
491  &bytesWritten, ssl );
492  if ( status < 0 ) {
493  return status;
494  }
495  }
496 
497  return 0;
498 }
499 
500 int
501 sslRead( int sock, void *buf, int len,
502  int *bytesRead, struct timeval *tv, SSL *ssl ) {
503  struct timeval timeout;
504 
505  /* Initialize the file descriptor set. */
506  fd_set set;
507  FD_ZERO( &set );
508  FD_SET( sock, &set );
509  if ( tv != NULL ) {
510  timeout = *tv;
511  }
512 
513  int toRead = len;
514  char *tmpPtr = ( char * ) buf;
515 
516  if ( bytesRead != NULL ) {
517  *bytesRead = 0;
518  }
519 
520  while ( toRead > 0 ) {
521  if ( SSL_pending( ssl ) == 0 && tv != NULL ) {
522  const int status = select( sock + 1, &set, NULL, NULL, &timeout );
523  if ( status == 0 ) {
524  /* timedout */
525  if ( len - toRead > 0 ) {
526  return len - toRead;
527  }
528  else {
529  return SYS_SOCK_READ_TIMEDOUT;
530  }
531  }
532  else if ( status < 0 ) {
533  if ( errno == EINTR ) {
534  continue;
535  }
536  else {
537  return SYS_SOCK_READ_ERR - errno;
538  }
539  }
540  }
541  int nbytes = SSL_read( ssl, ( void * ) tmpPtr, toRead );
542  if ( SSL_get_error( ssl, nbytes ) != SSL_ERROR_NONE ) {
543  if ( errno == EINTR ) {
544  /* interrupted */
545  errno = 0;
546  nbytes = 0;
547  }
548  else {
549  break;
550  }
551  }
552 
553  toRead -= nbytes;
554  tmpPtr += nbytes;
555  if ( bytesRead != NULL ) {
556  *bytesRead += nbytes;
557  }
558  }
559  return len - toRead;
560 }
561 
562 int
563 sslWrite( void *buf, int len,
564  int *bytesWritten, SSL *ssl ) {
565  int nbytes;
566  int toWrite;
567  char *tmpPtr;
568 
569  toWrite = len;
570  tmpPtr = ( char * ) buf;
571 
572  if ( bytesWritten != NULL ) {
573  *bytesWritten = 0;
574  }
575 
576  while ( toWrite > 0 ) {
577  nbytes = SSL_write( ssl, ( void * ) tmpPtr, toWrite );
578  if ( SSL_get_error( ssl, nbytes ) != SSL_ERROR_NONE ) {
579  if ( errno == EINTR ) {
580  /* interrupted */
581  errno = 0;
582  nbytes = 0;
583  }
584  else {
585  break;
586  }
587  }
588  toWrite -= nbytes;
589  tmpPtr += nbytes;
590  if ( bytesWritten != NULL ) {
591  *bytesWritten += nbytes;
592  }
593  }
594  return len - toWrite;
595 }
596 
597 /* Module internal support functions */
598 
599 static SSL_CTX*
600 sslInit( char *certfile, char *keyfile ) {
601  static int init_done = 0;
602 
603  rodsEnv env;
604  int status = getRodsEnv( &env );
605  if ( status < 0 ) {
606  rodsLog(
607  LOG_ERROR,
608  "sslInit - failed in getRodsEnv : %d",
609  status );
610  return NULL;
611 
612  }
613 
614  if ( !init_done ) {
615  SSL_library_init();
616  SSL_load_error_strings();
617  init_done = 1;
618  }
619 
620  /* in our test programs we set up a null signal
621  handler for SIGPIPE */
622  /* signal(SIGPIPE, sslSigpipeHandler); */
623 
624  SSL_CTX* ctx = SSL_CTX_new( SSLv23_method() );
625 
626  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 );
627 
628  /* load our keys and certificates if provided */
629  if ( certfile ) {
630  if ( SSL_CTX_use_certificate_chain_file( ctx, certfile ) != 1 ) {
631  sslLogError( "sslInit: couldn't read certificate chain file" );
632  SSL_CTX_free( ctx );
633  return NULL;
634  }
635  else {
636  if ( SSL_CTX_use_PrivateKey_file( ctx, keyfile, SSL_FILETYPE_PEM ) != 1 ) {
637  sslLogError( "sslInit: couldn't read key file" );
638  SSL_CTX_free( ctx );
639  return NULL;
640  }
641  }
642  }
643 
644  /* set up CA paths and files here */
645  const char *ca_path = strcmp( env.irodsSSLCACertificatePath, "" ) ? env.irodsSSLCACertificatePath : NULL;
646  const char *ca_file = strcmp( env.irodsSSLCACertificateFile, "" ) ? env.irodsSSLCACertificateFile : NULL;
647  if ( ca_path || ca_file ) {
648  if ( SSL_CTX_load_verify_locations( ctx, ca_file, ca_path ) != 1 ) {
649  sslLogError( "sslInit: error loading CA certificate locations" );
650  }
651  }
652  if ( SSL_CTX_set_default_verify_paths( ctx ) != 1 ) {
653  sslLogError( "sslInit: error loading default CA certificate locations" );
654  }
655 
656  /* Set up the default certificate verification */
657  /* if "none" is specified, we won't stop the SSL handshake
658  due to certificate error, but will log messages from
659  the verification callback */
660  const char* verify_server = env.irodsSSLVerifyServer;
661  if ( verify_server && !strcmp( verify_server, "none" ) ) {
662  SSL_CTX_set_verify( ctx, SSL_VERIFY_NONE, sslVerifyCallback );
663  }
664  else {
665  SSL_CTX_set_verify( ctx, SSL_VERIFY_PEER, sslVerifyCallback );
666  }
667  /* default depth is nine ... leave this here in case it needs modification */
668  SSL_CTX_set_verify_depth( ctx, 9 );
669 
670  /* ciphers */
671  if ( SSL_CTX_set_cipher_list( ctx, SSL_CIPHER_LIST ) != 1 ) {
672  sslLogError( "sslInit: couldn't set the cipher list (no valid ciphers)" );
673  SSL_CTX_free( ctx );
674  return NULL;
675  }
676 
677  return ctx;
678 }
679 
680 static SSL*
681 sslInitSocket( SSL_CTX *ctx, int sock ) {
682  SSL *ssl;
683  BIO *bio;
684 
685  bio = BIO_new_socket( sock, BIO_NOCLOSE );
686  if ( bio == NULL ) {
687  sslLogError( "sslInitSocket: BIO allocation error" );
688  return NULL;
689  }
690  ssl = SSL_new( ctx );
691  if ( ssl == NULL ) {
692  sslLogError( "sslInitSocket: couldn't create a new SSL socket" );
693  BIO_free( bio );
694  return NULL;
695  }
696  SSL_set_bio( ssl, bio, bio );
697 
698  return ssl;
699 }
700 
701 static void
702 sslLogError( char *msg ) {
703  unsigned long err;
704  char buf[512];
705 
706  while ( ( err = ERR_get_error() ) ) {
707  ERR_error_string_n( err, buf, 512 );
708  rodsLog( LOG_ERROR, "%s. SSL error: %s", msg, buf );
709  }
710 }
711 
712 /* This function returns a set of built-in Diffie-Hellman
713  parameters. We could read the parameters from a file instead,
714  but this is a reasonably strong prime. The parameters come from
715  the openssl distribution's 'apps' sub-directory. Comment from
716  the source file is:
717 
718  These are the 2048 bit DH parameters from "Assigned Number for SKIP Protocols"
719  (http://www.skip-vpn.org/spec/numbers.html).
720  See there for how they were generated. */
721 
722 static DH*
724  static unsigned char dh2048_p[] = {
725  0xF6, 0x42, 0x57, 0xB7, 0x08, 0x7F, 0x08, 0x17, 0x72, 0xA2, 0xBA, 0xD6,
726  0xA9, 0x42, 0xF3, 0x05, 0xE8, 0xF9, 0x53, 0x11, 0x39, 0x4F, 0xB6, 0xF1,
727  0x6E, 0xB9, 0x4B, 0x38, 0x20, 0xDA, 0x01, 0xA7, 0x56, 0xA3, 0x14, 0xE9,
728  0x8F, 0x40, 0x55, 0xF3, 0xD0, 0x07, 0xC6, 0xCB, 0x43, 0xA9, 0x94, 0xAD,
729  0xF7, 0x4C, 0x64, 0x86, 0x49, 0xF8, 0x0C, 0x83, 0xBD, 0x65, 0xE9, 0x17,
730  0xD4, 0xA1, 0xD3, 0x50, 0xF8, 0xF5, 0x59, 0x5F, 0xDC, 0x76, 0x52, 0x4F,
731  0x3D, 0x3D, 0x8D, 0xDB, 0xCE, 0x99, 0xE1, 0x57, 0x92, 0x59, 0xCD, 0xFD,
732  0xB8, 0xAE, 0x74, 0x4F, 0xC5, 0xFC, 0x76, 0xBC, 0x83, 0xC5, 0x47, 0x30,
733  0x61, 0xCE, 0x7C, 0xC9, 0x66, 0xFF, 0x15, 0xF9, 0xBB, 0xFD, 0x91, 0x5E,
734  0xC7, 0x01, 0xAA, 0xD3, 0x5B, 0x9E, 0x8D, 0xA0, 0xA5, 0x72, 0x3A, 0xD4,
735  0x1A, 0xF0, 0xBF, 0x46, 0x00, 0x58, 0x2B, 0xE5, 0xF4, 0x88, 0xFD, 0x58,
736  0x4E, 0x49, 0xDB, 0xCD, 0x20, 0xB4, 0x9D, 0xE4, 0x91, 0x07, 0x36, 0x6B,
737  0x33, 0x6C, 0x38, 0x0D, 0x45, 0x1D, 0x0F, 0x7C, 0x88, 0xB3, 0x1C, 0x7C,
738  0x5B, 0x2D, 0x8E, 0xF6, 0xF3, 0xC9, 0x23, 0xC0, 0x43, 0xF0, 0xA5, 0x5B,
739  0x18, 0x8D, 0x8E, 0xBB, 0x55, 0x8C, 0xB8, 0x5D, 0x38, 0xD3, 0x34, 0xFD,
740  0x7C, 0x17, 0x57, 0x43, 0xA3, 0x1D, 0x18, 0x6C, 0xDE, 0x33, 0x21, 0x2C,
741  0xB5, 0x2A, 0xFF, 0x3C, 0xE1, 0xB1, 0x29, 0x40, 0x18, 0x11, 0x8D, 0x7C,
742  0x84, 0xA7, 0x0A, 0x72, 0xD6, 0x86, 0xC4, 0x03, 0x19, 0xC8, 0x07, 0x29,
743  0x7A, 0xCA, 0x95, 0x0C, 0xD9, 0x96, 0x9F, 0xAB, 0xD0, 0x0A, 0x50, 0x9B,
744  0x02, 0x46, 0xD3, 0x08, 0x3D, 0x66, 0xA4, 0x5D, 0x41, 0x9F, 0x9C, 0x7C,
745  0xBD, 0x89, 0x4B, 0x22, 0x19, 0x26, 0xBA, 0xAB, 0xA2, 0x5E, 0xC3, 0x55,
746  0xE9, 0x32, 0x0B, 0x3B,
747  };
748  static unsigned char dh2048_g[] = {
749  0x02,
750  };
751  auto *dh = DH_new();
752 
753  if ( !dh ) {
754  return NULL;
755  }
756  auto* p = BN_bin2bn( dh2048_p, sizeof( dh2048_p ), NULL );
757  auto* g = BN_bin2bn( dh2048_g, sizeof( dh2048_g ), NULL );
758  if ( !p || !g ) {
759  DH_free( dh );
760  return NULL;
761  }
762  DH_set0_pqg(dh, p, nullptr, g);
763  return dh;
764 }
765 
766 static int
767 sslLoadDHParams( SSL_CTX *ctx, char *file ) {
768  DH *dhparams = NULL;
769  BIO *bio;
770 
771  if ( file ) {
772  bio = BIO_new_file( file, "r" );
773  if ( bio ) {
774  dhparams = PEM_read_bio_DHparams( bio, NULL, NULL, NULL );
775  BIO_free( bio );
776  }
777  }
778 
779  if ( dhparams == NULL ) {
780  sslLogError( "sslLoadDHParams: can't load DH parameter file. Falling back to built-ins." );
781  dhparams = get_dh2048();
782  if ( dhparams == NULL ) {
783  rodsLog( LOG_ERROR, "sslLoadDHParams: can't load built-in DH params" );
784  return -1;
785  }
786  }
787 
788  if ( SSL_CTX_set_tmp_dh( ctx, dhparams ) < 0 ) {
789  sslLogError( "sslLoadDHParams: couldn't set DH parameters" );
790  return -1;
791  }
792  return 0;
793 }
794 
795 static int
796 sslVerifyCallback( int ok, X509_STORE_CTX *store ) {
797  char data[256];
798 
799  /* log any verification problems, even if we'll still accept the cert */
800  if ( !ok ) {
801  auto *cert = X509_STORE_CTX_get_current_cert( store );
802  int depth = X509_STORE_CTX_get_error_depth( store );
803  int err = X509_STORE_CTX_get_error( store );
804 
805  rodsLog( LOG_NOTICE, "sslVerifyCallback: problem with certificate at depth: %i", depth );
806  X509_NAME_oneline( X509_get_issuer_name( cert ), data, 256 );
807  rodsLog( LOG_NOTICE, "sslVerifyCallback: issuer = %s", data );
808  X509_NAME_oneline( X509_get_subject_name( cert ), data, 256 );
809  rodsLog( LOG_NOTICE, "sslVerifyCallback: subject = %s", data );
810  rodsLog( LOG_NOTICE, "sslVerifyCallback: err %i:%s", err,
811  X509_verify_cert_error_string( err ) );
812  }
813 
814  return ok;
815 }
816 
817 static int
818 sslPostConnectionCheck( SSL *ssl, char *peer ) {
819  rodsEnv env;
820  int status = getRodsEnv( &env );
821  if ( status < 0 ) {
822  rodsLog(
823  LOG_ERROR,
824  "sslPostConnectionCheck - failed in getRodsEnv : %d",
825  status );
826  return status;
827 
828  }
829 
830  int match = 0;
831  char cn[256];
832 
833  const char* verify_server = env.irodsSSLVerifyServer;
834  if ( verify_server && strcmp( verify_server, "hostname" ) ) {
835  /* not being asked to verify that the peer hostname
836  is in the certificate. */
837  return 1;
838  }
839 
840  auto* cert = SSL_get_peer_certificate( ssl );
841  if ( cert == NULL ) {
842  /* no certificate presented */
843  return 0;
844  }
845 
846  if ( peer == NULL ) {
847  /* no hostname passed to verify */
848  X509_free( cert );
849  return 0;
850  }
851 
852  /* check if the peer name matches any of the subjectAltNames
853  listed in the certificate */
854  auto names = static_cast<STACK_OF(GENERAL_NAME)*>(X509_get_ext_d2i( cert, NID_subject_alt_name, NULL, NULL ));
855  std::size_t num_names = sk_GENERAL_NAME_num( names );
856  for ( std::size_t i = 0; i < num_names; i++ ) {
857  auto* name = sk_GENERAL_NAME_value( names, i );
858  if ( name->type == GEN_DNS ) {
859  if ( !strcasecmp( reinterpret_cast<const char*>(ASN1_STRING_get0_data( name->d.dNSName )), peer ) ) {
860  match = 1;
861  break;
862  }
863  }
864  }
865  sk_GENERAL_NAME_free( names );
866 
867  /* if no match above, check the common name in the certificate */
868  if ( !match &&
869  ( X509_NAME_get_text_by_NID( X509_get_subject_name( cert ),
870  NID_commonName, cn, 256 ) != -1 ) ) {
871  cn[255] = 0;
872  if ( !strcasecmp( cn, peer ) ) {
873  match = 1;
874  }
875  else if ( cn[0] == '*' ) { /* wildcard domain */
876  char *tmp = strchr( peer, '.' );
877  if ( tmp && !strcasecmp( tmp, cn + 1 ) ) {
878  match = 1;
879  }
880  }
881  }
882 
883  X509_free( cert );
884 
885  if ( match ) {
886  return 1;
887  }
888  else {
889  return 0;
890  }
891 }
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
rcComm_t
Definition: rcConnect.h:95
NULL
#define NULL
Definition: rodsDef.h:70
sslEndInp_t
Definition: sslEnd.h:6
rsComm_t
Definition: rcConnect.h:145
ASN1_STRING_get0_data
#define ASN1_STRING_get0_data
Definition: sslSockComm.cpp:16
sslWriteMsgHeader
int sslWriteMsgHeader(msgHeader_t *myHeader, SSL *ssl)
Definition: sslSockComm.cpp:393
msgHeader
Definition: rodsDef.h:210
getRodsEnv
int getRodsEnv(rodsEnv *myRodsEnv)
Definition: getRodsEnv.cpp:112
sslShutdown
int sslShutdown(rsComm_t *rsComm)
Definition: sslSockComm.cpp:194
rcComm_t::host
char host[64]
Definition: rcConnect.h:97
BytesBuf::buf
void * buf
Definition: rodsDef.h:199
sslLoadDHParams
static int sslLoadDHParams(SSL_CTX *ctx, char *file)
Definition: sslSockComm.cpp:767
HEADER_TYPE_LEN
#define HEADER_TYPE_LEN
Definition: rodsDef.h:53
sslLogError
static void sslLogError(char *msg)
Definition: sslSockComm.cpp:702
irods::CS_NEG_USE_TCP
const std::string CS_NEG_USE_TCP("CS_NEG_USE_TCP")
msgHeader::type
char type[128]
Definition: rodsDef.h:211
sslSockComm.h
SSL_HANDSHAKE_ERROR
@ SSL_HANDSHAKE_ERROR
Definition: rodsErrorTable.h:825
env
Definition: restructs.hpp:226
sslWrite
int sslWrite(void *buf, int len, int *bytesWritten, SSL *ssl)
Definition: sslSockComm.cpp:563
XML_PROT
@ XML_PROT
Definition: rodsDef.h:149
rcComm_t::ssl_on
int ssl_on
Definition: rcConnect.h:128
SSL_CIPHER_LIST
#define SSL_CIPHER_LIST
Definition: sslSockComm.h:17
pid_age.p
p
Definition: pid_age.py:13
unpackStruct
int unpackStruct(const void *inPackStr, void **outStruct, const char *packInstName, const packInstruct_t *myPackTable, irodsProt_t irodsProt)
Definition: packStruct.cpp:63
SSL_INIT_ERROR
@ SSL_INIT_ERROR
Definition: rodsErrorTable.h:824
LOG_DEBUG8
#define LOG_DEBUG8
Definition: rodsLog.h:21
rcGlobalExtern.h
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
sslAccept
int sslAccept(rsComm_t *rsComm)
Definition: sslSockComm.cpp:142
BytesBuf::len
int len
Definition: rodsDef.h:198
SYS_READ_MSG_BODY_INPUT_ERR
@ SYS_READ_MSG_BODY_INPUT_ERR
Definition: rodsErrorTable.h:79
msgHeader::msgLen
int msgLen
Definition: rodsDef.h:212
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
sslReadMsgHeader
int sslReadMsgHeader(int sock, msgHeader_t *myHeader, struct timeval *tv, SSL *ssl)
Definition: sslSockComm.cpp:226
sslRead
int sslRead(int sock, void *buf, int len, int *bytesRead, struct timeval *tv, SSL *ssl)
Definition: sslSockComm.cpp:501
SYS_SOCK_READ_ERR
@ SYS_SOCK_READ_ERR
Definition: rodsErrorTable.h:181
sslInit
static SSL_CTX * sslInit(char *certfile, char *keyfile)
Definition: sslSockComm.cpp:600
LOG_DEBUG
#define LOG_DEBUG
Definition: rodsLog.h:23
getRodsLogLevel
int getRodsLogLevel()
Definition: rodsLog.cpp:344
sslPostConnectionCheck
static int sslPostConnectionCheck(SSL *ssl, char *peer)
Definition: sslSockComm.cpp:818
get_dh2048
static DH * get_dh2048()
Definition: sslSockComm.cpp:723
rsComm_t::negotiation_results
char negotiation_results[(1024+64)]
Definition: rcConnect.h:185
sslVerifyCallback
static int sslVerifyCallback(int ok, X509_STORE_CTX *store)
Definition: sslSockComm.cpp:796
irods::CS_NEG_USE_SSL
const std::string CS_NEG_USE_SSL("CS_NEG_USE_SSL")
DH_set0_pqg
#define DH_set0_pqg(dh_, p_, q_, g_)
Definition: sslSockComm.cpp:17
sslReadMsgBody
int sslReadMsgBody(int sock, msgHeader_t *myHeader, bytesBuf_t *inputStructBBuf, bytesBuf_t *bsBBuf, bytesBuf_t *errorBBuf, irodsProt_t irodsProt, struct timeval *tv, SSL *ssl)
Definition: sslSockComm.cpp:296
rsComm_t::ssl
SSL * ssl
Definition: rcConnect.h:181
MAX_NAME_LEN
#define MAX_NAME_LEN
Definition: rodsDef.h:61
rsComm_t::ssl_ctx
SSL_CTX * ssl_ctx
Definition: rcConnect.h:180
rcComm_t::ssl
SSL * ssl
Definition: rcConnect.h:130
irods.pypyodbc.status
status
Definition: pypyodbc.py:467
packStruct.h
rcComm_t::ssl_ctx
SSL_CTX * ssl_ctx
Definition: rcConnect.h:129
SSL_CERT_ERROR
@ SSL_CERT_ERROR
Definition: rodsErrorTable.h:827
LOG_NOTICE
#define LOG_NOTICE
Definition: rodsLog.h:33
sslStartInp_t
Definition: sslStart.h:6
sslInitSocket
static SSL * sslInitSocket(SSL_CTX *ctx, int sock)
Definition: sslSockComm.cpp:681
sslEnd
int sslEnd(rcComm_t *rcComm)
Definition: sslSockComm.cpp:95
RodsPackTable
const packInstruct_t RodsPackTable[]
Definition: rodsPackTable.h:61
BytesBuf
Definition: rodsDef.h:197
rsComm_t::ssl_on
int ssl_on
Definition: rcConnect.h:179
SYS_SOCK_READ_TIMEDOUT
@ SYS_SOCK_READ_TIMEDOUT
Definition: rodsErrorTable.h:180
sslStart
int sslStart(rcComm_t *rcComm)
Definition: sslSockComm.cpp:35
rcSslStart
int rcSslStart(rcComm_t *conn, sslStartInp_t *sslStartInp)
Definition: rcSslStart.cpp:9
match
int match(char *pattern, char *text)
msgHeader::intInfo
int intInfo
Definition: rodsDef.h:215
sslSendRodsMsg
int sslSendRodsMsg(char *msgType, bytesBuf_t *msgBBuf, bytesBuf_t *byteStreamBBuf, bytesBuf_t *errorBBuf, int intInfo, irodsProt_t irodsProt, SSL *ssl)
Definition: sslSockComm.cpp:444
rodsClient.h
update_schema_ids_for_cmake.file
file
Definition: update_schema_ids_for_cmake.py:21
rodsLogError
void rodsLogError(int level, int errCode, char *formatStr,...)
Definition: rodsLog.cpp:422
packStruct
int packStruct(const void *inStruct, bytesBuf_t **packedResult, const char *packInstName, const packInstruct_t *myPackTable, int packFlag, irodsProt_t irodsProt)
Definition: packStruct.cpp:21
freeBBuf
int freeBBuf(bytesBuf_t *myBBuf)
Definition: rcMisc.cpp:88
rstrcpy
char * rstrcpy(char *dest, const char *src, int maxLen)
Definition: stringOpr.cpp:51
rodsEnv
Definition: getRodsEnv.h:8
SYS_HEADER_WRITE_LEN_ERR
@ SYS_HEADER_WRITE_LEN_ERR
Definition: rodsErrorTable.h:73
buf
static char buf[64+50+1]
Definition: rsAuthRequest.cpp:21
rsComm_t::sock
int sock
Definition: rcConnect.h:147
irods_client_server_negotiation.hpp
rcComm_t::negotiation_results
char negotiation_results[(1024+64)]
Definition: rcConnect.h:125
USER__NULL_INPUT_ERR
@ USER__NULL_INPUT_ERR
Definition: rodsErrorTable.h:247
SSL_SHUTDOWN_ERROR
@ SSL_SHUTDOWN_ERROR
Definition: rodsErrorTable.h:826
rcSslEnd
int rcSslEnd(rcComm_t *conn, sslEndInp_t *sslEndInp)
Definition: rcSslEnd.cpp:9
rcComm_t::sock
int sock
Definition: rcConnect.h:98