Commit message: None
CVE: CVE-2014-10375
CWE: CWE-189
Vulnerability description: handle_messages in eXtl_tls.c in eXosip before 5.0.0 mishandles a negative value in a content-length header.

Project: savannah

_eXosip_is_public_address (const char *c_address)
{
  return (0 != strncmp (c_address, "192.168", 7)
          && 0 != strncmp (c_address, "10.", 3)
          && 0 != strncmp (c_address, "172.16.", 7)
          && 0 != strncmp (c_address, "172.17.", 7)
          && 0 != strncmp (c_address, "172.18.", 7)
          && 0 != strncmp (c_address, "172.19.", 7)
          && 0 != strncmp (c_address, "172.20.", 7)
          && 0 != strncmp (c_address, "172.21.", 7)
          && 0 != strncmp (c_address, "172.22.", 7)
          && 0 != strncmp (c_address, "172.23.", 7)
          && 0 != strncmp (c_address, "172.24.", 7)
          && 0 != strncmp (c_address, "172.25.", 7)
          && 0 != strncmp (c_address, "172.26.", 7)
          && 0 != strncmp (c_address, "172.27.", 7)
          && 0 != strncmp (c_address, "172.28.", 7)
          && 0 != strncmp (c_address, "172.29.", 7)
          && 0 != strncmp (c_address, "172.30.", 7)
          && 0 != strncmp (c_address, "172.31.", 7)
          && 0 != strncmp (c_address, "169.254", 7));
}

Project: savannah

eXosip_enable_ipv6 (int _ipv6_enable)
{
  /* obsolete, use:
     eXosip_set_option(excontext, EXOSIP_OPT_ENABLE_IPV6, &val);
   */
}

Project: savannah

eXosip_find_free_port (struct eXosip_t *excontext, int free_port, int transport)
{
  int res1;
  int res2;
  struct addrinfo *addrinfo_rtp = NULL;
  struct addrinfo *curinfo_rtp;
  struct addrinfo *addrinfo_rtcp = NULL;
  struct addrinfo *curinfo_rtcp;
  int sock;
  int count;

  for (count = 0; count < 8; count++) {
    if (excontext->ipv6_enable == 0)
      res1 = _eXosip_get_addrinfo (excontext, &addrinfo_rtp, "0.0.0.0", free_port + count * 2, transport);
    else
      res1 = _eXosip_get_addrinfo (excontext, &addrinfo_rtp, "::", free_port + count * 2, transport);
    if (res1 != 0)
      return res1;
    if (excontext->ipv6_enable == 0)
      res2 = _eXosip_get_addrinfo (excontext, &addrinfo_rtcp, "0.0.0.0", free_port + count * 2 + 1, transport);
    else
      res2 = _eXosip_get_addrinfo (excontext, &addrinfo_rtcp, "::", free_port + count * 2 + 1, transport);
    if (res2 != 0) {
      _eXosip_freeaddrinfo (addrinfo_rtp);
      return res2;
    }

    sock = -1;
    for (curinfo_rtp = addrinfo_rtp; curinfo_rtp; curinfo_rtp = curinfo_rtp->ai_next) {
      if (curinfo_rtp->ai_protocol && curinfo_rtp->ai_protocol != transport) {
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo_rtp->ai_protocol));
        continue;
      }

      sock = (int) socket (curinfo_rtp->ai_family, curinfo_rtp->ai_socktype, curinfo_rtp->ai_protocol);
      if (sock < 0) {
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket!\n"));
        continue;
      }

      if (curinfo_rtp->ai_family == AF_INET6) {
#ifdef IPV6_V6ONLY
        if (setsockopt_ipv6only (sock)) {
          close (sock);
          sock = -1;
          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option!\n"));
          continue;
        }
#endif /* IPV6_V6ONLY */
      }

      res1 = bind (sock, curinfo_rtp->ai_addr, curinfo_rtp->ai_addrlen);
      if (res1 < 0) {
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "eXosip: Cannot bind socket node: 0.0.0.0 family:%d\n", curinfo_rtp->ai_family));
        close (sock);
        sock = -1;
        continue;
      }
      break;
    }

    _eXosip_freeaddrinfo (addrinfo_rtp);

    if (sock == -1) {
      _eXosip_freeaddrinfo (addrinfo_rtcp);
      continue;
    }

    close (sock);
    sock = -1;
    for (curinfo_rtcp = addrinfo_rtcp; curinfo_rtcp; curinfo_rtcp = curinfo_rtcp->ai_next) {
      if (curinfo_rtcp->ai_protocol && curinfo_rtcp->ai_protocol != transport) {
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo_rtcp->ai_protocol));
        continue;
      }

      sock = (int) socket (curinfo_rtcp->ai_family, curinfo_rtcp->ai_socktype, curinfo_rtcp->ai_protocol);
      if (sock < 0) {
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket!\n"));
        continue;
      }

      if (curinfo_rtcp->ai_family == AF_INET6) {
#ifdef IPV6_V6ONLY
        if (setsockopt_ipv6only (sock)) {
          close (sock);
          sock = -1;
          OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option!\n"));
          continue;
        }
#endif /* IPV6_V6ONLY */
      }

      res1 = bind (sock, curinfo_rtcp->ai_addr, curinfo_rtcp->ai_addrlen);
      if (res1 < 0) {
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "eXosip: Cannot bind socket node: 0.0.0.0 family:%d\n", curinfo_rtp->ai_family));
        close (sock);
        sock = -1;
        continue;
      }
      break;
    }

    _eXosip_freeaddrinfo (addrinfo_rtcp);

    /* the pair must be free */
    if (sock == -1)
      continue;

    close (sock);
    sock = -1;
    return free_port + count * 2;
  }

  /* just get a free port */
  if (excontext->ipv6_enable == 0)
    res1 = _eXosip_get_addrinfo (excontext, &addrinfo_rtp, "0.0.0.0", 0, transport);
  else
    res1 = _eXosip_get_addrinfo (excontext, &addrinfo_rtp, "::", 0, transport);

  if (res1)
    return res1;

  sock = -1;
  for (curinfo_rtp = addrinfo_rtp; curinfo_rtp; curinfo_rtp = curinfo_rtp->ai_next) {
    socklen_t len;
    struct sockaddr_storage ai_addr;

    if (curinfo_rtp->ai_protocol && curinfo_rtp->ai_protocol != transport) {
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO3, NULL, "eXosip: Skipping protocol %d\n", curinfo_rtp->ai_protocol));
      continue;
    }

    sock = (int) socket (curinfo_rtp->ai_family, curinfo_rtp->ai_socktype, curinfo_rtp->ai_protocol);
    if (sock < 0) {
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot create socket!\n"));
      continue;
    }

    if (curinfo_rtp->ai_family == AF_INET6) {
#ifdef IPV6_V6ONLY
      if (setsockopt_ipv6only (sock)) {
        close (sock);
        sock = -1;
        OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: Cannot set socket option!\n"));
        continue;
      }
#endif /* IPV6_V6ONLY */
    }

    res1 = bind (sock, curinfo_rtp->ai_addr, curinfo_rtp->ai_addrlen);
    if (res1 < 0) {
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "eXosip: Cannot bind socket node: 0.0.0.0 family:%d\n", curinfo_rtp->ai_family));
      close (sock);
      sock = -1;
      continue;
    }

    len = sizeof (ai_addr);
    res1 = getsockname (sock, (struct sockaddr *) &ai_addr, &len);
    if (res1 != 0) {
      close (sock);
      sock = -1;
      continue;
    }

    close (sock);
    sock = -1;
    _eXosip_freeaddrinfo (addrinfo_rtp);

    if (curinfo_rtp->ai_family == AF_INET)
      return ntohs (((struct sockaddr_in *) &ai_addr)->sin_port);
    else
      return ntohs (((struct sockaddr_in6 *) &ai_addr)->sin6_port);
  }

  _eXosip_freeaddrinfo (addrinfo_rtp);

  if (sock != -1) {
    close (sock);
    sock = -1;
  }

  return OSIP_UNDEFINED_ERROR;
}

Project: savannah

eXosip_get_version (void)
{
  return EXOSIP_VERSION;
}

Project: savannah

eXosip_guess_localip (struct eXosip_t *excontext, int family, char *address, int size)
{
  return _eXosip_guess_ip_for_via (excontext, family, address, size);
}

Project: savannah

eXosip_malloc (void)
{
  struct eXosip_t *ptr = (struct eXosip_t *) osip_malloc (sizeof (eXosip_t));

  if (ptr)
    memset (ptr, 0, sizeof (eXosip_t));
  return ptr;
}

Project: savannah

eXosip_masquerade_contact (struct eXosip_t *excontext, const char *public_address, int port)
{
  if (excontext->eXtl_transport.tl_masquerade_contact == NULL) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "no transport protocol selected!\n"));
    if (public_address == NULL || public_address[0] == '\0') {
      memset (excontext->udp_firewall_ip, '\0', sizeof (excontext->udp_firewall_ip));
      memset (excontext->udp_firewall_port, '\0', sizeof (excontext->udp_firewall_port));
      memset (excontext->tcp_firewall_ip, '\0', sizeof (excontext->tcp_firewall_ip));
      memset (excontext->tcp_firewall_port, '\0', sizeof (excontext->tcp_firewall_port));
      memset (excontext->tls_firewall_ip, '\0', sizeof (excontext->tls_firewall_ip));
      memset (excontext->tls_firewall_port, '\0', sizeof (excontext->tls_firewall_port));
      memset (excontext->dtls_firewall_ip, '\0', sizeof (excontext->dtls_firewall_ip));
      memset (excontext->dtls_firewall_port, '\0', sizeof (excontext->dtls_firewall_port));
      return;
    }
    snprintf (excontext->udp_firewall_ip, sizeof (excontext->udp_firewall_ip), "%s", public_address);
    snprintf (excontext->tcp_firewall_ip, sizeof (excontext->tcp_firewall_ip), "%s", public_address);
    snprintf (excontext->tls_firewall_ip, sizeof (excontext->tls_firewall_ip), "%s", public_address);
    snprintf (excontext->dtls_firewall_ip, sizeof (excontext->dtls_firewall_ip), "%s", public_address);
    if (port > 0) {
      snprintf (excontext->udp_firewall_port, sizeof (excontext->udp_firewall_port), "%i", port);
      snprintf (excontext->tcp_firewall_port, sizeof (excontext->tcp_firewall_port), "%i", port);
      snprintf (excontext->tls_firewall_port, sizeof (excontext->tls_firewall_port), "%i", port);
      snprintf (excontext->dtls_firewall_port, sizeof (excontext->dtls_firewall_port), "%i", port);
    }
    return;
  }
  excontext->eXtl_transport.tl_masquerade_contact (excontext, public_address, port);
  return;
}

Project: savannah

eXosip_quit (struct eXosip_t *excontext)
{
  jauthinfo_t *jauthinfo;
  eXosip_call_t *jc;
  eXosip_reg_t *jreg;

#ifndef MINISIZE
  eXosip_notify_t *jn;
  eXosip_subscribe_t *js;
  eXosip_pub_t *jpub;
#endif
#ifndef OSIP_MONOTHREAD
  int i;
#endif

  if (excontext == NULL)
    return;

  if (excontext->j_stop_ua == -1) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_WARNING, NULL, "eXosip: already stopped!\n"));
    return;
  }

  excontext->j_stop_ua = 1;     /* ask to quit the application */
  _eXosip_wakeup (excontext);
  eXosip_wakeup_event (excontext);

#ifndef OSIP_MONOTHREAD
  if (excontext->j_thread != NULL) {
    i = osip_thread_join ((struct osip_thread *) excontext->j_thread);
    if (i != 0) {
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "eXosip: can't terminate thread!\n"));
    }
    osip_free ((struct osip_thread *) excontext->j_thread);
  }

  jpipe_close (excontext->j_socketctl);
  jpipe_close (excontext->j_socketctl_event);
#endif

  osip_free (excontext->user_agent);

  for (jc = excontext->j_calls; jc != NULL; jc = excontext->j_calls) {
    REMOVE_ELEMENT (excontext->j_calls, jc);
    _eXosip_call_free (excontext, jc);
  }

#ifndef MINISIZE
  for (js = excontext->j_subscribes; js != NULL; js = excontext->j_subscribes) {
    REMOVE_ELEMENT (excontext->j_subscribes, js);
    _eXosip_subscribe_free (excontext, js);
  }

  for (jn = excontext->j_notifies; jn != NULL; jn = excontext->j_notifies) {
    REMOVE_ELEMENT (excontext->j_notifies, jn);
    _eXosip_notify_free (excontext, jn);
  }
#endif

#ifndef OSIP_MONOTHREAD
  osip_mutex_destroy ((struct osip_mutex *) excontext->j_mutexlock);
#if !defined (_WIN32_WCE)
  osip_cond_destroy ((struct osip_cond *) excontext->j_cond);
#endif
#endif

  for (jreg = excontext->j_reg; jreg != NULL; jreg = excontext->j_reg) {
    REMOVE_ELEMENT (excontext->j_reg, jreg);
    _eXosip_reg_free (excontext, jreg);
  }

#ifndef MINISIZE
  for (jpub = excontext->j_pub; jpub != NULL; jpub = excontext->j_pub) {
    REMOVE_ELEMENT (excontext->j_pub, jpub);
    _eXosip_pub_free (excontext, jpub);
  }
#endif

  while (!osip_list_eol (&excontext->j_transactions, 0)) {
    osip_transaction_t *tr = (osip_transaction_t *) osip_list_get (&excontext->j_transactions, 0);

    if (tr->state == IST_TERMINATED || tr->state == ICT_TERMINATED || tr->state == NICT_TERMINATED || tr->state == NIST_TERMINATED) {
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_INFO1, NULL, "Release a terminated transaction\n"));
      osip_list_remove (&excontext->j_transactions, 0);
      _eXosip_delete_reserved (tr);
      _eXosip_dnsutils_release (tr->naptr_record);
      tr->naptr_record = NULL;
      osip_transaction_free (tr);
    }
    else {
      osip_list_remove (&excontext->j_transactions, 0);
      _eXosip_delete_reserved (tr);
      _eXosip_dnsutils_release (tr->naptr_record);
      tr->naptr_record = NULL;
      osip_transaction_free (tr);
    }
  }

  _eXosip_kill_transaction (&excontext->j_osip->osip_ict_transactions);
  _eXosip_kill_transaction (&excontext->j_osip->osip_nict_transactions);
  _eXosip_kill_transaction (&excontext->j_osip->osip_ist_transactions);
  _eXosip_kill_transaction (&excontext->j_osip->osip_nist_transactions);
  osip_release (excontext->j_osip);

  {
    eXosip_event_t *ev;

    for (ev = osip_fifo_tryget (excontext->j_events); ev != NULL; ev = osip_fifo_tryget (excontext->j_events))
      eXosip_event_free (ev);
  }

  osip_fifo_free (excontext->j_events);

  for (jauthinfo = excontext->authinfos; jauthinfo != NULL; jauthinfo = excontext->authinfos) {
    REMOVE_ELEMENT (excontext->authinfos, jauthinfo);
    osip_free (jauthinfo);
  }

  {
    struct eXosip_http_auth *http_auth;
    int pos;

    /* update entries with same call_id */
    for (pos = 0; pos < MAX_EXOSIP_HTTP_AUTH; pos++) {
      http_auth = &excontext->http_auths[pos];
      if (http_auth->pszCallId[0] == '\0')
        continue;
      osip_proxy_authenticate_free (http_auth->wa);
      memset (http_auth, 0, sizeof (struct eXosip_http_auth));
    }
  }

  if (excontext->eXtl_transport.tl_free != NULL)
    excontext->eXtl_transport.tl_free (excontext);

  memset (excontext, 0, sizeof (eXosip_t));
  excontext->j_stop_ua = -1;

  return;
}

Project: savannah

eXosip_reset_transports (struct eXosip_t *excontext)
{
  int i = OSIP_WRONG_STATE;

  if (excontext->eXtl_transport.tl_reset)
    i = excontext->eXtl_transport.tl_reset (excontext);
  return i;
}

Project: savannah

eXosip_set_cbsip_message (struct eXosip_t *excontext, CbSipCallback cbsipCallback)
{
  excontext->cbsipCallback = cbsipCallback;
  return 0;
}

Project: savannah

_tcp_tl_check_connected (struct eXosip_t *excontext)
{
  struct eXtltcp *reserved = (struct eXtltcp *) excontext->eXtltcp_reserved;
  int pos;
  int res;

  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) {
    if (reserved->socket_tab[pos].invalid > 0) {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
                   "_tcp_tl_check_connected: socket node is in invalid state:%s:%i, socket %d [pos=%d], family:%d\n",
                   reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
      _tcp_tl_close_sockinfo (&reserved->socket_tab[pos]);
      continue;
    }

    if (reserved->socket_tab[pos].socket > 0 && reserved->socket_tab[pos].ai_addrlen > 0) {
      res = _tcp_tl_is_connected (reserved->socket_tab[pos].socket);
      if (res > 0) {
        res = connect (reserved->socket_tab[pos].socket, &reserved->socket_tab[pos].ai_addr, reserved->socket_tab[pos].ai_addrlen);
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO2, NULL,
                     "_tcp_tl_check_connected: socket node:%s:%i, socket %d [pos=%d], family:%d, in progress\n",
                     reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
        continue;
      }
      else if (res == 0) {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO1, NULL,
                     "_tcp_tl_check_connected: socket node:%s:%i , socket %d [pos=%d], family:%d, connected\n",
                     reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
        /* stop calling "connect()" */
        reserved->socket_tab[pos].ai_addrlen = 0;
        continue;
      }
      else {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO2, NULL,
                     "_tcp_tl_check_connected: socket node:%s:%i, socket %d [pos=%d], family:%d, error\n",
                     reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
        _tcp_tl_close_sockinfo (&reserved->socket_tab[pos]);
        continue;
      }
    }
  }
  return 0;
}

Project: savannah

_tcp_tl_close_sockinfo (struct _tcp_stream *sockinfo)
{
  closesocket (sockinfo->socket);
  if (sockinfo->buf != NULL)
    osip_free (sockinfo->buf);
  if (sockinfo->sendbuf != NULL)
    osip_free (sockinfo->sendbuf);
#ifdef MULTITASKING_ENABLED
  if (sockinfo->readStream != NULL) {
    CFReadStreamClose (sockinfo->readStream);
    CFRelease (sockinfo->readStream);
  }
  if (sockinfo->writeStream != NULL) {
    CFWriteStreamClose (sockinfo->writeStream);
    CFRelease (sockinfo->writeStream);
  }
#endif
  memset (sockinfo, 0, sizeof (*sockinfo));
}

Project: savannah

RSA_generate_key (int bits, unsigned long e_value, void (*callback) (int, int, void *), void *cb_arg)
{
  BN_GENCB cb;
  int i;
  RSA *rsa = RSA_new ();
  BIGNUM *e = BN_new ();

  if (!rsa || !e)
    goto err;

  /* The problem is when building with 8, 16, or 32 BN_ULONG,                                                                                                  
   * unsigned long can be larger */
  for (i = 0; i < (int) sizeof (unsigned long) * 8; i++) {
    if (e_value & (1UL << i))
      if (BN_set_bit (e, i) == 0)
        goto err;
  }

  BN_GENCB_set_old (&cb, callback, cb_arg);

  if (RSA_generate_key_ex (rsa, bits, e, &cb)) {
    BN_free (e);
    return rsa;
  }
err:
  if (e)
    BN_free (e);
  if (rsa)
    RSA_free (rsa);
  return 0;
}

Project: savannah

_tls_add_certificates (SSL_CTX * ctx)
{
  int count = 0;

#ifdef HAVE_WINCRYPT_H
  PCCERT_CONTEXT pCertCtx;
  X509 *cert = NULL;
  HCERTSTORE hStore = CertOpenSystemStore (0, L"CA");

  for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
    cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
    if (cert == NULL) {
      continue;
    }
    /*tls_dump_cert_info("CA", cert); */

    if (!X509_STORE_add_cert (ctx->cert_store, cert)) {
      X509_free (cert);
      continue;
    }
    count++;
    X509_free (cert);
  }

  CertCloseStore (hStore, 0);

  hStore = CertOpenSystemStore (0, L"ROOT");

  for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
    cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
    if (cert == NULL) {
      continue;
    }
    /*tls_dump_cert_info("ROOT", cert); */

    if (!X509_STORE_add_cert (ctx->cert_store, cert)) {
      X509_free (cert);
      continue;
    }
    count++;
    X509_free (cert);
  }

  CertCloseStore (hStore, 0);

  hStore = CertOpenSystemStore (0, L"MY");

  for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
    cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
    if (cert == NULL) {
      continue;
    }
    /*tls_dump_cert_info("MY", cert); */

    if (!X509_STORE_add_cert (ctx->cert_store, cert)) {
      X509_free (cert);
      continue;
    }
    count++;
    X509_free (cert);
  }

  CertCloseStore (hStore, 0);

  hStore = CertOpenSystemStore (0, L"Trustedpublisher");

  for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
    cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
    if (cert == NULL) {
      continue;
    }
    /*tls_dump_cert_info("Trustedpublisher", cert); */

    if (!X509_STORE_add_cert (ctx->cert_store, cert)) {
      X509_free (cert);
      continue;
    }
    count++;
    X509_free (cert);
  }

  CertCloseStore (hStore, 0);
#elif defined(__APPLE__) && (TARGET_OS_IPHONE==0)
  SecKeychainSearchRef pSecKeychainSearch = NULL;
  SecKeychainRef pSecKeychain;
  OSStatus status = noErr;
  X509 *cert = NULL;
  SInt32 osx_version = 0;

  if (Gestalt (gestaltSystemVersion, &osx_version) != noErr) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "macosx certificate store: can't get osx version"));
    return 0;
  }
  if (osx_version >= 0x1050) {
    /* Leopard store location */
    status = SecKeychainOpen ("/System/Library/Keychains/SystemRootCertificates.keychain", &pSecKeychain);
  }
  else {
    /* Tiger and below store location */
    status = SecKeychainOpen ("/System/Library/Keychains/X509Anchors", &pSecKeychain);
  }
  if (status != noErr) {
    OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "macosx certificate store: can't get osx version"));
    return 0;
  }

  status = SecKeychainSearchCreateFromAttributes (pSecKeychain, kSecCertificateItemClass, NULL, &pSecKeychainSearch);
  for (;;) {
    SecKeychainItemRef pSecKeychainItem = nil;

    status = SecKeychainSearchCopyNext (pSecKeychainSearch, &pSecKeychainItem);
    if (status == errSecItemNotFound) {
      break;
    }

    if (status == noErr) {
      void *_pCertData;
      UInt32 _pCertLength;

      status = SecKeychainItemCopyAttributesAndData (pSecKeychainItem, NULL, NULL, NULL, &_pCertLength, &_pCertData);

      if (status == noErr && _pCertData != NULL) {
        unsigned char *ptr;

        ptr = _pCertData;       /*required because d2i_X509 is modifying pointer */
        cert = d2i_X509 (NULL, (const unsigned char **) &ptr, _pCertLength);
        if (cert == NULL) {
          continue;
        }
        /*tls_dump_cert_info("ROOT", cert); */

        if (!X509_STORE_add_cert (ctx->cert_store, cert)) {
          X509_free (cert);
          continue;
        }
        count++;
        X509_free (cert);

        status = SecKeychainItemFreeAttributesAndData (NULL, _pCertData);
      }
    }

    if (pSecKeychainItem != NULL)
      CFRelease (pSecKeychainItem);

    if (status != noErr) {
      OSIP_TRACE (osip_trace (__FILE__, __LINE__, OSIP_ERROR, NULL, "macosx certificate store: can't add certificate (%i)", status));
    }
  }

  CFRelease (pSecKeychainSearch);
  CFRelease (pSecKeychain);

#endif
  return count;
}

Project: savannah

_tls_set_certificate (SSL_CTX * ctx, const char *cn)
{
#ifdef HAVE_WINCRYPT_H
  PCCERT_CONTEXT pCertCtx;
  X509 *cert = NULL;
  HCERTSTORE hStore = CertOpenSystemStore (0, L"CA");

  for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
    char peer_CN[65];

    cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
    if (cert == NULL) {
      continue;
    }

    memset (peer_CN, 0, sizeof (peer_CN));
    X509_NAME_get_text_by_NID (X509_get_subject_name (cert), NID_commonName, peer_CN, sizeof (peer_CN));
    if (osip_strcasecmp (cn, peer_CN) == 0) {
      break;
    }
    X509_free (cert);
    cert = NULL;
  }

  CertCloseStore (hStore, 0);

  if (cert == NULL) {
    hStore = CertOpenSystemStore (0, L"ROOT");
    for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
      char peer_CN[65];

      cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
      if (cert == NULL) {
        continue;
      }

      memset (peer_CN, 0, sizeof (peer_CN));
      X509_NAME_get_text_by_NID (X509_get_subject_name (cert), NID_commonName, peer_CN, sizeof (peer_CN));
      if (osip_strcasecmp (cn, peer_CN) == 0) {
        break;
      }
      X509_free (cert);
      cert = NULL;
    }

    CertCloseStore (hStore, 0);
  }

  if (cert == NULL) {
    hStore = CertOpenSystemStore (0, L"MY");

    for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
      char peer_CN[65];

      cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
      if (cert == NULL) {
        continue;
      }

      memset (peer_CN, 0, sizeof (peer_CN));
      X509_NAME_get_text_by_NID (X509_get_subject_name (cert), NID_commonName, peer_CN, sizeof (peer_CN));
      if (osip_strcasecmp (cn, peer_CN) == 0) {
        break;
      }
      X509_free (cert);
      cert = NULL;
    }

    CertCloseStore (hStore, 0);
  }

  if (cert == NULL) {
    hStore = CertOpenSystemStore (0, L"Trustedpublisher");

    for (pCertCtx = CertEnumCertificatesInStore (hStore, NULL); pCertCtx != NULL; pCertCtx = CertEnumCertificatesInStore (hStore, pCertCtx)) {
      char peer_CN[65];

      cert = d2i_X509 (NULL, (const unsigned char **) &pCertCtx->pbCertEncoded, pCertCtx->cbCertEncoded);
      if (cert == NULL) {
        continue;
      }

      memset (peer_CN, 0, sizeof (peer_CN));
      X509_NAME_get_text_by_NID (X509_get_subject_name (cert), NID_commonName, peer_CN, sizeof (peer_CN));
      if (osip_strcasecmp (cn, peer_CN) == 0) {
        break;
      }
      X509_free (cert);
      cert = NULL;
    }

    CertCloseStore (hStore, 0);
  }

  if (cert == NULL)
    return NULL;

  {
    RSA *rsa = NULL, *pub_rsa;
    struct rsa_ctx *priv;
    RSA_METHOD *rsa_meth;

    priv = osip_malloc (sizeof (*priv));
    rsa_meth = osip_malloc (sizeof (*rsa_meth));
    if (priv == NULL || rsa_meth == NULL) {
      CertFreeCertificateContext (pCertCtx);
      osip_free (priv);
      osip_free (rsa_meth);
      X509_free (cert);
      return NULL;
    }
    memset (priv, 0, sizeof (*priv));
    memset (rsa_meth, 0, sizeof (*rsa_meth));

    priv->cert = pCertCtx;

    if (CryptAcquireCertificatePrivateKey (pCertCtx, CRYPT_ACQUIRE_COMPARE_KEY_FLAG, NULL, &priv->crypt_prov, &priv->key_spec, &priv->free_crypt_prov) == 0) {
      CertFreeCertificateContext (priv->cert);
      osip_free (priv);
      osip_free (rsa_meth);
      X509_free (cert);
      return NULL;
    }

    if (!CryptGetUserKey (priv->crypt_prov, priv->key_spec, &priv->hCryptKey)) {
      CertFreeCertificateContext (priv->cert);
      if (priv->crypt_prov && priv->free_crypt_prov)
        CryptReleaseContext (priv->crypt_prov, 0);
      osip_free (priv);
      osip_free (rsa_meth);
      X509_free (cert);
      return NULL;
    }

    rsa_meth->name = "Microsoft CryptoAPI RSA Method";
    rsa_meth->rsa_pub_enc = rsa_pub_enc;
    rsa_meth->rsa_pub_dec = rsa_pub_dec;
    rsa_meth->rsa_priv_enc = rsa_priv_enc;
    rsa_meth->rsa_priv_dec = rsa_priv_dec;
    rsa_meth->finish = rsa_finish;
    rsa_meth->flags = RSA_METHOD_FLAG_NO_CHECK;
    rsa_meth->app_data = (char *) priv;

    rsa = RSA_new ();
    if (rsa == NULL) {
      CertFreeCertificateContext (priv->cert);
      if (priv->crypt_prov && priv->free_crypt_prov)
        CryptReleaseContext (priv->crypt_prov, 0);
      osip_free (priv);
      osip_free (rsa_meth);
      X509_free (cert);
      RSA_free (rsa);
      return NULL;
    }

    if (!SSL_CTX_use_certificate (ctx, cert)) {
      CertFreeCertificateContext (priv->cert);
      if (priv->crypt_prov && priv->free_crypt_prov)
        CryptReleaseContext (priv->crypt_prov, 0);
      osip_free (priv);
      osip_free (rsa_meth);
      X509_free (cert);
      return NULL;
    }

    pub_rsa = cert->cert_info->key->pkey->pkey.rsa;

    rsa->n = BN_dup (pub_rsa->n);
    rsa->e = BN_dup (pub_rsa->e);
    if (!RSA_set_method (rsa, rsa_meth)) {
      CertFreeCertificateContext (priv->cert);
      if (priv->crypt_prov && priv->free_crypt_prov)
        CryptReleaseContext (priv->crypt_prov, 0);
      osip_free (priv);
      osip_free (rsa_meth);
      RSA_free (rsa);
      X509_free (cert);
      SSL_CTX_free (ctx);
      return NULL;
    }

    if (!SSL_CTX_use_RSAPrivateKey (ctx, rsa)) {
      RSA_free (rsa);
      X509_free (cert);
      SSL_CTX_free (ctx);
      return NULL;
    }
    RSA_free (rsa);

    return cert;
  }

#endif
  return NULL;
}

Project: savannah

_tls_tl_check_connected (struct eXosip_t *excontext)
{
  struct eXtltls *reserved = (struct eXtltls *) excontext->eXtltls_reserved;
  int pos;
  int res;

  for (pos = 0; pos < EXOSIP_MAX_SOCKETS; pos++) {
    if (reserved->socket_tab[pos].invalid > 0) {
      OSIP_TRACE (osip_trace
                  (__FILE__, __LINE__, OSIP_INFO2, NULL,
                   "_tls_tl_check_connected: socket node is in invalid state:%s:%i, socket %d [pos=%d], family:%d\n",
                   reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
      _tls_tl_close_sockinfo (&reserved->socket_tab[pos]);
      continue;
    }

    if (reserved->socket_tab[pos].socket > 0 && reserved->socket_tab[pos].ai_addrlen > 0) {
      if (reserved->socket_tab[pos].ssl_state > 0) {
        /* already connected */
        reserved->socket_tab[pos].ai_addrlen = 0;
        continue;
      }

      res = _tls_tl_is_connected (reserved->socket_tab[pos].socket);
      if (res > 0) {
        res = connect (reserved->socket_tab[pos].socket, &reserved->socket_tab[pos].ai_addr, reserved->socket_tab[pos].ai_addrlen);
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO2, NULL,
                     "_tls_tl_check_connected: socket node:%s:%i, socket %d [pos=%d], family:%d, in progress\n",
                     reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
        continue;
      }
      else if (res == 0) {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO1, NULL,
                     "_tls_tl_check_connected: socket node:%s:%i , socket %d [pos=%d], family:%d, connected\n",
                     reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
        /* stop calling "connect()" */
        reserved->socket_tab[pos].ai_addrlen = 0;
        reserved->socket_tab[pos].ssl_state = 1;
        continue;
      }
      else {
        OSIP_TRACE (osip_trace
                    (__FILE__, __LINE__, OSIP_INFO2, NULL,
                     "_tls_tl_check_connected: socket node:%s:%i, socket %d [pos=%d], family:%d, error\n",
                     reserved->socket_tab[pos].remote_ip, reserved->socket_tab[pos].remote_port, reserved->socket_tab[pos].socket, pos, reserved->socket_tab[pos].ai_addr.sa_family));
        _tls_tl_close_sockinfo (&reserved->socket_tab[pos]);
        continue;
      }
    }
  }
  return 0;
}

Project: savannah

_tls_tl_close_sockinfo (struct _tls_stream *sockinfo)
{
  if (sockinfo->socket > 0) {
    if (sockinfo->ssl_conn != NULL) {
      SSL_shutdown (sockinfo->ssl_conn);
      SSL_shutdown (sockinfo->ssl_conn);
      SSL_free (sockinfo->ssl_conn);
    }
    if (sockinfo->ssl_ctx != NULL)
      SSL_CTX_free (sockinfo->ssl_ctx);
    closesocket (sockinfo->socket);
  }
  if (sockinfo->buf != NULL)
    osip_free (sockinfo->buf);
  if (sockinfo->sendbuf != NULL)
    osip_free (sockinfo->sendbuf);
#ifdef MULTITASKING_ENABLED
  if (sockinfo->readStream != NULL) {
    CFReadStreamClose (sockinfo->readStream);
    CFRelease (sockinfo->readStream);
  }
  if (sockinfo->writeStream != NULL) {
    CFWriteStreamClose (sockinfo->writeStream);
    CFRelease (sockinfo->writeStream);
  }
#endif
  memset (sockinfo, 0, sizeof (*sockinfo));
}