Beispiel #1
0
/**
 * Accept the GSI Authentication.
 * @param sock the socket for communication.
 * @param ctx the authorization context.
 * @return the context identifier. 
 */
bool
GSISocketServer::AcceptGSIAuthentication()
{
  char *name = NULL;
  long  errorcode = 0;
  int   flags;

  time_t curtime, starttime;
  int ret, accept_status;
  bool accept_timed_out = false;
  int expected = 0;
  BIO *bio = NULL;
  char *cert_file, *user_cert, *user_key, *user_proxy;
  char *serial=NULL;

  cert_file = user_cert = user_key = user_proxy = NULL;

  if (proxy_get_filenames(0, &cert_file, &cacertdir, &user_proxy, &user_cert, &user_key) == 0) {
    (void)load_credentials(user_cert, user_key, &ucert, &own_stack, &upkey, NULL);
  }

  free(cert_file);
  free(user_cert);
  free(user_key);
  free(user_proxy);

  own_cert = ucert;
  own_key = upkey;
  ctx = SSL_CTX_new(SSLv23_method());
  SSL_CTX_load_verify_locations(ctx, NULL, cacertdir);
  SSL_CTX_use_certificate(ctx, ucert);
  SSL_CTX_use_PrivateKey(ctx,upkey);
  SSL_CTX_set_cipher_list(ctx, "ALL:!LOW:!EXP:!MD5:!MD2");    
  SSL_CTX_set_purpose(ctx, X509_PURPOSE_ANY);
  SSL_CTX_set_mode(ctx, SSL_MODE_AUTO_RETRY);
  SSL_CTX_set_verify(ctx, SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT, proxy_verify_callback);
  SSL_CTX_set_verify_depth(ctx, 100);
  SSL_CTX_set_cert_verify_callback(ctx, proxy_app_verify_callback, 0);

  if (own_stack) {
    /*
     * Certificate was a proxy with a cert. chain.
     * Add the certificates one by one to the chain.
     */
    X509_STORE_add_cert(ctx->cert_store, ucert);
    for (int i = 0; i <sk_X509_num(own_stack); ++i) {
      X509 *cert = (sk_X509_value(own_stack,i));

      if (!X509_STORE_add_cert(ctx->cert_store, cert)) {
        if (ERR_GET_REASON(ERR_peek_error()) == X509_R_CERT_ALREADY_IN_HASH_TABLE) {
          ERR_clear_error();
          continue;
        }
        else {
          SetErrorOpenSSL("Cannot add certificate to the SSL context's certificate store");
          goto err;
        }
      }
    }
  }

  flags = fcntl(newsock, F_GETFL, 0);
  (void)fcntl(newsock, F_SETFL, flags | O_NONBLOCK);

  bio = BIO_new_socket(newsock, BIO_NOCLOSE);
  (void)BIO_set_nbio(bio, 1);

  ssl = SSL_new(ctx);
  setup_SSL_proxy_handler(ssl, cacertdir);

  writeb = bio->method->bwrite;
  readb  = bio->method->bread;
  bio->method->bwrite = globusf_write;
  bio->method->bread  = globusf_read;

  SSL_set_bio(ssl, bio, bio);

  curtime = starttime = time(NULL);

  ret = accept_status = -1;
  expected = 0;

  do {

    ret = do_select(newsock, starttime, timeout, expected);
    LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Select status: %d",ret);

    curtime = time(NULL);


    if (ret == 0){

      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Select timed out.");

      if (curtime - starttime > timeout){
        accept_timed_out = true;
        break;

      }else{

        continue;
      }
      
    }
    
    if (ret > 0) {
      accept_status = SSL_accept(ssl);
      curtime = time(NULL);
      expected = errorcode = SSL_get_error(ssl, accept_status);

      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Accept status: %d",accept_status);
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Error code: %d",errorcode);
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "SSL_WANT_READ: %d, SSL_WANT_WRITE: %d",SSL_ERROR_WANT_READ, SSL_ERROR_WANT_WRITE);
    }

    if (ret < 0)
      // No more data from the select
      break;

    if (accept_status == 1)
      // SSL handshake completed
      break;

    if (timeout != -1 && (curtime - starttime > timeout)){
      // Timeout reached
      accept_timed_out = true;
      break;
    }

    if (accept_status <= 0 && ( errorcode != SSL_ERROR_WANT_READ && errorcode != SSL_ERROR_WANT_WRITE ))
      // SSL handshake error
      break;
    
  } while (true);
  
  // Error enstabilishing context
  if (accept_status != 1){

    LOGM(VARP, logh, LEV_INFO, T_PRE, "Error enstabilishing SSL context.");

    if (accept_timed_out){
      SetError("SSL Handshake failed due to server timeout!");
    }else{
      SetErrorOpenSSL("SSL Handshake error:");
    }

    goto err;
  }
  
  // Context enstabilished
  actual_cert = SSL_get_peer_certificate(ssl);
  peer_stack  = SSL_get_peer_cert_chain(ssl);

  char buffer[1000];

//  if (LogLevelMin(logh, LEV_DEBUG)) {
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate DN: %s",
           X509_NAME_oneline(X509_get_subject_name(actual_cert), buffer, 999));
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate CA: %s",
           X509_NAME_oneline(X509_get_issuer_name(actual_cert), buffer, 999));
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Stack Size: %d", sk_X509_num(peer_stack));
//  }

  peer_cert = get_real_cert(actual_cert, peer_stack);

  if (peer_cert) {
    char *name = X509_NAME_oneline(X509_get_subject_name(peer_cert), NULL, 0);
    own_subject = std::string(name);
    OPENSSL_free(name);
  }

  if (LogLevelMin(logh, LEV_DEBUG)){
    for (int i = 0; i < sk_X509_num(peer_stack); i++) {
      X509 *cert = sk_X509_value(peer_stack, i);
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate DN: %s",
           X509_NAME_oneline(X509_get_subject_name(cert), buffer, 999));
      LOGM(VARP, logh, LEV_DEBUG, T_PRE, "Certificate CA: %s",
           X509_NAME_oneline(X509_get_issuer_name(cert), buffer, 999));
    }
  }

  name = X509_NAME_oneline(X509_get_subject_name(peer_cert), NULL, 0);
  if (name)
    peer_subject = std::string(name); 
  OPENSSL_free(name);

  name = X509_NAME_oneline(X509_get_issuer_name(peer_cert), NULL, 0);
  if (name)
    peer_ca = std::string(name);
  OPENSSL_free(name);

  serial = get_peer_serial(actual_cert);
  peer_serial = std::string(serial ? serial : "");
  OPENSSL_free(serial);

  return true;

err:
  destroy_SSL_proxy_handler(ssl);
  SSL_free(ssl);
  SSL_CTX_free(ctx);

  return false;
}
Beispiel #2
0
int main(int argc, char *argv[])
{
  // default paths currently point to my test certificates
  char *m_caCertPath;
  char *m_serverCert;
  char *m_serverKey;
  char *stoparg;

  m_caCertPath= argv[1];
  fprintf(stdout,  "phase1\n");
  m_serverCert = strchr(m_caCertPath, ';');
  fprintf(stdout,  "phase2\n");
  *m_serverCert++ ='\0';
  m_serverKey  = strchr(m_serverCert, ';');
  fprintf(stdout,  "phase3\n");
  *m_serverKey++ ='\0';
  stoparg = strchr(m_serverKey, ';');
  fprintf(stdout,  "phase4\n");
  *stoparg++ = '\0';

  fprintf(stdout, "ca:%s\ncert:%s\nkey:%s\nstop:%s\n", m_caCertPath, m_serverCert, m_serverKey, stoparg);

  SSL_CTX *m_sslCtx = NULL;

  // Initializing OpenSSL
  // FIXME should this only be called once?

  OpenSSL_add_all_algorithms();
  SSLeay_add_all_algorithms();
  SSL_load_error_strings();
  ERR_load_crypto_strings();
  ERR_load_BIO_strings();
  SSL_library_init();


  m_sslCtx = SSL_CTX_new( SSLv23_method() );
  if (!m_sslCtx) {
    ERR_print_errors_fp( stdout );
    printf("error1\n");

  }

  SSL_CTX_set_options(m_sslCtx, SSL_OP_DONT_INSERT_EMPTY_FRAGMENTS);
/*   SSL_CTX_set_cipher_list(m_sslCtx, "ALL:!LOW:!EXP:!MD5:!MD2");      */
  SSL_CTX_set_purpose(m_sslCtx, X509_PURPOSE_ANY);
  /*  SSL_CTX_set_mode(m_sslCtx, SSL_MODE_AUTO_RETRY); */

  printf("test\n");
  // load server certificate
  if ( SSL_CTX_use_certificate_file( m_sslCtx,
        m_serverCert, SSL_FILETYPE_PEM ) <= 0 )
  {
    ERR_print_errors_fp( stdout );
    printf("error1\n");
  }

  // load private key
  if ( SSL_CTX_use_PrivateKey_file( m_sslCtx,
        m_serverKey, SSL_FILETYPE_PEM) <= 0 )
  {
    ERR_print_errors_fp( stdout );
    printf("error2\n");
  }

  // load trusted Certificate Authority
  if ( !SSL_CTX_load_verify_locations( m_sslCtx, 0,
        m_caCertPath ) )
  {
    ERR_print_errors_fp( stdout );
    printf("error3\n");
  }

  // require peer (client) certificate verification
  SSL_CTX_set_verify( m_sslCtx, SSL_VERIFY_PEER, 0 );
  // Set the verification depth to 1
  SSL_CTX_set_verify_depth( m_sslCtx, 100 );

  // set the verify call back to girdsite, which understands
  // proxy certificates
  SSL_CTX_set_cert_verify_callback( m_sslCtx,
      proxy_verify_callback_server, 0);

  // create new ssl structure and pass the fd to it
  SSL *m_sslCon = SSL_new( m_sslCtx );

  BIO *bio = BIO_new_accept("33334");
  if (BIO_do_accept(bio) <= 0)
    fprintf(stdout, "BIO_do_accept failed\n");
  fprintf(stdout, "now accepting\n");
  fprintf(stdout, "bio=%ld\n", bio);
  BIO_do_accept(bio);
  fprintf(stdout, "part1\n");
  BIO *client= BIO_pop(bio);
  fprintf(stdout, "part2\n");
  SSL_set_bio(m_sslCon, client, client);
  fprintf(stdout,"bio set\n");

  // initiate the handshake
  int error;
  if ( (error = SSL_accept( m_sslCon )) <= 0 ) {
    unsigned long l;
    char buf[256];
#if SSLEAY_VERSION_NUMBER  >= 0x00904100L
    const char *file;
#else
    char *file;
#endif
    char *dat;
    int line;

  /* WIN32 does not have the ERR_get_error_line_data */
  /* exported, so simulate it till it is fixed */
  /* in SSLeay-0.9.0 */

    while ( ERR_peek_error() != 0 ) {

      int i;
      ERR_STATE *es;

      es = ERR_get_state();
      i = (es->bottom+1)%ERR_NUM_ERRORS;

      if (es->err_data[i] == NULL)
        dat = (char*)"";
      else
        dat = es->err_data[i];
      if (dat) {
        l = ERR_get_error_line(&file, &line);
        //      if (debug)
        fprintf(stdout, "%s:%s,%d,%s\n", ERR_error_string(l, buf),
                file, line, dat);
        //      error += std::string(ERR_reason_error_string(l)) + ":" + std::string(ERR_func_error_string(l)) + "\n";
      }
    }
/*     fprintf(stdout, "%s\n", */
/*             ERR_reason_error_string( ERR_get_error() )); */
    fprintf(stdout, "ERROR\n");
    exit(1);
  }

  fprintf(stdout, "Handshake done!\n");
  /* connected */
  sleep(100);

  exit(0);
}