wolf SSL / wolfSSL-TLS13-Beta

Fork of wolfSSL by wolf SSL

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers logging.c Source File

logging.c

00001 /* logging.c
00002  *
00003  * Copyright (C) 2006-2016 wolfSSL Inc.
00004  *
00005  * This file is part of wolfSSL.
00006  *
00007  * wolfSSL is free software; you can redistribute it and/or modify
00008  * it under the terms of the GNU General Public License as published by
00009  * the Free Software Foundation; either version 2 of the License, or
00010  * (at your option) any later version.
00011  *
00012  * wolfSSL is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
00015  * GNU General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU General Public License
00018  * along with this program; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1335, USA
00020  */
00021 
00022 
00023 #ifdef HAVE_CONFIG_H
00024     #include <config.h>
00025 #endif
00026 
00027 #include <wolfssl/wolfcrypt/settings.h>
00028 
00029 /* submitted by eof */
00030 
00031 #include <wolfssl/wolfcrypt/logging.h>
00032 #include <wolfssl/wolfcrypt/error-crypt.h>
00033 
00034 
00035 #ifdef __cplusplus
00036     extern "C" {
00037 #endif
00038     WOLFSSL_API int  wolfSSL_Debugging_ON(void);
00039     WOLFSSL_API void wolfSSL_Debugging_OFF(void);
00040 #ifdef __cplusplus
00041     }
00042 #endif
00043 
00044 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00045 static wolfSSL_Mutex debug_mutex; /* mutex for access to debug structure */
00046 
00047 /* accessing any node from the queue should be wrapped in a lock of
00048  * debug_mutex */
00049 static void* wc_error_heap;
00050 struct wc_error_queue {
00051     void*  heap; /* the heap hint used with nodes creation */
00052     struct wc_error_queue* next;
00053     struct wc_error_queue* prev;
00054     char   error[WOLFSSL_MAX_ERROR_SZ];
00055     char   file[WOLFSSL_MAX_ERROR_SZ];
00056     int    value;
00057     int    line;
00058 };
00059 volatile struct wc_error_queue* wc_errors;
00060 static struct wc_error_queue* wc_last_node;
00061 /* pointer to last node in queue to make insertion O(1) */
00062 #endif
00063 
00064 
00065 
00066 #if defined(DEBUG_WOLFSSL)
00067 
00068 /* Set these to default values initially. */
00069 static wolfSSL_Logging_cb log_function = NULL;
00070 static int loggingEnabled = 0;
00071 
00072 #endif /* DEBUG_WOLFSSL */
00073 
00074 
00075 int wolfSSL_SetLoggingCb(wolfSSL_Logging_cb f)
00076 {
00077 #ifdef DEBUG_WOLFSSL
00078     int res = 0;
00079 
00080     if (f)
00081         log_function = f;
00082     else
00083         res = BAD_FUNC_ARG;
00084 
00085     return res;
00086 #else
00087     (void)f;
00088     return NOT_COMPILED_IN;
00089 #endif
00090 }
00091 
00092 
00093 int wolfSSL_Debugging_ON(void)
00094 {
00095 #ifdef DEBUG_WOLFSSL
00096     loggingEnabled = 1;
00097     return 0;
00098 #else
00099     return NOT_COMPILED_IN;
00100 #endif
00101 }
00102 
00103 
00104 void wolfSSL_Debugging_OFF(void)
00105 {
00106 #ifdef DEBUG_WOLFSSL
00107     loggingEnabled = 0;
00108 #endif
00109 }
00110 
00111 
00112 #ifdef DEBUG_WOLFSSL
00113 
00114 #if defined(FREESCALE_MQX) || defined(FREESCALE_KSDK_MQX)
00115     #if MQX_USE_IO_OLD
00116         #include <fio.h>
00117     #else
00118         #include <nio.h>
00119     #endif
00120 #else
00121     #include <stdio.h>   /* for default printf stuff */
00122 #endif
00123 
00124 #ifdef THREADX
00125     int dc_log_printf(char*, ...);
00126 #endif
00127 
00128 static void wolfssl_log(const int logLevel, const char *const logMessage)
00129 {
00130     if (log_function)
00131         log_function(logLevel, logMessage);
00132     else {
00133         if (loggingEnabled) {
00134 #ifdef THREADX
00135             dc_log_printf("%s\n", logMessage);
00136 #elif defined(MICRIUM)
00137         #if (NET_SECURE_MGR_CFG_EN == DEF_ENABLED)
00138             NetSecure_TraceOut((CPU_CHAR *)logMessage);
00139         #endif
00140 #elif defined(WOLFSSL_MDK_ARM)
00141             fflush(stdout) ;
00142             printf("%s\n", logMessage);
00143             fflush(stdout) ;
00144 #elif defined(WOLFSSL_LOG_PRINTF)
00145             printf("%s\n", logMessage);
00146 #elif defined(WOLFSSL_UTASKER)
00147             fnDebugMsg((char*)logMessage);
00148             fnDebugMsg("\r\n");
00149 #else
00150             fprintf(stderr, "%s\n", logMessage);
00151 #endif
00152         }
00153     }
00154 }
00155 
00156 
00157 void WOLFSSL_MSG(const char* msg)
00158 {
00159     if (loggingEnabled)
00160         wolfssl_log(INFO_LOG , msg);
00161 }
00162 
00163 
00164 void WOLFSSL_BUFFER(const byte* buffer, word32 length)
00165 {
00166     #define LINE_LEN 16
00167 
00168     if (loggingEnabled) {
00169         word32 i;
00170         char line[80];
00171 
00172         if (!buffer) {
00173             wolfssl_log(INFO_LOG, "\tNULL");
00174 
00175             return;
00176         }
00177 
00178         sprintf(line, "\t");
00179 
00180         for (i = 0; i < LINE_LEN; i++) {
00181             if (i < length)
00182                 sprintf(line + 1 + i * 3,"%02x ", buffer[i]);
00183             else
00184                 sprintf(line + 1 + i * 3, "   ");
00185         }
00186 
00187         sprintf(line + 1 + LINE_LEN * 3, "| ");
00188 
00189         for (i = 0; i < LINE_LEN; i++)
00190             if (i < length)
00191                 sprintf(line + 3 + LINE_LEN * 3 + i,
00192                      "%c", 31 < buffer[i] && buffer[i] < 127 ? buffer[i] : '.');
00193 
00194         wolfssl_log(INFO_LOG, line);
00195 
00196         if (length > LINE_LEN)
00197             WOLFSSL_BUFFER(buffer + LINE_LEN, length - LINE_LEN);
00198     }
00199 }
00200 
00201 
00202 void WOLFSSL_ENTER(const char* msg)
00203 {
00204     if (loggingEnabled) {
00205         char buffer[80];
00206         sprintf(buffer, "wolfSSL Entering %s", msg);
00207         wolfssl_log(ENTER_LOG , buffer);
00208     }
00209 }
00210 
00211 
00212 void WOLFSSL_LEAVE(const char* msg, int ret)
00213 {
00214     if (loggingEnabled) {
00215         char buffer[80];
00216         sprintf(buffer, "wolfSSL Leaving %s, return %d", msg, ret);
00217         wolfssl_log(LEAVE_LOG , buffer);
00218     }
00219 }
00220 #endif  /* DEBUG_WOLFSSL */
00221 
00222 /*
00223  * When using OPENSSL_EXTRA or DEBUG_WOLFSSL_VERBOSE macro then WOLFSSL_ERROR is
00224  * mapped to new funtion WOLFSSL_ERROR_LINE which gets the line # and function
00225  * name where WOLFSSL_ERROR is called at.
00226  */
00227 #if (defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX)) || defined(WOLFSSL_HAPROXY)
00228     #if (defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE))
00229 void WOLFSSL_ERROR_LINE(int error, const char* func, unsigned int line,
00230             const char* file, void* usrCtx)
00231     #else
00232 void WOLFSSL_ERROR(int error)
00233     #endif
00234 {
00235     #if defined(DEBUG_WOLFSSL) && !defined(WOLFSSL_NGINX)
00236     if (loggingEnabled && error != WC_PENDING_E)
00237     #endif
00238     {
00239         char buffer[80];
00240         #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00241             (void)usrCtx; /* a user ctx for future flexibility */
00242             (void)func;
00243 
00244             if (wc_LockMutex(&debug_mutex) != 0) {
00245                 WOLFSSL_MSG("Lock debug mutex failed");
00246                 sprintf(buffer, "wolfSSL error occurred, error = %d", error);
00247             }
00248             else {
00249                 if (error < 0) error = error - (2*error); /*get absolute value*/
00250                 sprintf(buffer, "wolfSSL error occurred, error = %d line:%d file:%s",
00251                     error, line, file);
00252                 if (wc_AddErrorNode(error, line, buffer, (char*)file) != 0) {
00253                     WOLFSSL_MSG("Error creating logging node");
00254                     /* with void function there is no return here, continue on
00255                      * to unlock mutex and log what buffer was created. */
00256                 }
00257 
00258                 wc_UnLockMutex(&debug_mutex);
00259             }
00260         #else
00261             sprintf(buffer, "wolfSSL error occurred, error = %d", error);
00262         #endif
00263         #ifdef DEBUG_WOLFSSL
00264         wolfssl_log(ERROR_LOG , buffer);
00265         #endif
00266     }
00267 }
00268 
00269 #endif  /* DEBUG_WOLFSSL || WOLFSSL_NGINX || WOLFSSL_HAPROXY */
00270 
00271 #if defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE)
00272 /* Internal function that is called by wolfCrypt_Init() */
00273 int wc_LoggingInit(void)
00274 {
00275     if (wc_InitMutex(&debug_mutex) != 0) {
00276         WOLFSSL_MSG("Bad Init Mutex");
00277         return BAD_MUTEX_E;
00278     }
00279     wc_errors          = NULL;
00280     wc_last_node       = NULL;
00281 
00282     return 0;
00283 }
00284 
00285 
00286 /* internal function that is called by wolfCrypt_Cleanup */
00287 int wc_LoggingCleanup(void)
00288 {
00289     /* clear logging entries */
00290     wc_ClearErrorNodes();
00291 
00292     /* free mutex */
00293     if (wc_FreeMutex(&debug_mutex) != 0) {
00294         WOLFSSL_MSG("Bad Mutex free");
00295         return BAD_MUTEX_E;
00296     }
00297     return 0;
00298 }
00299 
00300 
00301 #if defined(DEBUG_WOLFSSL) || defined(WOLFSSL_NGINX) || defined(WOLFSSL_HAPROXY)
00302 /* peek at an error node
00303  *
00304  * idx : if -1 then the most recent node is looked at, otherwise search
00305  *         through queue for node at the given index
00306  * file  : pointer to internal file string
00307  * reason : pointer to internal error reason
00308  * line  : line number that error happened at
00309  *
00310  * Returns a negative value in error case, on success returns the nodes error
00311  * value which is positve (absolute value)
00312  */
00313 int wc_PeekErrorNode(int idx, const char **file, const char **reason,
00314         int *line)
00315 {
00316     struct wc_error_queue* err;
00317 
00318     if (wc_LockMutex(&debug_mutex) != 0) {
00319         WOLFSSL_MSG("Lock debug mutex failed");
00320         return BAD_MUTEX_E;
00321     }
00322 
00323     if (idx < 0) {
00324         err = wc_last_node;
00325         if (err == NULL) {
00326             WOLFSSL_MSG("No Errors in queue");
00327             wc_UnLockMutex(&debug_mutex);
00328             return BAD_STATE_E;
00329         }
00330     }
00331     else {
00332         int i;
00333 
00334         err = (struct wc_error_queue*)wc_errors;
00335         for (i = 0; i < idx; i++) {
00336             if (err == NULL) {
00337                 WOLFSSL_MSG("Error node not found. Bad index?");
00338                 wc_UnLockMutex(&debug_mutex);
00339                 return BAD_FUNC_ARG;
00340             }
00341             err = err->next;
00342         }
00343     }
00344 
00345     if (file != NULL) {
00346         *file = err->file;
00347     }
00348 
00349     if (reason != NULL) {
00350         *reason = err->error;
00351     }
00352 
00353     if (line != NULL) {
00354         *line = err->line;
00355     }
00356 
00357     wc_UnLockMutex(&debug_mutex);
00358 
00359     return err->value;
00360 }
00361 
00362 
00363 /* create new error node and add it to the queue
00364  * buffers are assumed to be of size WOLFSSL_MAX_ERROR_SZ for this internal
00365  * function. debug_mutex should be locked before a call to this function. */
00366 int wc_AddErrorNode(int error, int line, char* buf, char* file)
00367 {
00368 
00369     struct wc_error_queue* err;
00370 
00371     err = (struct wc_error_queue*)XMALLOC(
00372             sizeof(struct wc_error_queue), wc_error_heap, DYNAMIC_TYPE_LOG);
00373     if (err == NULL) {
00374         WOLFSSL_MSG("Unable to create error node for log");
00375         return MEMORY_E;
00376     }
00377     else {
00378         int sz;
00379 
00380         XMEMSET(err, 0, sizeof(struct wc_error_queue));
00381         err->heap = wc_error_heap;
00382         sz = (int)XSTRLEN(buf);
00383         if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
00384             sz = WOLFSSL_MAX_ERROR_SZ - 1;
00385         }
00386         if (sz > 0) {
00387             XMEMCPY(err->error, buf, sz);
00388         }
00389 
00390         sz = (int)XSTRLEN(file);
00391         if (sz > WOLFSSL_MAX_ERROR_SZ - 1) {
00392             sz = WOLFSSL_MAX_ERROR_SZ - 1;
00393         }
00394         if (sz > 0) {
00395             XMEMCPY(err->file, file, sz);
00396         }
00397 
00398         err->value = error;
00399         err->line  = line;
00400 
00401         /* make sure is terminated */
00402         err->error[WOLFSSL_MAX_ERROR_SZ - 1] = '\0';
00403         err->file[WOLFSSL_MAX_ERROR_SZ - 1]  = '\0';
00404 
00405 
00406         /* since is queue place new node at last of the list */
00407         if (wc_last_node == NULL) {
00408             /* case of first node added to queue */
00409             if (wc_errors != NULL) {
00410                 /* check for unexpected case before over writing wc_errors */
00411                 WOLFSSL_MSG("ERROR in adding new node to logging queue!!\n");
00412             }
00413             else {
00414                 wc_errors    = err;
00415                 wc_last_node = err;
00416             }
00417         }
00418         else {
00419             wc_last_node->next = err;
00420             err->prev = wc_last_node;
00421             wc_last_node = err;
00422         }
00423     }
00424 
00425     return 0;
00426 }
00427 
00428 /* Removes the error node at the specified index.
00429  * idx : if -1 then the most recent node is looked at, otherwise search
00430  *         through queue for node at the given index
00431  */
00432 void wc_RemoveErrorNode(int idx)
00433 {
00434     struct wc_error_queue* current;
00435 
00436     if (wc_LockMutex(&debug_mutex) != 0) {
00437         WOLFSSL_MSG("Lock debug mutex failed");
00438         return;
00439     }
00440 
00441     if (idx == -1)
00442         current = wc_last_node;
00443     else {
00444         current = (struct wc_error_queue*)wc_errors;
00445         for (; current != NULL && idx > 0; idx--)
00446              current = current->next;
00447     }
00448     if (current != NULL) {
00449         if (current->prev != NULL)
00450             current->prev->next = current->next;
00451         if (wc_last_node == current)
00452             wc_last_node = current->prev;
00453         if (wc_errors == current)
00454             wc_errors = current->next;
00455         XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00456     }
00457 
00458     wc_UnLockMutex(&debug_mutex);
00459 }
00460 
00461 #endif /* DEBUG_WOLFSSL || WOLFSSL_NGINX */
00462 
00463 /* Clears out the list of error nodes.
00464  */
00465 void wc_ClearErrorNodes(void)
00466 {
00467     if (wc_LockMutex(&debug_mutex) != 0) {
00468         WOLFSSL_MSG("Lock debug mutex failed");
00469         return;
00470     }
00471 
00472     /* free all nodes from error queue */
00473     {
00474         struct wc_error_queue* current;
00475         struct wc_error_queue* next;
00476 
00477         current = (struct wc_error_queue*)wc_errors;
00478         while (current != NULL) {
00479             next = current->next;
00480             XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00481             current = next;
00482         }
00483     }
00484 
00485     wc_errors    = NULL;
00486     wc_last_node = NULL;
00487     wc_UnLockMutex(&debug_mutex);
00488 }
00489 
00490 int wc_SetLoggingHeap(void* h)
00491 {
00492     if (wc_LockMutex(&debug_mutex) != 0) {
00493         WOLFSSL_MSG("Lock debug mutex failed");
00494         return BAD_MUTEX_E;
00495     }
00496     wc_error_heap = h;
00497     wc_UnLockMutex(&debug_mutex);
00498     return 0;
00499 }
00500 
00501 #if !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM)
00502 /* empties out the error queue into the file */
00503 void wc_ERR_print_errors_fp(FILE* fp)
00504 {
00505     WOLFSSL_ENTER("wc_ERR_print_errors_fp");
00506 
00507     if (wc_LockMutex(&debug_mutex) != 0) {
00508         WOLFSSL_MSG("Lock debug mutex failed");
00509     }
00510     else {
00511         /* free all nodes from error queue and print them to file */
00512         {
00513             struct wc_error_queue* current;
00514             struct wc_error_queue* next;
00515 
00516             current = (struct wc_error_queue*)wc_errors;
00517             while (current != NULL) {
00518                 next = current->next;
00519                 fprintf(fp, "%s\n", current->error);
00520                 XFREE(current, current->heap, DYNAMIC_TYPE_LOG);
00521                 current = next;
00522             }
00523 
00524             /* set global pointers to match having been freed */
00525             wc_errors    = NULL;
00526             wc_last_node = NULL;
00527         }
00528 
00529         wc_UnLockMutex(&debug_mutex);
00530     }
00531 }
00532 #endif /* !defined(NO_FILESYSTEM) && !defined(NO_STDIO_FILESYSTEM) */
00533 
00534 #endif /* defined(OPENSSL_EXTRA) || defined(DEBUG_WOLFSSL_VERBOSE) */
00535 
00536