text: /*------------------------------------------------------------------
   * us902.c - Unit Tests for User Story 902 - Server simple reenroll
   *
   * August, 2013
   *
   * Copyright (c) 2013, 2016 by cisco Systems, Inc.
   * All rights reserved.
   *------------------------------------------------------------------
   */
  #include <stdio.h>
  #ifndef WIN32
  #include <unistd.h>
  #endif
  #include <est.h>
  #include <curl/curl.h>
  #include "curl_utils.h"
  #include "test_utils.h"
  #include "st_server.h"
  #include <openssl/ssl.h>
  
  #ifdef HAVE_CUNIT
  #include "CUnit/Basic.h"
  #include "CUnit/Automated.h"
  #endif
  
  #ifndef WIN32
  static char test5_outfile[FILENAME_MAX] = "US902/test5.hdr";
  #define US902_CACERTS       "CA/estCA/cacert.crt"
  #define US902_TRUSTED_CERT  "CA/trustedcerts.crt"
  #define US902_SERVER_CERT_AND_KEY "CA/estCA/private/estservercertandkey.pem"
  #else
  static char test5_outfile[FILENAME_MAX] = "US902\\test5.hdr";
  #define US902_CACERTS       "CA\\estCA\\cacert.crt"
  #define US902_TRUSTED_CERT  "CA\\trustedcerts.crt"
  #define US902_SERVER_CERT_AND_KEY "CA\\estCA\\private\\estservercertandkey.pem"
  #endif
  static unsigned char *cacerts = NULL;
  static int cacerts_len = 0;
  
  #define US902_RETRY_INTERVAL    3600
  #define US902_TCP_PORT      29001
  
  /*
   * The following CSR was generated using the following openssl command and then
   * using cat on the rsa.req file:
   *
   * openssl req -newkey rsa:2048 -keyout rsakey.pem -keyform PEM -out rsa.req -outform PEM
   */
  #define US902_PKCS10_RSA2048 "MIICvTCCAaUCAQAweDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5DMQwwCgYDVQQH\nDANSVFAxEjAQBgNVBAoMCVJTQWNlcnRjbzEMMAoGA1UECwwDcnNhMRAwDgYDVQQD\nDAdyc2EgZG9lMRowGAYJKoZIhvcNAQkBFgtyc2FAZG9lLmNvbTCCASIwDQYJKoZI\nhvcNAQEBBQADggEPADCCAQoCggEBAN6pCTBrK7T029Bganq0QHXHyNL8opvxc7JY\nXaQz39R3J9BoBE72XZ0QXsBtUEYGNhHOLaISASNzs2ZKWpvMHJWmPYNt39OCi48Y\nFOgLDbAn83mAOKSfcMLbibCcsh4HOlhaaFrWskRTAsew16MUOzFu6vBkw/AhI82J\nKPYws0dYOxuWFIgE1HL+m/gplbzq7FrBIdrqkNL+ddgyXoDd5NuLMJGDAK7vB1Ww\n9/Baw/6Ai9V5psye1v8fWDr6HW2gg9XnVtMwB4pCg1rl1lSYstumTGYbM6cxJywe\nLuMnDjj1ZwDsZ1wIXaBAXZaxEIS/rXOX0HnZMTefxY/gpFk1Kv0CAwEAAaAAMA0G\nCSqGSIb3DQEBBQUAA4IBAQB6rIwNjE8l8jFKR1hQ/qeSvee/bAQa58RufZ4USKuK\nlsih7UCf8bkQvgljnhscQuczIbnJzeqEPqSdnomFW6CvMc/ah+QfX87FGYxJgpwF\nutnUifjDiZhrWgf/jNNbtHrkecw/Zex4sZ/HC127jtE3cyEkDsrA1oBxYRCq93tC\nW2q9PLVmLlyjcZcS1KHVD2nya79kfS0YGMocsw1GelVL2iz/ocayAS5GB9Y2sEBw\nRkCaYZw6vhj5qjpCUzJ3E8Cl3VD4Kpi3j3bZGDJA9mdmd8j5ZyPY56eAuxarWssD\nciUM/h6E99w3tmrUZbLljkjJ7pBXRnontgm5WZmQFH4X"
  
  /*
   * The following CSR was generated using the following openssl command and then
   * using cat on the ec.req file:
   *
   * openssl req -newkey ec:256parms -keyout eckey.pem -keyform PEM -out ec.req -outform PEM
   */
  #define US902_PKCS10_DSA1024 "MIICfjCCAj0CAQAwfDELMAkGA1UEBhMCVVMxCzAJBgNVBAgMAk5DMQwwCgYDVQQH\nDANSVFAxEzARBgNVBAoMCkRTQUNvbXBhbnkxDzANBgNVBAsMBkRTQW9yZzEQMA4G\nA1UEAwwHZHNhIGRvZTEaMBgGCSqGSIb3DQEJARYLZHNhQGRvZS5jb20wggG2MIIB\nKwYHKoZIzjgEATCCAR4CgYEAqIfbyk7rEAaULIPB1GcHHc0ctx6g0dhBfdUdOPNG\nBSE+TP5UF5lw8Qm6oCXstU3nYEJalmMvkjFwbgvBws8aJBnj09dDDn8spKEGcG0M\nZpqdMys6+b4QJjq5YAxEaATVY/1L/rBgGGm1EFDhc/6Ezm2T3CGeQklwo5aBZQCc\naIsCFQDC1olBFuE+phOhjXAwEE5EPJkRJwKBgD+vZ+tLCTjBzVFNjAO8X/SMamwW\noraNfdyZ+ZCEAmYI/D4838nCGAjVRQyDb1q5akkLyxoJX1YV7gNbaBNUys3waqdu\nso1HtuEur2cbhU5iOeKBWpj6MIWlPdD3uCRu4uiBF9XBiANaRID8CT2kchhwy4Ok\nFfQMuYOz4eBhMQqmA4GEAAKBgDuwR7H3U4CfuQjWeTtrI50M1TxhlVZ3TonRtVIx\nEHpuXxAouxATVkthJtaCBKc0EHii1bE/kgNUgGX/ZdFjBUb/XfpkYsRT3QRLF0+s\nPZGY/0TovO9pKjqiw0C10leNKFbEVdlXYtAkjXUbHmyNog3195/t7oKXHMT1A/5p\nhUCRoAAwCQYHKoZIzjgEAwMwADAtAhUAhPCqQG3gKUUPKdwBNCmZfzWDqjsCFAh0\nzn9HujlXNaTA1OhjmPmcJSxT"
  
  /*
   * The following CSR was generated using the following openssl command and then
   * using cat on the dsa.req file:
   *
   * openssl req -newkey dsa:dsaparms -keyout dsakey.pem -keyform PEM -out dsa.req -outform PEM
   */
  #define US902_PKCS10_ECDSA256 "MIIBMTCB2gIBADB4MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTkMxDDAKBgNVBAcM\nA1JUUDESMBAGA1UECgwJRUNDb21wYW55MQ4wDAYDVQQLDAVFQ29yZzEPMA0GA1UE\nAwwGRUMgZG9lMRkwFwYJKoZIhvcNAQkBFgplY0Bkb2UuY29tMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAEO1uszCKdXNFzygNLNeS8azQKod1516GT9qdDddt9iJN4\nLpBTnv+7K7+tji5kts1kWSYyvqLxvnq8Q/TU1iQJ56AAMAkGByqGSM49BAEDRwAw\nRAIgP6qda+0TEKZFPopgUfwFMRsxcNmuQUe2yuz16460/SQCIBfLvmuMeyYOqbbD\nX0Ifde9yzkROVBCEPvK0hcU5KsTO"
  
  #define US902_PKCS10_CORRUPT "MIIBMTCB2gIBADB4MQswCQYDVQQGEwJVUzELMAkGA1UECAwCTkMxDDAKBgNVBAcM\nA1JUUDESMBAGA1UECgwJRUNDb21wYW55MQ4wDAYDVQQLDAVFQ39yZzEPMA0GA1UE\nAwwGRUMgZG9lMRkwFwYJKoZIhvcNAQkBFgplY0Bkb2UuY29tMFkwEwYHKoZIzj0C\nAQYIKoZIzj0DAQcDQgAEO1uszCKdXNFzygNLNeS8azQKod1516GT9qdDddt9iJN4\nLpBTnv+7K7+tji5kts1kWSYyvqLxvnq8Q/TU1iQJ56AAMAkGByqGSM49BAEDRwAw\nRAIgP6qda+0TEKZFPopgUfwFMRsxcNmuQUe2yuz16460/SQCIBfLvmuMeyYOqbbD\nX0Ifde9yzkROVBCEPvK0hcU5KsTO"
  
  #define US902_ENROLL_URL_BA "https://127.0.0.1:29001/.well-known/est/simplereenroll"
  #define US902_PKCS10_CT     "Content-Type: application/pkcs10" 
  #define US902_UIDPWD_GOOD   "estuser:estpwd"
  
  static FILE *outfile;
  static size_t write_func (void *ptr, size_t size, size_t nmemb, void *userdata)
  {
      size_t written;
      written = fwrite(ptr, size, nmemb, outfile);
      return written;
  }
  
  static void us902_clean (void)
  {
  }
  
  static int us902_start_server (int manual_enroll, int nid)
  {
      int rv;
  
      rv = st_start(US902_TCP_PORT,
      US902_SERVER_CERT_AND_KEY,
      US902_SERVER_CERT_AND_KEY, "US902 test realm",
      US902_CACERTS,
      US902_TRUSTED_CERT, "CA/estExampleCA.cnf", manual_enroll, 0, nid);
      return rv;
  }
  
  /*
   * This routine is called when CUnit initializes this test
   * suite.  This can be used to allocate data or open any
   * resources required for all the test cases.
   */
  static int us902_init_suite (void)
  {
      int rv;
  
      est_init_logger(EST_LOG_LVL_INFO, NULL);
  
      /*
       * Read in the CA certificates
       */
      cacerts_len = read_binary_file(US902_CACERTS, &cacerts);
      if (cacerts_len <= 0) {
          return 1;
      }
  
      us902_clean();
  
      /*
       * Start an instance of the EST server with
       * automatic enrollment enabled.
       */
      rv = us902_start_server(0, 0);
  
      return rv;
  }
  
  /*
   * This routine is called when CUnit uninitializes this test
   * suite.  This can be used to deallocate data or close any
   * resources that were used for the test cases.
   */
  static int us902_destory_suite (void)
  {
      st_stop();
      free(cacerts);
      return 0;
  }
  
  /*
   * Simple reenroll - RSA 2048
   *
   * This test case uses libcurl to test simple
   * enrollment of a 2048 bit RSA CSR.  HTTP Basic
   * authentication is used.
   */
  static void us902_test1 (void)
  {
      long rv;
  
      LOG_FUNC_NM
      ;
  
      rv = curl_http_post(US902_ENROLL_URL_BA, US902_PKCS10_CT,
      US902_PKCS10_RSA2048,
      US902_UIDPWD_GOOD, US902_CACERTS, CURLAUTH_BASIC, NULL, NULL, NULL);
      /*
       * Since we passed in a valid userID/password,
       * we expect the server to respond with 200
       */
      CU_ASSERT(rv == 200);
  }
  
  /*
   * Simple reenroll - EC prime 256
   *
   * This test case uses libcurl to test simple
   * enrollment of a 256 bit EC CSR.  HTTP Basic
   * authentication is used.
   */
  static void us902_test2 (void)
  {
      long rv;
  
      LOG_FUNC_NM
      ;
  
      rv = curl_http_post(US902_ENROLL_URL_BA, US902_PKCS10_CT,
      US902_PKCS10_ECDSA256,
      US902_UIDPWD_GOOD, US902_CACERTS, CURLAUTH_BASIC, NULL, NULL, NULL);
      /*
       * Since we passed in a valid userID/password,
       * we expect the server to respond with 200
       */
      CU_ASSERT(rv == 200);
  }
  
  /*
   * Simple reenroll - DSA prime 1024
   *
   * This test case uses libcurl to test simple
   * enrollment of a 1024 bit DSA CSR.  HTTP Basic
   * authentication is used.
   */
  static void us902_test3 (void)
  {
      long rv;
  
      LOG_FUNC_NM
      ;
  
      rv = curl_http_post(US902_ENROLL_URL_BA, US902_PKCS10_CT,
      US902_PKCS10_DSA1024,
      US902_UIDPWD_GOOD, US902_CACERTS, CURLAUTH_BASIC, NULL, NULL, NULL);
      /*
       * Since we passed in a valid userID/password,
       * we expect the server to respond with 200
       */
      CU_ASSERT(rv == 200);
  }
  
  /*
   * Simple reenroll - Corrupted PKCS10
   *
   * This test case uses libcurl to test simple
   * enrollment using a corrupted CSR.  HTTP Basic
   * authentication is used.
   */
  static void us902_test4 (void)
  {
      long rv;
  
      LOG_FUNC_NM
      ;
  
      rv = curl_http_post(US902_ENROLL_URL_BA, US902_PKCS10_CT,
      US902_PKCS10_CORRUPT,
      US902_UIDPWD_GOOD, US902_CACERTS, CURLAUTH_BASIC, NULL, NULL, NULL);
      /*
       * Since the CSR is not valid, the server should
       * respond with a 400.
       */
      CU_ASSERT(rv == 400);
  }
  
  /*
   * Simple reenroll - manual enrollment
   *
   * This test case verifies the server is
   * sending the appropriate retry-after response.
   */
  static void us902_test5 (void)
  {
      long rv;
  
      LOG_FUNC_NM
      ;
  
      /* Stop the EST server */
      st_stop();
  
      /* Restart the server with manual enrollment enabled */
      us902_start_server(1, 0);
  
      outfile = fopen(test5_outfile, "w");
      rv = curl_http_post(US902_ENROLL_URL_BA, US902_PKCS10_CT,
      US902_PKCS10_RSA2048,
      US902_UIDPWD_GOOD, US902_CACERTS, CURLAUTH_BASIC, NULL, NULL, &write_func);
      fclose(outfile);
  
      /*
       * Since the server hasn't seen this CSR in the past,
       * it should respond with a retry-after 202 response.
       */
      CU_ASSERT(rv == 202);
  
      /*
       * Verify the retry-after value
       */
      rv = grep(test5_outfile, "Retry-After: 3600");
      CU_ASSERT(rv == 0);
  
      /*
       * We will avoid waiting the full retry period since we're
       * only simulating manual enrollment.  Wait a second and then
       * try to enroll the cert again.
       */
      SLEEP(1);
      rv = curl_http_post(US902_ENROLL_URL_BA, US902_PKCS10_CT,
      US902_PKCS10_RSA2048,
      US902_UIDPWD_GOOD, US902_CACERTS, CURLAUTH_BASIC, NULL, NULL, NULL);
  
      /*
       * This enrollment request should succeed this time
       * Our simulated manual enrollment will automatically
       * enroll on the second attempt.
       */
      CU_ASSERT(rv == 200);
  
      /* Stop the EST server */
      st_stop();
  
      /* Restart the server with manual enrollment disabled */
      us902_start_server(0, 0);
  }
  
  /* The main() function for setting up and running the tests.
   * Returns a CUE_SUCCESS on successful running, another
   * CUnit error code on failure.
   */
  int us902_add_suite (void)
  {
  #ifdef HAVE_CUNIT
      CU_pSuite pSuite = NULL;
  
      /* add a suite to the registry */
      pSuite = CU_add_suite("us902_srv_simpreenroll",
              us902_init_suite,
              us902_destory_suite);
      if (NULL == pSuite) {
          CU_cleanup_registry();
          return CU_get_error();
      }
  
      /* add the tests to the suite */
      if ((NULL == CU_add_test(pSuite, "ReEnroll RSA cert", us902_test1)) ||
          (NULL == CU_add_test(pSuite, "ReEnroll ECDSA cert", us902_test2)) ||
          (NULL == CU_add_test(pSuite, "ReEnroll DSA cert", us902_test3)) ||
          (NULL == CU_add_test(pSuite, "ReEnroll corrupted ECDSA cert", us902_test4)) ||
          (NULL == CU_add_test(pSuite, "ReEnroll retry-after manual approval ", us902_test5)))
      {
          CU_cleanup_registry();
          return CU_get_error();
      }
  
      return CUE_SUCCESS;
  #endif
  }
  
  