schannel: Code cleanup and bug fixes

curl_sspi.c: Fixed mingw32-gcc compiler warnings
curl_sspi.c: Fixed length of error code hex output

The hex value was printed as signed 64-bit value on 64-bit systems:
SEC_E_WRONG_PRINCIPAL (0xFFFFFFFF80090322)

It is now correctly printed as the following:
SEC_E_WRONG_PRINCIPAL (0x80090322)

curl_sspi.c: Fallback to security function table version number
Instead of reporting an unknown version, the interface version is used.

curl_sspi.c: Removed SSPI/ version prefix from Curl_sspi_version
curl_schannel: Replaced static buffer sizes with defined names
curl_schannel.c: First brace when declaring functions on column 0
curl_schannel.c: Put the pointer sign directly at variable name
curl_schannel.c: Use structs directly instead of typedef'ed structs
curl_schannel.c: Removed space before opening brace
curl_schannel.c: Fixed lines being longer than 80 chars
This commit is contained in:
Marc Hoersken 2012-04-15 04:12:26 +02:00 committed by Daniel Stenberg
parent c1311c2b8f
commit 7047e2ed72
4 changed files with 75 additions and 52 deletions

View File

@ -79,15 +79,16 @@ static Curl_recv schannel_recv;
static Curl_send schannel_send; static Curl_send schannel_send;
static CURLcode static CURLcode
schannel_connect_step1(struct connectdata *conn, int sockindex) { schannel_connect_step1(struct connectdata *conn, int sockindex)
{
ssize_t write = -1; ssize_t write = -1;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf; SecBuffer outbuf;
SecBufferDesc outbuf_desc; SecBufferDesc outbuf_desc;
SCHANNEL_CRED schannel_cred; SCHANNEL_CRED schannel_cred;
SECURITY_STATUS sspi_status = SEC_E_OK; SECURITY_STATUS sspi_status = SEC_E_OK;
curl_schannel_cred *old_cred = NULL; struct curl_schannel_cred *old_cred = NULL;
char *sspi_msg = NULL; char *sspi_msg = NULL;
struct in_addr addr; struct in_addr addr;
#ifdef ENABLE_IPV6 #ifdef ENABLE_IPV6
@ -110,13 +111,13 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
if(data->set.ssl.verifypeer) { if(data->set.ssl.verifypeer) {
schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION | schannel_cred.dwFlags = SCH_CRED_AUTO_CRED_VALIDATION |
SCH_CRED_REVOCATION_CHECK_CHAIN; SCH_CRED_REVOCATION_CHECK_CHAIN;
infof(data, "schannel: checking server certificate and revocation\n"); infof(data, "schannel: checking server certificate revocation\n");
} }
else { else {
schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION | schannel_cred.dwFlags = SCH_CRED_MANUAL_CRED_VALIDATION |
SCH_CRED_IGNORE_NO_REVOCATION_CHECK | SCH_CRED_IGNORE_NO_REVOCATION_CHECK |
SCH_CRED_IGNORE_REVOCATION_OFFLINE; SCH_CRED_IGNORE_REVOCATION_OFFLINE;
infof(data, "schannel: disable server certificate and revocation checks\n"); infof(data, "schannel: disable server certificate revocation checks\n");
} }
if(Curl_inet_pton(AF_INET, conn->host.name, &addr) || if(Curl_inet_pton(AF_INET, conn->host.name, &addr) ||
@ -143,12 +144,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
} }
/* allocate memory for the re-usable credential handle */ /* allocate memory for the re-usable credential handle */
connssl->cred = malloc(sizeof(curl_schannel_cred)); connssl->cred = malloc(sizeof(struct curl_schannel_cred));
if (!connssl->cred) { if(!connssl->cred) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
memset(connssl->cred, 0, sizeof(curl_schannel_cred)); memset(connssl->cred, 0, sizeof(struct curl_schannel_cred));
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx */ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa374716.aspx */
sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL, sspi_status = s_pSecFn->AcquireCredentialsHandle(NULL,
@ -185,12 +186,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM; ISC_REQ_ALLOCATE_MEMORY | ISC_REQ_STREAM;
/* allocate memory for the security context handle */ /* allocate memory for the security context handle */
connssl->ctxt = malloc(sizeof(curl_schannel_ctxt)); connssl->ctxt = malloc(sizeof(struct curl_schannel_ctxt));
if (!connssl->ctxt) { if(!connssl->ctxt) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
return CURLE_OUT_OF_MEMORY; return CURLE_OUT_OF_MEMORY;
} }
memset(connssl->ctxt, 0, sizeof(curl_schannel_ctxt)); memset(connssl->ctxt, 0, sizeof(struct curl_schannel_ctxt));
/* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */ /* http://msdn.microsoft.com/en-us/library/windows/desktop/aa375924.aspx */
sspi_status = s_pSecFn->InitializeSecurityContext( sspi_status = s_pSecFn->InitializeSecurityContext(
@ -232,11 +233,12 @@ schannel_connect_step1(struct connectdata *conn, int sockindex) {
} }
static CURLcode static CURLcode
schannel_connect_step2(struct connectdata *conn, int sockindex) { schannel_connect_step2(struct connectdata *conn, int sockindex)
{
int i; int i;
ssize_t read = -1, write = -1; ssize_t read = -1, write = -1;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data* connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
SecBuffer outbuf[2]; SecBuffer outbuf[2];
SecBufferDesc outbuf_desc; SecBufferDesc outbuf_desc;
SecBuffer inbuf[2]; SecBuffer inbuf[2];
@ -250,7 +252,7 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
/* buffer to store previously received and encrypted data */ /* buffer to store previously received and encrypted data */
if(connssl->encdata_buffer == NULL) { if(connssl->encdata_buffer == NULL) {
connssl->encdata_offset = 0; connssl->encdata_offset = 0;
connssl->encdata_length = 4096; connssl->encdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->encdata_buffer = malloc(connssl->encdata_length); connssl->encdata_buffer = malloc(connssl->encdata_length);
if(connssl->encdata_buffer == NULL) { if(connssl->encdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
@ -401,11 +403,12 @@ schannel_connect_step2(struct connectdata *conn, int sockindex) {
} }
static CURLcode static CURLcode
schannel_connect_step3(struct connectdata *conn, int sockindex) { schannel_connect_step3(struct connectdata *conn, int sockindex)
{
CURLcode retcode = CURLE_OK; CURLcode retcode = CURLE_OK;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
curl_schannel_cred *old_cred = NULL; struct curl_schannel_cred *old_cred = NULL;
int incache; int incache;
DEBUGASSERT(ssl_connect_3 == connssl->connecting_state); DEBUGASSERT(ssl_connect_3 == connssl->connecting_state);
@ -441,7 +444,7 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) {
} }
if(!incache) { if(!incache) {
retcode = Curl_ssl_addsessionid(conn, (void*)connssl->cred, retcode = Curl_ssl_addsessionid(conn, (void*)connssl->cred,
sizeof(curl_schannel_cred)); sizeof(struct curl_schannel_cred));
if(retcode) { if(retcode) {
failf(data, "schannel: failed to store credential handle\n"); failf(data, "schannel: failed to store credential handle\n");
return retcode; return retcode;
@ -458,7 +461,8 @@ schannel_connect_step3(struct connectdata *conn, int sockindex) {
static CURLcode static CURLcode
schannel_connect_common(struct connectdata *conn, int sockindex, schannel_connect_common(struct connectdata *conn, int sockindex,
bool nonblocking, bool *done) { bool nonblocking, bool *done)
{
CURLcode retcode; CURLcode retcode;
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@ -568,7 +572,8 @@ schannel_connect_common(struct connectdata *conn, int sockindex,
static ssize_t static ssize_t
schannel_send(struct connectdata *conn, int sockindex, schannel_send(struct connectdata *conn, int sockindex,
const void *buf, size_t len, CURLcode *err) { const void *buf, size_t len, CURLcode *err)
{
ssize_t ret = -1; ssize_t ret = -1;
size_t data_len = 0; size_t data_len = 0;
unsigned char *data = NULL; unsigned char *data = NULL;
@ -652,7 +657,8 @@ schannel_send(struct connectdata *conn, int sockindex,
static ssize_t static ssize_t
schannel_recv(struct connectdata *conn, int sockindex, schannel_recv(struct connectdata *conn, int sockindex,
char *buf, size_t len, CURLcode *err) { char *buf, size_t len, CURLcode *err)
{
size_t size = 0; size_t size = 0;
ssize_t read = 0, ret = -1; ssize_t read = 0, ret = -1;
CURLcode retcode; CURLcode retcode;
@ -670,7 +676,7 @@ schannel_recv(struct connectdata *conn, int sockindex,
/* buffer to store previously received and decrypted data */ /* buffer to store previously received and decrypted data */
if(connssl->decdata_buffer == NULL) { if(connssl->decdata_buffer == NULL) {
connssl->decdata_offset = 0; connssl->decdata_offset = 0;
connssl->decdata_length = 4096; connssl->decdata_length = CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->decdata_buffer = malloc(connssl->decdata_length); connssl->decdata_buffer = malloc(connssl->decdata_length);
if(connssl->decdata_buffer == NULL) { if(connssl->decdata_buffer == NULL) {
failf(data, "schannel: unable to allocate memory"); failf(data, "schannel: unable to allocate memory");
@ -679,10 +685,10 @@ schannel_recv(struct connectdata *conn, int sockindex,
} }
/* increase buffer in order to fit the requested amount of data */ /* increase buffer in order to fit the requested amount of data */
while(connssl->encdata_length - connssl->encdata_offset < 2048 || while(connssl->encdata_length - connssl->encdata_offset <
connssl->encdata_length < len) { CURL_SCHANNEL_BUFFER_STEP_SIZE || connssl->encdata_length < len) {
/* increase internal encrypted data buffer */ /* increase internal encrypted data buffer */
connssl->encdata_length += 2048; connssl->encdata_length += CURL_SCHANNEL_BUFFER_STEP_SIZE;
connssl->encdata_buffer = realloc(connssl->encdata_buffer, connssl->encdata_buffer = realloc(connssl->encdata_buffer,
connssl->encdata_length); connssl->encdata_length);
if(connssl->encdata_buffer == NULL) { if(connssl->encdata_buffer == NULL) {
@ -760,7 +766,8 @@ schannel_recv(struct connectdata *conn, int sockindex,
infof(data, "schannel: decrypted data length: %d\n", inbuf[1].cbBuffer); infof(data, "schannel: decrypted data length: %d\n", inbuf[1].cbBuffer);
/* increase buffer in order to fit the received amount of data */ /* increase buffer in order to fit the received amount of data */
size = inbuf[1].cbBuffer > 2048 ? inbuf[1].cbBuffer : 2048; size = inbuf[1].cbBuffer > CURL_SCHANNEL_BUFFER_STEP_SIZE ?
inbuf[1].cbBuffer : CURL_SCHANNEL_BUFFER_STEP_SIZE;
while(connssl->decdata_length - connssl->decdata_offset < size || while(connssl->decdata_length - connssl->decdata_offset < size ||
connssl->decdata_length < len) { connssl->decdata_length < len) {
/* increase internal decrypted data buffer */ /* increase internal decrypted data buffer */
@ -839,15 +846,17 @@ schannel_recv(struct connectdata *conn, int sockindex,
} }
/* reduce internal buffer length to reduce memory usage */ /* reduce internal buffer length to reduce memory usage */
if(connssl->encdata_length > 4096) { if(connssl->encdata_length > CURL_SCHANNEL_BUFFER_INIT_SIZE) {
connssl->encdata_length = connssl->encdata_offset > 4096 ? connssl->encdata_length =
connssl->encdata_offset : 4096; connssl->encdata_offset > CURL_SCHANNEL_BUFFER_INIT_SIZE ?
connssl->encdata_offset : CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->encdata_buffer = realloc(connssl->encdata_buffer, connssl->encdata_buffer = realloc(connssl->encdata_buffer,
connssl->encdata_length); connssl->encdata_length);
} }
if(connssl->decdata_length > 4096) { if(connssl->decdata_length > CURL_SCHANNEL_BUFFER_INIT_SIZE) {
connssl->decdata_length = connssl->decdata_offset > 4096 ? connssl->decdata_length =
connssl->decdata_offset : 4096; connssl->decdata_offset > CURL_SCHANNEL_BUFFER_INIT_SIZE ?
connssl->decdata_offset : CURL_SCHANNEL_BUFFER_INIT_SIZE;
connssl->decdata_buffer = realloc(connssl->decdata_buffer, connssl->decdata_buffer = realloc(connssl->decdata_buffer,
connssl->decdata_length); connssl->decdata_length);
} }
@ -875,12 +884,14 @@ schannel_recv(struct connectdata *conn, int sockindex,
CURLcode CURLcode
Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex, Curl_schannel_connect_nonblocking(struct connectdata *conn, int sockindex,
bool *done) { bool *done)
{
return schannel_connect_common(conn, sockindex, TRUE, done); return schannel_connect_common(conn, sockindex, TRUE, done);
} }
CURLcode CURLcode
Curl_schannel_connect(struct connectdata *conn, int sockindex) { Curl_schannel_connect(struct connectdata *conn, int sockindex)
{
CURLcode retcode; CURLcode retcode;
bool done = FALSE; bool done = FALSE;
@ -893,7 +904,8 @@ Curl_schannel_connect(struct connectdata *conn, int sockindex) {
return CURLE_OK; return CURLE_OK;
} }
bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex) { bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex)
{
const struct ssl_connect_data *connssl = &conn->ssl[sockindex]; const struct ssl_connect_data *connssl = &conn->ssl[sockindex];
if(connssl->use) /* SSL is in use */ if(connssl->use) /* SSL is in use */
@ -903,7 +915,8 @@ bool Curl_schannel_data_pending(const struct connectdata *conn, int sockindex) {
return FALSE; return FALSE;
} }
void Curl_schannel_close(struct connectdata *conn, int sockindex) { void Curl_schannel_close(struct connectdata *conn, int sockindex)
{
struct SessionHandle *data = conn->data; struct SessionHandle *data = conn->data;
struct ssl_connect_data *connssl = &conn->ssl[sockindex]; struct ssl_connect_data *connssl = &conn->ssl[sockindex];
@ -934,12 +947,14 @@ void Curl_schannel_close(struct connectdata *conn, int sockindex) {
} }
} }
int Curl_schannel_shutdown(struct connectdata *conn, int sockindex) { int Curl_schannel_shutdown(struct connectdata *conn, int sockindex)
{
return CURLE_NOT_BUILT_IN; /* TODO: implement SSL/TLS shutdown */ return CURLE_NOT_BUILT_IN; /* TODO: implement SSL/TLS shutdown */
} }
void Curl_schannel_session_free(void *ptr) { void Curl_schannel_session_free(void *ptr)
curl_schannel_cred *cred = ptr; {
struct curl_schannel_cred *cred = ptr;
if(cred) { if(cred) {
s_pSecFn->FreeCredentialsHandle(&cred->cred_handle); s_pSecFn->FreeCredentialsHandle(&cred->cred_handle);
@ -947,18 +962,20 @@ void Curl_schannel_session_free(void *ptr) {
} }
} }
int Curl_schannel_init() { int Curl_schannel_init()
{
return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0); return (Curl_sspi_global_init() == CURLE_OK ? 1 : 0);
} }
void Curl_schannel_cleanup() { void Curl_schannel_cleanup()
{
Curl_sspi_global_cleanup(); Curl_sspi_global_cleanup();
} }
size_t Curl_schannel_version(char *buffer, size_t size) size_t Curl_schannel_version(char *buffer, size_t size)
{ {
char* version = Curl_sspi_version(); char *version = Curl_sspi_version();
size = snprintf(buffer, size, "Schannel-%s", version); size = snprintf(buffer, size, "Schannel/%s", version);
free(version); free(version);
return size; return size;
} }

View File

@ -93,6 +93,10 @@
#endif #endif
#define CURL_SCHANNEL_BUFFER_INIT_SIZE 4096
#define CURL_SCHANNEL_BUFFER_STEP_SIZE 2048
CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex); CURLcode Curl_schannel_connect(struct connectdata *conn, int sockindex);
CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn, CURLcode Curl_schannel_connect_nonblocking(struct connectdata *conn,

View File

@ -133,6 +133,7 @@ Curl_sspi_version()
LPTSTR path = NULL; LPTSTR path = NULL;
LPVOID data = NULL; LPVOID data = NULL;
DWORD size, handle; DWORD size, handle;
UINT length;
if(s_hSecDll) { if(s_hSecDll) {
path = malloc(MAX_PATH); path = malloc(MAX_PATH);
@ -143,8 +144,8 @@ Curl_sspi_version()
data = malloc(size); data = malloc(size);
if(data) { if(data) {
if(GetFileVersionInfo(path, handle, size, data)) { if(GetFileVersionInfo(path, handle, size, data)) {
if(VerQueryValue(data, "\\", &version_info, &handle)) { if(VerQueryValue(data, "\\", (LPVOID*)&version_info, &length)) {
version = curl_maprintf("SSPI/%d.%d.%d.%d", version = curl_maprintf("%d.%d.%d.%d",
(version_info->dwProductVersionMS>>16)&0xffff, (version_info->dwProductVersionMS>>16)&0xffff,
(version_info->dwProductVersionMS>>0)&0xffff, (version_info->dwProductVersionMS>>0)&0xffff,
(version_info->dwProductVersionLS>>16)&0xffff, (version_info->dwProductVersionLS>>16)&0xffff,
@ -158,7 +159,7 @@ Curl_sspi_version()
free(path); free(path);
} }
if(!version) if(!version)
version = strdup("SSPI/Unknown"); version = curl_maprintf("%d", s_pSecFn ? s_pSecFn->dwVersion : 0);
} }
if(!version) if(!version)
@ -265,7 +266,8 @@ Curl_sspi_status(SECURITY_STATUS status)
status_const = "Unknown error"; status_const = "Unknown error";
} }
return curl_maprintf("%s (0x%08X)", status_const, status); return curl_maprintf("%s (0x%04X%04X)", status_const,
(status>>16)&0xffff, status&0xffff);
} }

View File

@ -222,15 +222,15 @@ enum protection_level {
#ifdef USE_SCHANNEL #ifdef USE_SCHANNEL
/* Structs to store Schannel handles */ /* Structs to store Schannel handles */
typedef struct curl_schannel_cred { struct curl_schannel_cred {
CredHandle cred_handle; CredHandle cred_handle;
TimeStamp time_stamp; TimeStamp time_stamp;
} curl_schannel_cred; };
typedef struct curl_schannel_ctxt { struct curl_schannel_ctxt {
CtxtHandle ctxt_handle; CtxtHandle ctxt_handle;
TimeStamp time_stamp; TimeStamp time_stamp;
} curl_schannel_ctxt; };
#endif #endif
/* enum for the nonblocking SSL connection state machine */ /* enum for the nonblocking SSL connection state machine */
@ -302,8 +302,8 @@ struct ssl_connect_data {
SSL* ssl; SSL* ssl;
#endif /* USE_AXTLS */ #endif /* USE_AXTLS */
#ifdef USE_SCHANNEL #ifdef USE_SCHANNEL
curl_schannel_cred *cred; struct curl_schannel_cred *cred;
curl_schannel_ctxt *ctxt; struct curl_schannel_ctxt *ctxt;
SecPkgContext_StreamSizes stream_sizes; SecPkgContext_StreamSizes stream_sizes;
ssl_connect_state connecting_state; ssl_connect_state connecting_state;
size_t encdata_length, decdata_length; size_t encdata_length, decdata_length;