sspi: Refactored socks_sspi and schannel to use same error message functions

Moved the error constant switch to curl_sspi.c and added two new helper
functions to curl_sspi.[ch] which either return the constant or a fully
translated message representing the SSPI security status.
Updated socks_sspi.c and curl_schannel.c to use the new functions.
This commit is contained in:
Marc Hoersken 2012-04-11 17:25:26 +02:00 committed by Daniel Stenberg
parent 15ca80c831
commit f858bb0d1f
4 changed files with 180 additions and 98 deletions

View File

@ -89,6 +89,7 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
SCHANNEL_CRED schannel_cred;
SECURITY_STATUS sspi_status = SEC_E_OK;
curl_schannel_cred *old_cred = NULL;
char *sspi_msg = NULL;
struct in_addr addr;
#ifdef ENABLE_IPV6
struct in6_addr addr6;
@ -156,11 +157,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
&connssl->cred->cred_handle, &connssl->cred->time_stamp);
if(sspi_status != SEC_E_OK) {
sspi_msg = Curl_sspi_status_msg(sspi_status);
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed\n");
failf(data, "schannel: SNI or certificate check failed: %s\n",
sspi_msg);
else
failf(data, "schannel: AcquireCredentialsHandleA failed: %d\n",
sspi_status);
failf(data, "schannel: AcquireCredentialsHandleA failed: %s\n",
sspi_msg);
free(sspi_msg);
free(connssl->cred);
connssl->cred = NULL;
return CURLE_SSL_CONNECT_ERROR;
@ -196,11 +200,14 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
&outbuf_desc, &connssl->ret_flags, &connssl->ctxt->time_stamp);
if(sspi_status != SEC_I_CONTINUE_NEEDED) {
sspi_msg = Curl_sspi_status_msg(sspi_status);
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed\n");
failf(data, "schannel: SNI or certificate check failed: %s\n",
sspi_msg);
else
failf(data, "schannel: initial InitializeSecurityContextA failed: %d\n",
sspi_status);
failf(data, "schannel: initial InitializeSecurityContextA failed: %s\n",
sspi_msg);
free(sspi_msg);
free(connssl->ctxt);
connssl->ctxt = NULL;
return CURLE_SSL_CONNECT_ERROR;
@ -236,6 +243,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
SecBuffer inbuf[2];
SecBufferDesc inbuf_desc;
SECURITY_STATUS sspi_status = SEC_E_OK;
char *sspi_msg = NULL;
infof(data, "schannel: connecting to %s:%d (step 2/3)\n",
conn->host.name, conn->remote_port);
@ -320,8 +328,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
/* check if the handshake was incomplete */
if(sspi_status == SEC_E_INCOMPLETE_MESSAGE) {
connssl->connecting_state = ssl_connect_2_reading;
infof(data, "schannel: received incomplete message, need more data: %d\n",
sspi_status);
infof(data, "schannel: received incomplete message, need more data\n");
return CURLE_OK;
}
@ -350,11 +357,14 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
}
}
else {
sspi_msg = Curl_sspi_status_msg(sspi_status);
if(sspi_status == SEC_E_WRONG_PRINCIPAL)
failf(data, "schannel: SNI or certificate check failed\n");
failf(data, "schannel: SNI or certificate check failed: %s\n",
sspi_msg);
else
failf(data, "schannel: next InitializeSecurityContextA failed: %d\n",
sspi_status);
failf(data, "schannel: next InitializeSecurityContextA failed: %s\n",
sspi_msg);
free(sspi_msg);
return CURLE_SSL_CONNECT_ERROR;
}
@ -653,6 +663,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
SecBuffer inbuf[4];
SecBufferDesc inbuf_desc;
SECURITY_STATUS sspi_status = SEC_E_OK;
char *sspi_msg = NULL;
infof(data, "schannel: client wants to read %d\n", len);
*err = CURLE_OK;
@ -853,7 +864,9 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* check if something went wrong and we need to return an error */
if(ret < 0 && sspi_status != SEC_E_OK) {
infof(data, "schannel: failed to read data from server\n");
sspi_msg = Curl_sspi_status_msg(sspi_status);
infof(data, "schannel: failed to read data from server: %s\n", sspi_msg);
free(sspi_msg);
*err = CURLE_RECV_ERROR;
return -1;
}

View File

@ -118,4 +118,153 @@ Curl_sspi_global_cleanup(void)
}
}
/*
* Curl_sspi_status(SECURIY_STATUS status)
*
* This function returns a string representing an SSPI status.
* It will in any case return a usable string pointer which needs to be freed.
*/
char*
Curl_sspi_status(SECURITY_STATUS status)
{
const char* status_const;
switch(status) {
case SEC_I_COMPLETE_AND_CONTINUE:
status_const = "SEC_I_COMPLETE_AND_CONTINUE";
break;
case SEC_I_COMPLETE_NEEDED:
status_const = "SEC_I_COMPLETE_NEEDED";
break;
case SEC_I_CONTINUE_NEEDED:
status_const = "SEC_I_CONTINUE_NEEDED";
break;
case SEC_I_CONTEXT_EXPIRED:
status_const = "SEC_I_CONTEXT_EXPIRED";
break;
case SEC_I_INCOMPLETE_CREDENTIALS:
status_const = "SEC_I_INCOMPLETE_CREDENTIALS";
break;
case SEC_I_RENEGOTIATE:
status_const = "SEC_I_RENEGOTIATE";
break;
case SEC_E_BUFFER_TOO_SMALL:
status_const = "SEC_E_BUFFER_TOO_SMALL";
break;
case SEC_E_CONTEXT_EXPIRED:
status_const = "SEC_E_CONTEXT_EXPIRED";
break;
case SEC_E_CRYPTO_SYSTEM_INVALID:
status_const = "SEC_E_CRYPTO_SYSTEM_INVALID";
break;
case SEC_E_INCOMPLETE_MESSAGE:
status_const = "SEC_E_INCOMPLETE_MESSAGE";
break;
case SEC_E_INSUFFICIENT_MEMORY:
status_const = "SEC_E_INSUFFICIENT_MEMORY";
break;
case SEC_E_INTERNAL_ERROR:
status_const = "SEC_E_INTERNAL_ERROR";
break;
case SEC_E_INVALID_HANDLE:
status_const = "SEC_E_INVALID_HANDLE";
break;
case SEC_E_INVALID_TOKEN:
status_const = "SEC_E_INVALID_TOKEN";
break;
case SEC_E_LOGON_DENIED:
status_const = "SEC_E_LOGON_DENIED";
break;
case SEC_E_MESSAGE_ALTERED:
status_const = "SEC_E_MESSAGE_ALTERED";
break;
case SEC_E_NO_AUTHENTICATING_AUTHORITY:
status_const = "SEC_E_NO_AUTHENTICATING_AUTHORITY";
break;
case SEC_E_NO_CREDENTIALS:
status_const = "SEC_E_NO_CREDENTIALS";
break;
case SEC_E_NOT_OWNER:
status_const = "SEC_E_NOT_OWNER";
break;
case SEC_E_OK:
status_const = "SEC_E_OK";
break;
case SEC_E_OUT_OF_SEQUENCE:
status_const = "SEC_E_OUT_OF_SEQUENCE";
break;
case SEC_E_QOP_NOT_SUPPORTED:
status_const = "SEC_E_QOP_NOT_SUPPORTED";
break;
case SEC_E_SECPKG_NOT_FOUND:
status_const = "SEC_E_SECPKG_NOT_FOUND";
break;
case SEC_E_TARGET_UNKNOWN:
status_const = "SEC_E_TARGET_UNKNOWN";
break;
case SEC_E_UNKNOWN_CREDENTIALS:
status_const = "SEC_E_UNKNOWN_CREDENTIALS";
break;
case SEC_E_UNSUPPORTED_FUNCTION:
status_const = "SEC_E_UNSUPPORTED_FUNCTION";
break;
case SEC_E_WRONG_PRINCIPAL:
status_const = "SEC_E_WRONG_PRINCIPAL";
break;
default:
status_const = "Unknown error";
}
return curl_maprintf("%s (0x%08X)", status_const, status);
}
/*
* Curl_sspi_status_msg(SECURITY_STATUS status)
*
* This function returns a message representing an SSPI status.
* It will in any case return a usable string pointer which needs to be freed.
*/
char*
Curl_sspi_status_msg(SECURITY_STATUS status)
{
LPSTR format_msg = NULL;
char *status_msg = NULL, *status_const = NULL;
int status_len = 0;
status_len = FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL, status, 0, (LPTSTR)&format_msg, 0, NULL);
if(status_len > 0 && format_msg) {
status_msg = strdup(format_msg);
LocalFree(format_msg);
/* remove trailing CR+LF */
if(status_len > 0) {
if(status_msg[status_len-1] == '\n') {
status_msg[status_len-1] = '\0';
if(status_len > 1) {
if(status_msg[status_len-2] == '\r') {
status_msg[status_len-2] = '\0';
}
}
}
}
}
status_const = Curl_sspi_status(status);
if(status_msg) {
status_msg = curl_maprintf("%s [%s]", status_msg, status_const);
free(status_const);
}
else {
status_msg = status_const;
}
return status_msg;
}
#endif /* USE_WINDOWS_SSPI */

View File

@ -63,6 +63,8 @@
CURLcode Curl_sspi_global_init(void);
void Curl_sspi_global_cleanup(void);
char* Curl_sspi_status(SECURITY_STATUS status);
char* Curl_sspi_status_msg(SECURITY_STATUS status);
/* Forward-declaration of global variables defined in curl_sspi.c */

View File

@ -53,98 +53,16 @@ static int check_sspi_err(struct SessionHandle *data,
SECURITY_STATUS minor_status,
const char* function)
{
const char *txt;
char *sspi_msg = NULL;
(void)minor_status;
if(major_status != SEC_E_OK &&
major_status != SEC_I_COMPLETE_AND_CONTINUE &&
major_status != SEC_I_COMPLETE_NEEDED &&
major_status != SEC_I_CONTINUE_NEEDED) {
failf(data, "SSPI error: %s failed: %d\n", function, major_status);
switch (major_status) {
case SEC_I_COMPLETE_AND_CONTINUE:
txt="SEC_I_COMPLETE_AND_CONTINUE";
break;
case SEC_I_COMPLETE_NEEDED:
txt="SEC_I_COMPLETE_NEEDED";
break;
case SEC_I_CONTINUE_NEEDED:
txt="SEC_I_CONTINUE_NEEDED";
break;
case SEC_I_CONTEXT_EXPIRED:
txt="SEC_I_CONTEXT_EXPIRED";
break;
case SEC_I_INCOMPLETE_CREDENTIALS:
txt="SEC_I_INCOMPLETE_CREDENTIALS";
break;
case SEC_I_RENEGOTIATE:
txt="SEC_I_RENEGOTIATE";
break;
case SEC_E_BUFFER_TOO_SMALL:
txt="SEC_E_BUFFER_TOO_SMALL";
break;
case SEC_E_CONTEXT_EXPIRED:
txt="SEC_E_CONTEXT_EXPIRED";
break;
case SEC_E_CRYPTO_SYSTEM_INVALID:
txt="SEC_E_CRYPTO_SYSTEM_INVALID";
break;
case SEC_E_INCOMPLETE_MESSAGE:
txt="SEC_E_INCOMPLETE_MESSAGE";
break;
case SEC_E_INSUFFICIENT_MEMORY:
txt="SEC_E_INSUFFICIENT_MEMORY";
break;
case SEC_E_INTERNAL_ERROR:
txt="SEC_E_INTERNAL_ERROR";
break;
case SEC_E_INVALID_HANDLE:
txt="SEC_E_INVALID_HANDLE";
break;
case SEC_E_INVALID_TOKEN:
txt="SEC_E_INVALID_TOKEN";
break;
case SEC_E_LOGON_DENIED:
txt="SEC_E_LOGON_DENIED";
break;
case SEC_E_MESSAGE_ALTERED:
txt="SEC_E_MESSAGE_ALTERED";
break;
case SEC_E_NO_AUTHENTICATING_AUTHORITY:
txt="SEC_E_NO_AUTHENTICATING_AUTHORITY";
break;
case SEC_E_NO_CREDENTIALS:
txt="SEC_E_NO_CREDENTIALS";
break;
case SEC_E_NOT_OWNER:
txt="SEC_E_NOT_OWNER";
break;
case SEC_E_OUT_OF_SEQUENCE:
txt="SEC_E_OUT_OF_SEQUENCE";
break;
case SEC_E_QOP_NOT_SUPPORTED:
txt="SEC_E_QOP_NOT_SUPPORTED";
break;
case SEC_E_SECPKG_NOT_FOUND:
txt="SEC_E_SECPKG_NOT_FOUND";
break;
case SEC_E_TARGET_UNKNOWN:
txt="SEC_E_TARGET_UNKNOWN";
break;
case SEC_E_UNKNOWN_CREDENTIALS:
txt="SEC_E_UNKNOWN_CREDENTIALS";
break;
case SEC_E_UNSUPPORTED_FUNCTION:
txt="SEC_E_UNSUPPORTED_FUNCTION";
break;
case SEC_E_WRONG_PRINCIPAL:
txt="SEC_E_WRONG_PRINCIPAL";
break;
default:
txt="Unknown error";
}
failf(data, "SSPI error: %s failed: %s\n", function, txt);
sspi_msg = Curl_sspi_status_msg(major_status);
failf(data, "SSPI error: %s failed: %s\n", function, sspi_msg);
free(sspi_msg);
return 1;
}
return 0;