Exemplo n.º 1
0
/*
 * This function is called when an SSL connection is closed.
 */
void Curl_nss_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  if(connssl->handle) {
    /* NSS closes the socket we previously handed to it, so we must mark it
       as closed to avoid double close */
    fake_sclose(conn->sock[sockindex]);
    conn->sock[sockindex] = CURL_SOCKET_BAD;

    if((connssl->client_nickname != NULL) || (connssl->obj_clicert != NULL))
      /* A server might require different authentication based on the
       * particular path being requested by the client.  To support this
       * scenario, we must ensure that a connection will never reuse the
       * authentication data from a previous connection. */
      SSL_InvalidateSession(connssl->handle);

    if(connssl->client_nickname != NULL) {
      free(connssl->client_nickname);
      connssl->client_nickname = NULL;
    }
    /* destroy all NSS objects in order to avoid failure of NSS shutdown */
    Curl_llist_destroy(connssl->obj_list, NULL);
    connssl->obj_list = NULL;
    connssl->obj_clicert = NULL;

    PR_Close(connssl->handle);
    connssl->handle = NULL;
  }
}
Exemplo n.º 2
0
Arquivo: hash.c Projeto: B-Rich/CMake
/* return 1 on error, 0 is fine */
int
Curl_hash_init(struct curl_hash *h, int slots, curl_hash_dtor dtor)
{
    int i;

    h->dtor = dtor;
    h->size = 0;
    h->slots = slots;

    h->table = (struct curl_llist **) malloc(slots * sizeof(struct curl_llist *));
    if(h->table) {
        for (i = 0; i < slots; ++i) {
            h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
            if(!h->table[i]) {
                while(i--)
                    Curl_llist_destroy(h->table[i], NULL);
                free(h->table);
                return 1; /* failure */
            }
        }
        return 0; /* fine */
    }
    else
        return 1; /* failure */
}
Exemplo n.º 3
0
void Curl_wildcard_dtor(struct WildcardData *wc)
{
  if(!wc)
    return;

  if(wc->tmp_dtor) {
    wc->tmp_dtor(wc->tmp);
    wc->tmp_dtor = ZERO_NULL;
    wc->tmp = NULL;
  }
  DEBUGASSERT(wc->tmp == NULL);

  if(wc->filelist) {
    Curl_llist_destroy(wc->filelist, NULL);
    wc->filelist = NULL;
  }

  free(wc->path);
  wc->path = NULL;
  free(wc->pattern);
  wc->pattern = NULL;

  wc->customptr = NULL;
  wc->state = CURLWC_INIT;
}
Exemplo n.º 4
0
Arquivo: nss.c Projeto: jerywang/curl
/*
 * This function is called when an SSL connection is closed.
 */
void Curl_nss_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  if(connssl->handle) {
    /* NSS closes the socket we previously handed to it, so we must mark it
       as closed to avoid double close */
    fake_sclose(conn->sock[sockindex]);
    conn->sock[sockindex] = CURL_SOCKET_BAD;
    if(connssl->client_nickname != NULL) {
      free(connssl->client_nickname);
      connssl->client_nickname = NULL;

      /* force NSS to ask again for a client cert when connecting
       * next time to the same server */
      SSL_InvalidateSession(connssl->handle);
    }
    /* destroy all NSS objects in order to avoid failure of NSS shutdown */
    Curl_llist_destroy(connssl->obj_list, NULL);
    connssl->obj_list = NULL;
    connssl->obj_clicert = NULL;

    PR_Close(connssl->handle);
    connssl->handle = NULL;
  }
}
Exemplo n.º 5
0
/* return 1 on error, 0 is fine */
int
Curl_hash_init(struct curl_hash *h,
               int slots,
               hash_function hfunc,
               comp_function comparator,
               curl_hash_dtor dtor)
{
  int i;

  if(!slots || !hfunc || !comparator ||!dtor) {
    return 1; /* failure */
  }

  h->hash_func = hfunc;
  h->comp_func = comparator;
  h->dtor = dtor;
  h->size = 0;
  h->slots = slots;

  h->table = malloc(slots * sizeof(struct curl_llist *));
  if(h->table) {
    for(i = 0; i < slots; ++i) {
      h->table[i] = Curl_llist_alloc((curl_llist_dtor) hash_element_dtor);
      if(!h->table[i]) {
        while(i--)
          Curl_llist_destroy(h->table[i], NULL);
        free(h->table);
        return 1; /* failure */
      }
    }
    return 0; /* fine */
  }
  else
    return 1; /* failure */
}
Exemplo n.º 6
0
static void bundle_destroy(struct connectbundle *cb_ptr)
{
  if(!cb_ptr)
    return;

  Curl_llist_destroy(&cb_ptr->conn_list, NULL);

  free(cb_ptr);
}
Exemplo n.º 7
0
static void bundle_destroy(struct connectbundle *cb_ptr)
{
  if(!cb_ptr)
    return;

  if(cb_ptr->conn_list) {
    Curl_llist_destroy(cb_ptr->conn_list, NULL);
    cb_ptr->conn_list = NULL;
  }
  free(cb_ptr);
}
Exemplo n.º 8
0
Arquivo: hash.c Projeto: B-Rich/CMake
void
Curl_hash_clean(struct curl_hash *h)
{
    int i;

    for (i = 0; i < h->slots; ++i) {
        Curl_llist_destroy(h->table[i], (void *) h);
    }

    free(h->table);
}
Exemplo n.º 9
0
Arquivo: pipeline.c Projeto: 2px/curl
CURLMcode Curl_pipeline_set_server_blacklist(char **servers,
                                             struct curl_llist **list_ptr)
{
  struct curl_llist *old_list = *list_ptr;
  struct curl_llist *new_list = NULL;

  if(servers) {
    new_list = Curl_llist_alloc((curl_llist_dtor) server_blacklist_llist_dtor);
    if(!new_list)
      return CURLM_OUT_OF_MEMORY;

    /* Parse the URLs and populate the list */
    while(*servers) {
      char *server_name;

      server_name = strdup(*servers);
      if(!server_name) {
        Curl_llist_destroy(new_list, NULL);
        return CURLM_OUT_OF_MEMORY;
      }

      if(!Curl_llist_insert_next(new_list, new_list->tail, server_name)) {
        Curl_llist_destroy(new_list, NULL);
        Curl_safefree(server_name);
        return CURLM_OUT_OF_MEMORY;
      }

      servers++;
    }
  }

  /* Free the old list */
  if(old_list) {
    Curl_llist_destroy(old_list, NULL);
  }

  /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
  *list_ptr = new_list;

  return CURLM_OK;
}
Exemplo n.º 10
0
CURLMcode Curl_pipeline_set_site_blacklist(char **sites,
                                           struct curl_llist **list_ptr)
{
  struct curl_llist *old_list = *list_ptr;
  struct curl_llist *new_list = NULL;

  if(sites) {
    new_list = Curl_llist_alloc((curl_llist_dtor) site_blacklist_llist_dtor);
    if(!new_list)
      return CURLM_OUT_OF_MEMORY;

    /* Parse the URLs and populate the list */
    while(*sites) {
      char *hostname;
      char *port;
      struct site_blacklist_entry *entry;

      entry = malloc(sizeof(struct site_blacklist_entry));

      hostname = strdup(*sites);
      if(!hostname)
        return CURLM_OUT_OF_MEMORY;

      port = strchr(hostname, ':');
      if(port) {
        *port = '\0';
        port++;
        entry->port = (unsigned short)strtol(port, NULL, 10);
      }
      else {
        /* Default port number for HTTP */
        entry->port = 80;
      }

      entry->hostname = hostname;

      if(!Curl_llist_insert_next(new_list, new_list->tail, entry))
        return CURLM_OUT_OF_MEMORY;

      sites++;
    }
  }

  /* Free the old list */
  if(old_list) {
    Curl_llist_destroy(old_list, NULL);
  }

  /* This might be NULL if sites == NULL, i.e the blacklist is cleared */
  *list_ptr = new_list;

  return CURLM_OK;
}
Exemplo n.º 11
0
static CURLcode unit_setup(void)
{
  llist = Curl_llist_alloc(test_curl_llist_dtor);
  if(!llist)
    return CURLE_OUT_OF_MEMORY;
  llist_destination = Curl_llist_alloc(test_curl_llist_dtor);
  if(!llist_destination) {
      Curl_llist_destroy(llist, NULL);
      return CURLE_OUT_OF_MEMORY;
  }

  return CURLE_OK;
}
Exemplo n.º 12
0
void
Curl_hash_clean(struct curl_hash *h)
{
  int i;

  for(i = 0; i < h->slots; ++i) {
    Curl_llist_destroy(h->table[i], (void *) h);
    h->table[i] = NULL;
  }

  Curl_safefree(h->table);
  h->size = 0;
  h->slots = 0;
}
Exemplo n.º 13
0
Arquivo: nss.c Projeto: zcopley/curl
/*
 * This function is called when an SSL connection is closed.
 */
void Curl_nss_close(struct connectdata *conn, int sockindex)
{
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];

  if(connssl->handle) {
    PR_Close(connssl->handle);

    /* NSS closes the socket we previously handed to it, so we must mark it
       as closed to avoid double close */
    fake_sclose(conn->sock[sockindex]);
    conn->sock[sockindex] = CURL_SOCKET_BAD;
    if(connssl->client_nickname != NULL) {
      free(connssl->client_nickname);
      connssl->client_nickname = NULL;
    }
#ifdef HAVE_PK11_CREATEGENERICOBJECT
    /* destroy all NSS objects in order to avoid failure of NSS shutdown */
    Curl_llist_destroy(connssl->obj_list, NULL);
#endif
    connssl->handle = NULL;
  }
}
Exemplo n.º 14
0
CURLcode Curl_nss_connect(struct connectdata *conn, int sockindex)
{
  PRErrorCode err = 0;
  PRFileDesc *model = NULL;
  PRBool ssl2 = PR_FALSE;
  PRBool ssl3 = PR_FALSE;
  PRBool tlsv1 = PR_FALSE;
  PRBool ssl_no_cache;
  PRBool ssl_cbc_random_iv;
  struct SessionHandle *data = conn->data;
  curl_socket_t sockfd = conn->sock[sockindex];
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  CURLcode curlerr;
  const int *cipher_to_enable;
  PRSocketOptionData sock_opt;
  long time_left;
  PRUint32 timeout;

  if(connssl->state == ssl_connection_complete)
    return CURLE_OK;

  connssl->data = data;

  /* list of all NSS objects we need to destroy in Curl_nss_close() */
  connssl->obj_list = Curl_llist_alloc(nss_destroy_object);
  if(!connssl->obj_list)
    return CURLE_OUT_OF_MEMORY;

  /* FIXME. NSS doesn't support multiple databases open at the same time. */
  PR_Lock(nss_initlock);
  curlerr = nss_init(conn->data);
  if(CURLE_OK != curlerr) {
    PR_Unlock(nss_initlock);
    goto error;
  }

  curlerr = CURLE_SSL_CONNECT_ERROR;

  if(!mod) {
    char *configstring = aprintf("library=%s name=PEM", pem_library);
    if(!configstring) {
      PR_Unlock(nss_initlock);
      goto error;
    }
    mod = SECMOD_LoadUserModule(configstring, NULL, PR_FALSE);
    free(configstring);

    if(!mod || !mod->loaded) {
      if(mod) {
        SECMOD_DestroyModule(mod);
        mod = NULL;
      }
      infof(data, "WARNING: failed to load NSS PEM library %s. Using "
            "OpenSSL PEM certificates will not work.\n", pem_library);
    }
  }

  PK11_SetPasswordFunc(nss_get_password);
  PR_Unlock(nss_initlock);

  model = PR_NewTCPSocket();
  if(!model)
    goto error;
  model = SSL_ImportFD(NULL, model);

  /* make the socket nonblocking */
  sock_opt.option = PR_SockOpt_Nonblocking;
  sock_opt.value.non_blocking = PR_TRUE;
  if(PR_SetSocketOption(model, &sock_opt) != PR_SUCCESS)
    goto error;

  if(SSL_OptionSet(model, SSL_SECURITY, PR_TRUE) != SECSuccess)
    goto error;
  if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_SERVER, PR_FALSE) != SECSuccess)
    goto error;
  if(SSL_OptionSet(model, SSL_HANDSHAKE_AS_CLIENT, PR_TRUE) != SECSuccess)
    goto error;

  /* do not use SSL cache if we are not going to verify peer */
  ssl_no_cache = (data->set.ssl.verifypeer) ? PR_FALSE : PR_TRUE;
  if(SSL_OptionSet(model, SSL_NO_CACHE, ssl_no_cache) != SECSuccess)
    goto error;

  switch (data->set.ssl.version) {
  default:
  case CURL_SSLVERSION_DEFAULT:
    ssl3 = PR_TRUE;
    if(data->state.ssl_connect_retry)
      infof(data, "TLS disabled due to previous handshake failure\n");
    else
      tlsv1 = PR_TRUE;
    break;
  case CURL_SSLVERSION_TLSv1:
    tlsv1 = PR_TRUE;
    break;
  case CURL_SSLVERSION_SSLv2:
    ssl2 = PR_TRUE;
    break;
  case CURL_SSLVERSION_SSLv3:
    ssl3 = PR_TRUE;
    break;
  }

  if(SSL_OptionSet(model, SSL_ENABLE_SSL2, ssl2) != SECSuccess)
    goto error;
  if(SSL_OptionSet(model, SSL_ENABLE_SSL3, ssl3) != SECSuccess)
    goto error;
  if(SSL_OptionSet(model, SSL_ENABLE_TLS, tlsv1) != SECSuccess)
    goto error;

  if(SSL_OptionSet(model, SSL_V2_COMPATIBLE_HELLO, ssl2) != SECSuccess)
    goto error;

  ssl_cbc_random_iv = !data->set.ssl_enable_beast;
#ifdef SSL_CBC_RANDOM_IV
  /* unless the user explicitly asks to allow the protocol vulnerability, we
     use the work-around */
  if(SSL_OptionSet(model, SSL_CBC_RANDOM_IV, ssl_cbc_random_iv) != SECSuccess)
    infof(data, "warning: failed to set SSL_CBC_RANDOM_IV = %d\n",
          ssl_cbc_random_iv);
#else
  if(ssl_cbc_random_iv)
    infof(data, "warning: support for SSL_CBC_RANDOM_IV not compiled in\n");
#endif

  /* reset the flag to avoid an infinite loop */
  data->state.ssl_connect_retry = FALSE;

  /* enable all ciphers from enable_ciphers_by_default */
  cipher_to_enable = enable_ciphers_by_default;
  while(SSL_NULL_WITH_NULL_NULL != *cipher_to_enable) {
    if(SSL_CipherPrefSet(model, *cipher_to_enable, PR_TRUE) != SECSuccess) {
      curlerr = CURLE_SSL_CIPHER;
      goto error;
    }
    cipher_to_enable++;
  }

  if(data->set.ssl.cipher_list) {
    if(set_ciphers(data, model, data->set.ssl.cipher_list) != SECSuccess) {
      curlerr = CURLE_SSL_CIPHER;
      goto error;
    }
  }

  if(!data->set.ssl.verifypeer && data->set.ssl.verifyhost)
    infof(data, "warning: ignoring value of ssl.verifyhost\n");

  /* bypass the default SSL_AuthCertificate() hook in case we do not want to
   * verify peer */
  if(SSL_AuthCertificateHook(model, nss_auth_cert_hook, conn) != SECSuccess)
    goto error;

  data->set.ssl.certverifyresult=0; /* not checked yet */
  if(SSL_BadCertHook(model, BadCertHandler, conn) != SECSuccess)
    goto error;

  if(SSL_HandshakeCallback(model, HandshakeCallback, NULL) != SECSuccess)
    goto error;

  if(data->set.ssl.verifypeer) {
    const CURLcode rv = nss_load_ca_certificates(conn, sockindex);
    if(CURLE_OK != rv) {
      curlerr = rv;
      goto error;
    }
  }

  if(data->set.ssl.CRLfile) {
    if(SECSuccess != nss_load_crl(data->set.ssl.CRLfile)) {
      curlerr = CURLE_SSL_CRL_BADFILE;
      goto error;
    }
    infof(data,
          "  CRLfile: %s\n",
          data->set.ssl.CRLfile ? data->set.ssl.CRLfile : "none");
  }

  if(data->set.str[STRING_CERT]) {
    char *nickname = dup_nickname(data, STRING_CERT);
    if(nickname) {
      /* we are not going to use libnsspem.so to read the client cert */
      connssl->obj_clicert = NULL;
    }
    else {
      CURLcode rv = cert_stuff(conn, sockindex, data->set.str[STRING_CERT],
                               data->set.str[STRING_KEY]);
      if(CURLE_OK != rv) {
        /* failf() is already done in cert_stuff() */
        curlerr = rv;
        goto error;
      }
    }

    /* store the nickname for SelectClientCert() called during handshake */
    connssl->client_nickname = nickname;
  }
  else
    connssl->client_nickname = NULL;

  if(SSL_GetClientAuthDataHook(model, SelectClientCert,
                               (void *)connssl) != SECSuccess) {
    curlerr = CURLE_SSL_CERTPROBLEM;
    goto error;
  }

  /* Import our model socket  onto the existing file descriptor */
  connssl->handle = PR_ImportTCPSocket(sockfd);
  connssl->handle = SSL_ImportFD(model, connssl->handle);
  if(!connssl->handle)
    goto error;

  PR_Close(model); /* We don't need this any more */
  model = NULL;

  /* This is the password associated with the cert that we're using */
  if(data->set.str[STRING_KEY_PASSWD]) {
    SSL_SetPKCS11PinArg(connssl->handle, data->set.str[STRING_KEY_PASSWD]);
  }

  /* Force handshake on next I/O */
  SSL_ResetHandshake(connssl->handle, /* asServer */ PR_FALSE);

  SSL_SetURL(connssl->handle, conn->host.name);

  /* check timeout situation */
  time_left = Curl_timeleft(data, NULL, TRUE);
  if(time_left < 0L) {
    failf(data, "timed out before SSL handshake");
    curlerr = CURLE_OPERATION_TIMEDOUT;
    goto error;
  }
  timeout = PR_MillisecondsToInterval((PRUint32) time_left);

  /* Force the handshake now */
  if(SSL_ForceHandshakeWithTimeout(connssl->handle, timeout) != SECSuccess) {
    if(conn->data->set.ssl.certverifyresult == SSL_ERROR_BAD_CERT_DOMAIN)
      curlerr = CURLE_PEER_FAILED_VERIFICATION;
    else if(conn->data->set.ssl.certverifyresult!=0)
      curlerr = CURLE_SSL_CACERT;
    goto error;
  }

  connssl->state = ssl_connection_complete;
  conn->recv[sockindex] = nss_recv;
  conn->send[sockindex] = nss_send;

  display_conn_info(conn, connssl->handle);

  if(data->set.str[STRING_SSL_ISSUERCERT]) {
    SECStatus ret = SECFailure;
    char *nickname = dup_nickname(data, STRING_SSL_ISSUERCERT);
    if(nickname) {
      /* we support only nicknames in case of STRING_SSL_ISSUERCERT for now */
      ret = check_issuer_cert(connssl->handle, nickname);
      free(nickname);
    }

    if(SECFailure == ret) {
      infof(data,"SSL certificate issuer check failed\n");
      curlerr = CURLE_SSL_ISSUER_ERROR;
      goto error;
    }
    else {
      infof(data, "SSL certificate issuer check ok\n");
    }
  }

  return CURLE_OK;

  error:
  /* reset the flag to avoid an infinite loop */
  data->state.ssl_connect_retry = FALSE;

  if(is_nss_error(curlerr)) {
    /* read NSPR error code */
    err = PR_GetError();
    if(is_cc_error(err))
      curlerr = CURLE_SSL_CERTPROBLEM;

    /* print the error number and error string */
    infof(data, "NSS error %d (%s)\n", err, nss_error_to_name(err));

    /* print a human-readable message describing the error if available */
    nss_print_error_message(data, err);
  }

  if(model)
    PR_Close(model);

    /* cleanup on connection failure */
    Curl_llist_destroy(connssl->obj_list, NULL);
    connssl->obj_list = NULL;

  if(ssl3 && tlsv1 && isTLSIntoleranceError(err)) {
    /* schedule reconnect through Curl_retry_request() */
    data->state.ssl_connect_retry = TRUE;
    infof(data, "Error in TLS handshake, trying SSLv3...\n");
    return CURLE_OK;
  }

  return curlerr;
}
Exemplo n.º 15
0
static void unit_stop(void)
{
  Curl_llist_destroy(llist, NULL);
  Curl_llist_destroy(llist_destination, NULL);
}