1
0
mirror of https://github.com/moparisthebest/curl synced 2024-11-17 15:05:02 -05:00

schannel: unified error code handling

Closes #2901
This commit is contained in:
Han Han 2018-08-15 19:57:16 -07:00 committed by Daniel Stenberg
parent 84a23a0997
commit 5a3efb1dba
No known key found for this signature in database
GPG Key ID: 5CC908FDB71E12C2
2 changed files with 71 additions and 30 deletions

View File

@ -363,7 +363,7 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
sep = _tcschr(path, TEXT('\\')); sep = _tcschr(path, TEXT('\\'));
if(sep == NULL) if(sep == NULL)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CERTPROBLEM;
store_name_len = sep - path; store_name_len = sep - path;
@ -387,19 +387,19 @@ get_cert_location(TCHAR *path, DWORD *store_name, TCHAR **store_path,
store_name_len) == 0) store_name_len) == 0)
*store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE; *store_name = CERT_SYSTEM_STORE_LOCAL_MACHINE_ENTERPRISE;
else else
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CERTPROBLEM;
*store_path = sep + 1; *store_path = sep + 1;
sep = _tcschr(*store_path, TEXT('\\')); sep = _tcschr(*store_path, TEXT('\\'));
if(sep == NULL) if(sep == NULL)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CERTPROBLEM;
*sep = 0; *sep = 0;
*thumbprint = sep + 1; *thumbprint = sep + 1;
if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN) if(_tcslen(*thumbprint) != CERT_THUMBPRINT_STR_LEN)
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CERTPROBLEM;
return CURLE_OK; return CURLE_OK;
} }
@ -612,7 +612,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
"last error is %x", "last error is %x",
cert_store_name, cert_store_path, GetLastError()); cert_store_name, cert_store_path, GetLastError());
Curl_unicodefree(cert_path); Curl_unicodefree(cert_path);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CERTPROBLEM;
} }
cert_thumbprint.pbData = cert_thumbprint_data; cert_thumbprint.pbData = cert_thumbprint_data;
@ -623,7 +623,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
cert_thumbprint_data, &cert_thumbprint.cbData, cert_thumbprint_data, &cert_thumbprint.cbData,
NULL, NULL)) { NULL, NULL)) {
Curl_unicodefree(cert_path); Curl_unicodefree(cert_path);
return CURLE_SSL_CONNECT_ERROR; return CURLE_SSL_CERTPROBLEM;
} }
client_certs[0] = CertFindCertificateInStore( client_certs[0] = CertFindCertificateInStore(
@ -636,6 +636,10 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
schannel_cred.cCreds = 1; schannel_cred.cCreds = 1;
schannel_cred.paCred = client_certs; schannel_cred.paCred = client_certs;
} }
else {
/* CRYPT_E_NOT_FOUND / E_INVALIDARG */
return CURLE_SSL_CERTPROBLEM;
}
CertCloseStore(cert_store, 0); CertCloseStore(cert_store, 0);
} }
@ -672,14 +676,20 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
CertFreeCertificateContext(client_certs[0]); CertFreeCertificateContext(client_certs[0]);
if(sspi_status != SEC_E_OK) { if(sspi_status != SEC_E_OK) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL) failf(data, "schannel: AcquireCredentialsHandle failed: %s",
failf(data, "schannel: SNI or certificate check failed: %s", Curl_sspi_strerror(conn, sspi_status));
Curl_sspi_strerror(conn, sspi_status));
else
failf(data, "schannel: AcquireCredentialsHandle failed: %s",
Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(BACKEND->cred); Curl_safefree(BACKEND->cred);
return CURLE_SSL_CONNECT_ERROR; switch(sspi_status) {
case SEC_E_INSUFFICIENT_MEMORY:
return CURLE_OUT_OF_MEMORY;
case SEC_E_NO_CREDENTIALS:
case SEC_E_SECPKG_NOT_FOUND:
case SEC_E_NOT_OWNER:
case SEC_E_UNKNOWN_CREDENTIALS:
case SEC_E_INTERNAL_ERROR:
default:
return CURLE_SSL_CONNECT_ERROR;
}
} }
} }
@ -782,14 +792,30 @@ schannel_connect_step1(struct connectdata *conn, int sockindex)
Curl_unicodefree(host_name); Curl_unicodefree(host_name);
if(sspi_status != SEC_I_CONTINUE_NEEDED) { if(sspi_status != SEC_I_CONTINUE_NEEDED) {
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed: %s",
Curl_sspi_strerror(conn, sspi_status));
else
failf(data, "schannel: initial InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
Curl_safefree(BACKEND->ctxt); Curl_safefree(BACKEND->ctxt);
return CURLE_SSL_CONNECT_ERROR; switch(sspi_status) {
case SEC_E_INSUFFICIENT_MEMORY:
failf(data, "schannel: initial InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
return CURLE_OUT_OF_MEMORY;
case SEC_E_WRONG_PRINCIPAL:
failf(data, "schannel: SNI or certificate check failed: %s",
Curl_sspi_strerror(conn, sspi_status));
return CURLE_PEER_FAILED_VERIFICATION;
case SEC_E_INVALID_HANDLE:
case SEC_E_INVALID_TOKEN:
case SEC_E_LOGON_DENIED:
case SEC_E_TARGET_UNKNOWN:
case SEC_E_NO_AUTHENTICATING_AUTHORITY:
case SEC_E_INTERNAL_ERROR:
case SEC_E_NO_CREDENTIALS:
case SEC_E_UNSUPPORTED_FUNCTION:
case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
default:
failf(data, "schannel: initial InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
return CURLE_SSL_CONNECT_ERROR;
}
} }
infof(data, "schannel: sending initial handshake data: " infof(data, "schannel: sending initial handshake data: "
@ -1004,14 +1030,29 @@ schannel_connect_step2(struct connectdata *conn, int sockindex)
} }
} }
else { else {
if(sspi_status == SEC_E_WRONG_PRINCIPAL) switch(sspi_status) {
failf(data, "schannel: SNI or certificate check failed: %s", case SEC_E_INSUFFICIENT_MEMORY:
Curl_sspi_strerror(conn, sspi_status)); failf(data, "schannel: next InitializeSecurityContext failed: %s",
else Curl_sspi_strerror(conn, sspi_status));
failf(data, "schannel: next InitializeSecurityContext failed: %s", return CURLE_OUT_OF_MEMORY;
Curl_sspi_strerror(conn, sspi_status)); case SEC_E_WRONG_PRINCIPAL:
return sspi_status == SEC_E_UNTRUSTED_ROOT ? failf(data, "schannel: SNI or certificate check failed: %s",
CURLE_SSL_CACERT : CURLE_SSL_CONNECT_ERROR; Curl_sspi_strerror(conn, sspi_status));
return CURLE_PEER_FAILED_VERIFICATION;
case SEC_E_INVALID_HANDLE:
case SEC_E_INVALID_TOKEN:
case SEC_E_LOGON_DENIED:
case SEC_E_TARGET_UNKNOWN:
case SEC_E_NO_AUTHENTICATING_AUTHORITY:
case SEC_E_INTERNAL_ERROR:
case SEC_E_NO_CREDENTIALS:
case SEC_E_UNSUPPORTED_FUNCTION:
case SEC_E_APPLICATION_PROTOCOL_MISMATCH:
default:
failf(data, "schannel: next InitializeSecurityContext failed: %s",
Curl_sspi_strerror(conn, sspi_status));
return CURLE_SSL_CONNECT_ERROR;
}
} }
/* check if there was additional remaining encrypted data */ /* check if there was additional remaining encrypted data */
@ -1192,7 +1233,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex)
if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) { if((sspi_status != SEC_E_OK) || (ccert_context == NULL)) {
failf(data, "schannel: failed to retrieve remote cert context"); failf(data, "schannel: failed to retrieve remote cert context");
return CURLE_SSL_CONNECT_ERROR; return CURLE_PEER_FAILED_VERIFICATION;
} }
result = Curl_ssl_init_certinfo(data, 1); result = Curl_ssl_init_certinfo(data, 1);

View File

@ -135,7 +135,7 @@ static CURLcode add_certs_to_store(HCERTSTORE trust_store,
failf(data, failf(data,
"schannel: CA file exceeds max size of %u bytes", "schannel: CA file exceeds max size of %u bytes",
MAX_CAFILE_SIZE); MAX_CAFILE_SIZE);
result = CURLE_OUT_OF_MEMORY; result = CURLE_SSL_CACERT_BADFILE;
goto cleanup; goto cleanup;
} }