Commit 897ef500 authored by Patrick Monnerat's avatar Patrick Monnerat
Browse files

gskit.c: use 'CURLcode result'

parent ec783dc1
Loading
Loading
Loading
Loading
+143 −141
Original line number Diff line number Diff line
@@ -164,8 +164,6 @@ static bool is_separator(char c)
static CURLcode gskit_status(struct SessionHandle *data, int rc,
                             const char *procname, CURLcode defcode)
{
  CURLcode cc;

  /* Process GSKit status and map it to a CURLcode. */
  switch (rc) {
  case GSK_OK:
@@ -298,7 +296,7 @@ static CURLcode set_ciphers(struct SessionHandle *data,
  int i;
  int l;
  bool unsupported;
  CURLcode cc;
  CURLcode result;
  struct {
    char *buf;
    char *ptr;
@@ -331,7 +329,7 @@ static CURLcode set_ciphers(struct SessionHandle *data,

  /* Process each cipher in input string. */
  unsupported = FALSE;
  cc = CURLE_OK;
  result = CURLE_OK;
  for(;;) {
    for(clp = cipherlist; *cipherlist && !is_separator(*cipherlist);)
      cipherlist++;
@@ -344,7 +342,7 @@ static CURLcode set_ciphers(struct SessionHandle *data,
        break;
    if(!ctp->name) {
      failf(data, "Unknown cipher %.*s", l, clp);
      cc = CURLE_SSL_CIPHER;
      result = CURLE_SSL_CIPHER;
    }
    else {
      unsupported |= !(ctp->versions & (CURL_GSKPROTO_SSLV2_MASK |
@@ -372,53 +370,53 @@ static CURLcode set_ciphers(struct SessionHandle *data,

  /* Try to set-up TLSv1.1 and TLSv2.1 ciphers. */
  if(*protoflags & CURL_GSKPROTO_TLSV11_MASK) {
    cc = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
    result = set_buffer(data, h, GSK_TLSV11_CIPHER_SPECS,
                        ciphers[CURL_GSKPROTO_TLSV11].buf, TRUE);
    if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
      cc = CURLE_OK;
    if(result == CURLE_UNSUPPORTED_PROTOCOL) {
      result = CURLE_OK;
      if(unsupported) {
        failf(data, "TLSv1.1-only ciphers are not yet supported");
        cc = CURLE_SSL_CIPHER;
        result = CURLE_SSL_CIPHER;
      }
    }
  }
  if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
    cc = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
  if(!result && (*protoflags & CURL_GSKPROTO_TLSV12_MASK)) {
    result = set_buffer(data, h, GSK_TLSV12_CIPHER_SPECS,
                        ciphers[CURL_GSKPROTO_TLSV12].buf, TRUE);
    if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
      cc = CURLE_OK;
    if(result == CURLE_UNSUPPORTED_PROTOCOL) {
      result = CURLE_OK;
      if(unsupported) {
        failf(data, "TLSv1.2-only ciphers are not yet supported");
        cc = CURLE_SSL_CIPHER;
        result = CURLE_SSL_CIPHER;
      }
    }
  }

  /* Try to set-up TLSv1.0 ciphers. If not successful, concatenate them to
     the SSLv3 ciphers. OS/400 prior to version 7.1 will understand it. */
  if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
    cc = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
  if(!result && (*protoflags & CURL_GSKPROTO_TLSV10_MASK)) {
    result = set_buffer(data, h, GSK_TLSV10_CIPHER_SPECS,
                        ciphers[CURL_GSKPROTO_TLSV10].buf, TRUE);
    if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
      cc = CURLE_OK;
    if(result == CURLE_UNSUPPORTED_PROTOCOL) {
      result = CURLE_OK;
      strcpy(ciphers[CURL_GSKPROTO_SSLV3].ptr,
             ciphers[CURL_GSKPROTO_TLSV10].ptr);
    }
  }

  /* Set-up other ciphers. */
  if(cc == CURLE_OK &&  (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
    cc = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
  if(!result && (*protoflags & CURL_GSKPROTO_SSLV3_MASK))
    result = set_buffer(data, h, GSK_V3_CIPHER_SPECS,
                        ciphers[CURL_GSKPROTO_SSLV3].buf, FALSE);
  if(cc == CURLE_OK && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
    cc = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
  if(!result && (*protoflags & CURL_GSKPROTO_SSLV2_MASK))
    result = set_buffer(data, h, GSK_V2_CIPHER_SPECS,
                        ciphers[CURL_GSKPROTO_SSLV2].buf, FALSE);

  /* Clean-up. */
  for(i = 0; i < CURL_GSKPROTO_LAST; i++)
    free(ciphers[i].buf);

  return cc;
  return result;
}


@@ -442,7 +440,7 @@ static CURLcode init_environment(struct SessionHandle *data,
                                 const char *password)
{
  int rc;
  CURLcode c;
  CURLcode result;
  gsk_handle h;

  /* Creates the GSKit environment. */
@@ -458,29 +456,29 @@ static CURLcode init_environment(struct SessionHandle *data,
    return CURLE_SSL_CONNECT_ERROR;
  }

  c = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
  if(c == CURLE_OK && appid)
    c = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
  if(c == CURLE_OK && file)
    c = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
  if(c == CURLE_OK && label)
    c = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
  if(c == CURLE_OK && password)
    c = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);
  result = set_enum(data, h, GSK_SESSION_TYPE, GSK_CLIENT_SESSION, FALSE);
  if(!result && appid)
    result = set_buffer(data, h, GSK_OS400_APPLICATION_ID, appid, FALSE);
  if(!result && file)
    result = set_buffer(data, h, GSK_KEYRING_FILE, file, FALSE);
  if(!result && label)
    result = set_buffer(data, h, GSK_KEYRING_LABEL, label, FALSE);
  if(!result && password)
    result = set_buffer(data, h, GSK_KEYRING_PW, password, FALSE);

  if(c == CURLE_OK) {
  if(!result) {
    /* Locate CAs, Client certificate and key according to our settings.
       Note: this call may be blocking for some tenths of seconds. */
    c = gskit_status(data, gsk_environment_init(h),
    result = gskit_status(data, gsk_environment_init(h),
                          "gsk_environment_init()", CURLE_SSL_CERTPROBLEM);
    if(c == CURLE_OK) {
    if(!result) {
      *envir = h;
      return c;
      return result;
    }
  }
  /* Error: rollback. */
  gsk_environment_close(&h);
  return c;
  return result;
}


@@ -558,7 +556,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
  struct SessionHandle *data = conn->data;
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  gsk_handle envir;
  CURLcode cc;
  CURLcode result;
  int rc;
  char *keyringfile;
  char *keyringpwd;
@@ -600,18 +598,18 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)

  if(!envir) {
    /* Use keyring mode. */
    cc = init_environment(data, &envir, (const char *) NULL,
    result = init_environment(data, &envir, (const char *) NULL,
                              keyringfile, keyringlabel, keyringpwd);
    if(cc != CURLE_OK)
      return cc;
    if(result)
      return result;
  }

  /* Create secure session. */
  cc = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
  result = gskit_status(data, gsk_secure_soc_open(envir, &connssl->handle),
                        "gsk_secure_soc_open()", CURLE_SSL_CONNECT_ERROR);
  gsk_environment_close(&envir);
  if(cc != CURLE_OK)
    return cc;
  if(result)
    return result;

  /* Determine which SSL/TLS version should be enabled. */
  protoflags = CURL_GSKPROTO_SSLV3_MASK | CURL_GSKPROTO_TLSV10_MASK |
@@ -643,81 +641,84 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)

  /* Process SNI. Ignore if not supported (on OS400 < V7R1). */
  if(sni) {
    cc = set_buffer(data, connssl->handle,
    result = set_buffer(data, connssl->handle,
                        GSK_SSL_EXTN_SERVERNAME_REQUEST, sni, TRUE);
    if(cc == CURLE_UNSUPPORTED_PROTOCOL)
      cc = CURLE_OK;
    if(result == CURLE_UNSUPPORTED_PROTOCOL)
      result = CURLE_OK;
  }

  /* Set session parameters. */
  if(cc == CURLE_OK) {
  if(!result) {
    /* Compute the handshake timeout. Since GSKit granularity is 1 second,
       we round up the required value. */
    timeout = Curl_timeleft(data, NULL, TRUE);
    if(timeout < 0)
      cc = CURLE_OPERATION_TIMEDOUT;
      result = CURLE_OPERATION_TIMEDOUT;
    else
      cc = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
      result = set_numeric(data, connssl->handle, GSK_HANDSHAKE_TIMEOUT,
                           (timeout + 999) / 1000);
  }
  if(cc == CURLE_OK)
    cc = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
  if(cc == CURLE_OK)
    cc = set_ciphers(data, connssl->handle, &protoflags);
  if(!result)
    result = set_numeric(data, connssl->handle, GSK_FD, conn->sock[sockindex]);
  if(!result)
    result = set_ciphers(data, connssl->handle, &protoflags);
  if(!protoflags) {
    failf(data, "No SSL protocol/cipher combination enabled");
    cc = CURLE_SSL_CIPHER;
    result = CURLE_SSL_CIPHER;
  }
  if(cc == CURLE_OK)
      cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
  if(!result)
    result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV2,
                      (protoflags & CURL_GSKPROTO_SSLV2_MASK)?
                      GSK_PROTOCOL_SSLV2_ON: GSK_PROTOCOL_SSLV2_OFF, FALSE);
  if(cc == CURLE_OK)
    cc = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
  if(!result)
    result = set_enum(data, connssl->handle, GSK_PROTOCOL_SSLV3,
                      (protoflags & CURL_GSKPROTO_SSLV3_MASK)?
                      GSK_PROTOCOL_SSLV3_ON: GSK_PROTOCOL_SSLV3_OFF, FALSE);
  if(cc == CURLE_OK)
    cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
  if(!result)
    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV1,
                      (protoflags & CURL_GSKPROTO_TLSV10_MASK)?
                      GSK_PROTOCOL_TLSV1_ON: GSK_PROTOCOL_TLSV1_OFF, FALSE);
  if(cc == CURLE_OK) {
    cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
  if(!result) {
    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV11,
                      (protoflags & CURL_GSKPROTO_TLSV11_MASK)?
                      GSK_TRUE: GSK_FALSE, TRUE);
    if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
      cc = CURLE_OK;
    if(result == CURLE_UNSUPPORTED_PROTOCOL) {
      result = CURLE_OK;
      if(protoflags == CURL_GSKPROTO_TLSV11_MASK) {
        failf(data, "TLS 1.1 not yet supported");
        cc = CURLE_SSL_CIPHER;
        result = CURLE_SSL_CIPHER;
      }
    }
  }
  if(cc == CURLE_OK) {
    cc = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
  if(!result) {
    result = set_enum(data, connssl->handle, GSK_PROTOCOL_TLSV12,
                      (protoflags & CURL_GSKPROTO_TLSV12_MASK)?
                      GSK_TRUE: GSK_FALSE, TRUE);
    if(cc == CURLE_UNSUPPORTED_PROTOCOL) {
      cc = CURLE_OK;
    if(result == CURLE_UNSUPPORTED_PROTOCOL) {
      result = CURLE_OK;
      if(protoflags == CURL_GSKPROTO_TLSV12_MASK) {
        failf(data, "TLS 1.2 not yet supported");
        cc = CURLE_SSL_CIPHER;
        result = CURLE_SSL_CIPHER;
      }
    }
  }
  if(cc == CURLE_OK)
    cc = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
  if(!result)
    result = set_enum(data, connssl->handle, GSK_SERVER_AUTH_TYPE,
                      data->set.ssl.verifypeer? GSK_SERVER_AUTH_FULL:
                      GSK_SERVER_AUTH_PASSTHRU, FALSE);

  if(cc == CURLE_OK) {
  if(!result) {
    /* Start handshake. Try asynchronous first. */
    memset(&commarea, 0, sizeof commarea);
    connssl->iocport = QsoCreateIOCompletionPort();
    if(connssl->iocport != -1) {
      cc = gskit_status(data, gsk_secure_soc_startInit(connssl->handle,
                        connssl->iocport, &commarea),
                        "gsk_secure_soc_startInit()", CURLE_SSL_CONNECT_ERROR);
      if(cc == CURLE_OK) {
      result = gskit_status(data,
                            gsk_secure_soc_startInit(connssl->handle,
                                                     connssl->iocport,
                                                     &commarea),
                            "gsk_secure_soc_startInit()",
                            CURLE_SSL_CONNECT_ERROR);
      if(!result) {
        connssl->connecting_state = ssl_connect_2;
        return CURLE_OK;
      }
@@ -725,12 +726,13 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)
        close_async_handshake(connssl);
    }
    else if(errno != ENOBUFS)
      cc = gskit_status(data, GSK_ERROR_IO, "QsoCreateIOCompletionPort()", 0);
      result = gskit_status(data, GSK_ERROR_IO,
                            "QsoCreateIOCompletionPort()", 0);
    else {
      /* No more completion port available. Use synchronous IO. */
      cc = gskit_status(data, gsk_secure_soc_init(connssl->handle),
      result = gskit_status(data, gsk_secure_soc_init(connssl->handle),
                            "gsk_secure_soc_init()", CURLE_SSL_CONNECT_ERROR);
      if(cc == CURLE_OK) {
      if(!result) {
        connssl->connecting_state = ssl_connect_3;
        return CURLE_OK;
      }
@@ -739,7 +741,7 @@ static CURLcode gskit_connect_step1(struct connectdata *conn, int sockindex)

  /* Error: rollback. */
  close_one(connssl, data);
  return cc;
  return result;
}


@@ -751,7 +753,7 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
  Qso_OverlappedIO_t cstat;
  long timeout_ms;
  struct timeval stmv;
  CURLcode cc;
  CURLcode result;

  /* Poll or wait for end of SSL asynchronous handshake. */

@@ -786,12 +788,12 @@ static CURLcode gskit_connect_step2(struct connectdata *conn, int sockindex,
    }
    break;
  }
  cc = gskit_status(data, cstat.returnValue, "SSL handshake",
  result = gskit_status(data, cstat.returnValue, "SSL handshake",
                        CURLE_SSL_CONNECT_ERROR);
  if(cc == CURLE_OK)
  if(!result)
    connssl->connecting_state = ssl_connect_3;
  close_async_handshake(connssl);
  return cc;
  return result;
}


@@ -806,7 +808,7 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
  const char *certend;
  const char *ptr;
  int i;
  CURLcode cc;
  CURLcode result;

  /* SSL handshake done: gather certificate info and verify host. */

@@ -839,9 +841,9 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
  }

  /* Verify host. */
  cc = Curl_verifyhost(conn, cert, certend);
  if(cc != CURLE_OK)
    return cc;
  result = Curl_verifyhost(conn, cert, certend);
  if(result)
    return result;

  /* The only place GSKit can get the whole CA chain is a validation
     callback where no user data pointer is available. Therefore it's not
@@ -852,15 +854,15 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
    if(Curl_ssl_init_certinfo(data, 1))
      return CURLE_OUT_OF_MEMORY;
    if(cert) {
      cc = Curl_extract_certinfo(conn, 0, cert, certend);
      if(cc != CURLE_OK)
        return cc;
      result = Curl_extract_certinfo(conn, 0, cert, certend);
      if(result)
        return result;
    }
  }

  /* Check pinned public key. */
  ptr = data->set.str[STRING_SSL_PINNEDPUBLICKEY];
  if(cc == CURLE_OK && ptr) {
  if(!result && ptr) {
    curl_X509certificate x509;
    curl_asn1Element *p;

@@ -868,10 +870,10 @@ static CURLcode gskit_connect_step3(struct connectdata *conn, int sockindex)
      return CURLE_SSL_PINNEDPUBKEYNOTMATCH;
    Curl_parseX509(&x509, cert, certend);
    p = &x509.subjectPublicKeyInfo;
    cc = Curl_pin_peer_pubkey(ptr, p->header, p->end - p->header);
    if(cc != CURLE_OK) {
    result = Curl_pin_peer_pubkey(ptr, p->header, p->end - p->header);
    if(result) {
      failf(data, "SSL: public key does not match pinned public key!");
      return cc;
      return result;
    }
  }

@@ -887,7 +889,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
  struct ssl_connect_data *connssl = &conn->ssl[sockindex];
  long timeout_ms;
  Qso_OverlappedIO_t cstat;
  CURLcode cc = CURLE_OK;
  CURLcode result = CURLE_OK;

  *done = connssl->state == ssl_connection_complete;
  if(*done)
@@ -901,31 +903,31 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
    if(timeout_ms < 0) {
      /* no need to continue if time already is up */
      failf(data, "SSL connection timeout");
      cc = CURLE_OPERATION_TIMEDOUT;
      result = CURLE_OPERATION_TIMEDOUT;
    }
    else
      cc = gskit_connect_step1(conn, sockindex);
      result = gskit_connect_step1(conn, sockindex);
  }

  /* Step 2: check if handshake is over. */
  if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_2) {
  if(!result && connssl->connecting_state == ssl_connect_2) {
    /* check allowed time left */
    timeout_ms = Curl_timeleft(data, NULL, TRUE);

    if(timeout_ms < 0) {
      /* no need to continue if time already is up */
      failf(data, "SSL connection timeout");
      cc = CURLE_OPERATION_TIMEDOUT;
      result = CURLE_OPERATION_TIMEDOUT;
    }
    else
      cc = gskit_connect_step2(conn, sockindex, nonblocking);
      result = gskit_connect_step2(conn, sockindex, nonblocking);
  }

  /* Step 3: gather certificate info, verify host. */
  if(cc == CURLE_OK && connssl->connecting_state == ssl_connect_3)
    cc = gskit_connect_step3(conn, sockindex);
  if(!result && connssl->connecting_state == ssl_connect_3)
    result = gskit_connect_step3(conn, sockindex);

  if(cc != CURLE_OK)
  if(result)
    close_one(connssl, data);
  else if(connssl->connecting_state == ssl_connect_done) {
    connssl->state = ssl_connection_complete;
@@ -935,7 +937,7 @@ static CURLcode gskit_connect_common(struct connectdata *conn, int sockindex,
    *done = TRUE;
  }

  return cc;
  return result;
}


@@ -943,24 +945,24 @@ CURLcode Curl_gskit_connect_nonblocking(struct connectdata *conn,
                                        int sockindex,
                                        bool *done)
{
  CURLcode cc;
  CURLcode result;

  cc = gskit_connect_common(conn, sockindex, TRUE, done);
  if(*done || cc != CURLE_OK)
  result = gskit_connect_common(conn, sockindex, TRUE, done);
  if(*done || result)
    conn->ssl[sockindex].connecting_state = ssl_connect_1;
  return cc;
  return result;
}


CURLcode Curl_gskit_connect(struct connectdata *conn, int sockindex)
{
  CURLcode retcode;
  CURLcode result;
  bool done;

  conn->ssl[sockindex].connecting_state = ssl_connect_1;
  retcode = gskit_connect_common(conn, sockindex, FALSE, &done);
  if(retcode)
    return retcode;
  result = gskit_connect_common(conn, sockindex, FALSE, &done);
  if(result)
    return result;

  DEBUGASSERT(done);