]> granicus.if.org Git - curl/commitdiff
sspi: Refactored socks_sspi and schannel to use same error message functions
authorMarc Hoersken <info@marc-hoersken.de>
Wed, 11 Apr 2012 15:25:26 +0000 (17:25 +0200)
committerDaniel Stenberg <daniel@haxx.se>
Mon, 11 Jun 2012 17:00:34 +0000 (19:00 +0200)
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.

lib/curl_schannel.c
lib/curl_sspi.c
lib/curl_sspi.h
lib/socks_sspi.c

index 0ad1145f21b53ccddbb719d8173be1a8b2d33903..3de8e7c01eb28b91793cf257f1c042e915eef2a0 100644 (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;
   }
index b985dbceb0a430c56924cae63cbaed52eb5b3239..d915710f8b7913f005105f79ad0dfe6793c87840 100644 (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 */
index c0e4f368f1071b9897c39c5e4c50bfe176f0f39d..8174878306f871313fc2ea7a52d6bf7d58785b5d 100644 (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 */
 
index d96a82e8a93f4b986e04773ee2a06a0a726621fb..1e724bb06e4144af99eaf7d63176fc5cc94b7b76 100644 (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;