]> git.sur5r.net Git - freertos/blobdiff - FreeRTOS-Plus/CyaSSL/src/crl.c
Prepare for V7.2.0 release.
[freertos] / FreeRTOS-Plus / CyaSSL / src / crl.c
index 561d573bf1940b1254d153a6914d2ef7bc112ead..40759a4f1d1ce5cd7c9ba5a95e980b24de2a8463 100644 (file)
 /* Initialze CRL members */
 int InitCRL(CYASSL_CRL* crl, CYASSL_CERT_MANAGER* cm)
 {
-       CYASSL_ENTER("InitCRL");
-
-       crl->cm = cm;
-       crl->crlList = NULL;
-       if (InitMutex(&crl->crlLock) != 0)
-               return BAD_MUTEX_ERROR; 
+    CYASSL_ENTER("InitCRL");
+
+    crl->cm = cm;
+    crl->crlList = NULL;
+    crl->monitors[0].path = NULL;
+    crl->monitors[1].path = NULL;
+#ifdef HAVE_CRL_MONITOR
+    crl->tid = 0;
+#endif
+    if (InitMutex(&crl->crlLock) != 0)
+        return BAD_MUTEX_ERROR; 
 
-       return 0;
+    return 0;
 }
 
 
 /* Initialze CRL Entry */
 static int InitCRL_Entry(CRL_Entry* crle, DecodedCRL* dcrl)
 {
-       CYASSL_ENTER("FreeCRL_Entry");
+    CYASSL_ENTER("InitCRL_Entry");
 
-       XMEMCPY(crle->issuerHash, dcrl->issuerHash, SHA_DIGEST_SIZE);
-       XMEMCPY(crle->crlHash, dcrl->crlHash, MD5_DIGEST_SIZE);
-       XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
-       XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
+    XMEMCPY(crle->issuerHash, dcrl->issuerHash, SHA_DIGEST_SIZE);
+    XMEMCPY(crle->crlHash, dcrl->crlHash, MD5_DIGEST_SIZE);
+    XMEMCPY(crle->lastDate, dcrl->lastDate, MAX_DATE_SIZE);
+    XMEMCPY(crle->nextDate, dcrl->nextDate, MAX_DATE_SIZE);
+    crle->lastDateFormat = dcrl->lastDateFormat;
+    crle->nextDateFormat = dcrl->nextDateFormat;
 
-       crle->certs = dcrl->certs;   /* take ownsership */
-       dcrl->certs = NULL;
-       crle->totalCerts = dcrl->totalCerts;
+    crle->certs = dcrl->certs;   /* take ownsership */
+    dcrl->certs = NULL;
+    crle->totalCerts = dcrl->totalCerts;
 
-       return 0;
+    return 0;
 }
 
 
 /* Free all CRL Entry resources */
 static void FreeCRL_Entry(CRL_Entry* crle)
 {
-       RevokedCert* tmp = crle->certs; 
+    RevokedCert* tmp = crle->certs; 
 
-       CYASSL_ENTER("FreeCRL_Entry");
+    CYASSL_ENTER("FreeCRL_Entry");
 
     while(tmp) {
         RevokedCert* next = tmp->next;
@@ -84,9 +91,15 @@ static void FreeCRL_Entry(CRL_Entry* crle)
 /* Free all CRL resources */
 void FreeCRL(CYASSL_CRL* crl)
 {
-       CRL_Entry* tmp = crl->crlList;
+    CRL_Entry* tmp = crl->crlList;
+
+    CYASSL_ENTER("FreeCRL");
 
-       CYASSL_ENTER("FreeCRL");
+    if (crl->monitors[0].path)
+        XFREE(crl->monitors[0].path, NULL, DYNAMIC_TYPE_CRL_MONITOR);
+
+    if (crl->monitors[1].path)
+        XFREE(crl->monitors[1].path, NULL, DYNAMIC_TYPE_CRL_MONITOR);
 
     while(tmp) {
         CRL_Entry* next = tmp->next;
@@ -95,6 +108,12 @@ void FreeCRL(CYASSL_CRL* crl)
         tmp = next;
     }  
 
+#ifdef HAVE_CRL_MONITOR
+    if (crl->tid != 0) {
+        CYASSL_MSG("Canceling monitor thread");
+        pthread_cancel(crl->tid);
+    }
+#endif
     FreeMutex(&crl->crlLock);
 }
 
@@ -102,202 +121,456 @@ void FreeCRL(CYASSL_CRL* crl)
 /* Is the cert ok with CRL, return 0 on success */
 int CheckCertCRL(CYASSL_CRL* crl, DecodedCert* cert)
 {
-       CRL_Entry* crle;
-       int        foundEntry = 0;
-       int        revoked = 0;
-       int        ret = 0;
-
-       CYASSL_ENTER("CheckCertCRL");
-
-       if (LockMutex(&crl->crlLock) != 0) {
-               CYASSL_MSG("LockMutex failed");
-               return BAD_MUTEX_ERROR;
-       }
-
-       crle = crl->crlList;
-
-       while (crle) {
-               if (XMEMCMP(crle->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0) {
-                       CYASSL_MSG("Found CRL Entry on list");
-                       foundEntry = 1;
-                       break;
-               }
-               crle = crle->next;
-       }
-
-       if (foundEntry) {
-               RevokedCert* rc = crle->certs;
-
-               while (rc) {
-                       if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
-                               CYASSL_MSG("Cert revoked");
-                               revoked = 1;
-                               ret = CRL_CERT_REVOKED;
-                               break;
-                       }
-                       rc = rc->next;  
-               }
-       }
-
-       UnLockMutex(&crl->crlLock);
-
-       if (foundEntry == 0) {
-               CYASSL_MSG("Couldn't find CRL for status check");
-               ret = CRL_MISSING;
-               if (crl->cm->cbMissingCRL) {
-                       char url[256];
-
-                       CYASSL_MSG("Issuing missing CRL callback");
-                       url[0] = '\0';
-                       if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
-                               XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
-                               url[cert->extCrlInfoSz] = '\0';
-                       }
-                       else  {
-                               CYASSL_MSG("CRL url too long");
+    CRL_Entry* crle;
+    int        foundEntry = 0;
+    int        revoked = 0;
+    int        ret = 0;
+
+    CYASSL_ENTER("CheckCertCRL");
+
+    if (LockMutex(&crl->crlLock) != 0) {
+        CYASSL_MSG("LockMutex failed");
+        return BAD_MUTEX_ERROR;
+    }
+
+    crle = crl->crlList;
+
+    while (crle) {
+        if (XMEMCMP(crle->issuerHash, cert->issuerHash, SHA_DIGEST_SIZE) == 0) {
+            CYASSL_MSG("Found CRL Entry on list");
+            CYASSL_MSG("Checking next date validity");
+
+            if (!ValidateDate(crle->nextDate, crle->nextDateFormat, AFTER)) {
+                CYASSL_MSG("CRL next date is no longer valid");
+                ret = ASN_AFTER_DATE_E;
             }
-                       crl->cm->cbMissingCRL(url);
-               }
-       }
+            else
+                foundEntry = 1;
+            break;
+        }
+        crle = crle->next;
+    }
+
+    if (foundEntry) {
+        RevokedCert* rc = crle->certs;
+
+        while (rc) {
+            if (XMEMCMP(rc->serialNumber, cert->serial, rc->serialSz) == 0) {
+                CYASSL_MSG("Cert revoked");
+                revoked = 1;
+                ret = CRL_CERT_REVOKED;
+                break;
+            }
+            rc = rc->next;     
+        }
+    }
 
+    UnLockMutex(&crl->crlLock);
 
-       return ret;     
+    if (foundEntry == 0) {
+        CYASSL_MSG("Couldn't find CRL for status check");
+        ret = CRL_MISSING;
+        if (crl->cm->cbMissingCRL) {
+            char url[256];
+
+            CYASSL_MSG("Issuing missing CRL callback");
+            url[0] = '\0';
+            if (cert->extCrlInfoSz < (int)sizeof(url) -1 ) {
+                XMEMCPY(url, cert->extCrlInfo, cert->extCrlInfoSz);
+                url[cert->extCrlInfoSz] = '\0';
+            }
+            else  {
+                CYASSL_MSG("CRL url too long");
+            }
+            crl->cm->cbMissingCRL(url);
+        }
+    }
+
+
+    return ret;        
 }
 
 
 /* Add Decoded CRL, 0 on success */
 static int AddCRL(CYASSL_CRL* crl, DecodedCRL* dcrl)
 {
-       CRL_Entry* crle;
-
-       CYASSL_ENTER("AddCRL");
-
-       crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
-       if (crle == NULL) {
-               CYASSL_MSG("alloc CRL Entry failed");
-               return -1;
-       }
-
-       if (InitCRL_Entry(crle, dcrl) < 0) {
-               CYASSL_MSG("Init CRL Entry failed");
-               return -1;
-       }
-
-       if (LockMutex(&crl->crlLock) != 0) {
-               CYASSL_MSG("LockMutex failed");
-               FreeCRL_Entry(crle);
-               return BAD_MUTEX_ERROR;
-       }
-       crle->next = crl->crlList;
-       crl->crlList = crle;
-       UnLockMutex(&crl->crlLock);
-
-       return 0;
+    CRL_Entry* crle;
+
+    CYASSL_ENTER("AddCRL");
+
+    crle = (CRL_Entry*)XMALLOC(sizeof(CRL_Entry), NULL, DYNAMIC_TYPE_CRL_ENTRY);
+    if (crle == NULL) {
+        CYASSL_MSG("alloc CRL Entry failed");
+        return -1;
+    }
+
+    if (InitCRL_Entry(crle, dcrl) < 0) {
+        CYASSL_MSG("Init CRL Entry failed");
+        XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
+        return -1;
+    }
+
+    if (LockMutex(&crl->crlLock) != 0) {
+        CYASSL_MSG("LockMutex failed");
+        FreeCRL_Entry(crle);
+        XFREE(crle, NULL, DYNAMIC_TYPE_CRL_ENTRY);
+        return BAD_MUTEX_ERROR;
+    }
+    crle->next = crl->crlList;
+    crl->crlList = crle;
+    UnLockMutex(&crl->crlLock);
+
+    return 0;
 }
 
 
 /* Load CRL File of type, SSL_SUCCESS on ok */
 int BufferLoadCRL(CYASSL_CRL* crl, const byte* buff, long sz, int type)
 {
-       int          ret = SSL_SUCCESS;
-       const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
-       buffer       der;
-       DecodedCRL   dcrl;
-
-       der.buffer = NULL;
-
-       CYASSL_ENTER("BufferLoadCRL");
-
-       if (crl == NULL || buff == NULL || sz == 0)
-               return BAD_FUNC_ARG;
-
-       if (type == SSL_FILETYPE_PEM) {
-               int eccKey = 0;   /* not used */
-               EncryptedInfo info;
-               info.ctx = NULL;
-
-               ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
-               if (ret == 0) {
-                       myBuffer = der.buffer;
-                       sz = der.length;
-               }
-               else {
-                       CYASSL_MSG("Pem to Der failed");
-                       return -1;
-               }
-       }
-
-       InitDecodedCRL(&dcrl);
-       ret = ParseCRL(&dcrl, myBuffer, sz);
-       if (ret != 0) {
-               CYASSL_MSG("ParseCRL error");
-       }
-       else {
-               ret = AddCRL(crl, &dcrl);
-               if (ret != 0) {
-                       CYASSL_MSG("AddCRL error");
+    int          ret = SSL_SUCCESS;
+    const byte*  myBuffer = buff;    /* if DER ok, otherwise switch */
+    buffer       der;
+    DecodedCRL   dcrl;
+
+    der.buffer = NULL;
+
+    CYASSL_ENTER("BufferLoadCRL");
+
+    if (crl == NULL || buff == NULL || sz == 0)
+        return BAD_FUNC_ARG;
+
+    if (type == SSL_FILETYPE_PEM) {
+        int eccKey = 0;   /* not used */
+        EncryptedInfo info;
+        info.ctx = NULL;
+
+        ret = PemToDer(buff, sz, CRL_TYPE, &der, NULL, &info, &eccKey);
+        if (ret == 0) {
+            myBuffer = der.buffer;
+            sz = der.length;
+        }
+        else {
+            CYASSL_MSG("Pem to Der failed");
+            return -1;
+        }
+    }
+
+    InitDecodedCRL(&dcrl);
+    ret = ParseCRL(&dcrl, myBuffer, sz, crl->cm);
+    if (ret != 0) {
+        CYASSL_MSG("ParseCRL error");
+    }
+    else {
+        ret = AddCRL(crl, &dcrl);
+        if (ret != 0) {
+            CYASSL_MSG("AddCRL error");
+        }
+    }
+    FreeDecodedCRL(&dcrl);
+
+    if (der.buffer)
+        XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
+
+    if (ret == 0)
+        return SSL_SUCCESS;  /* convert */
+    return ret;
+}
+
+
+#ifdef HAVE_CRL_MONITOR
+
+
+/* read in new CRL entries and save new list */
+static int SwapLists(CYASSL_CRL* crl)
+{
+    int        ret;
+    CYASSL_CRL tmp;
+    CRL_Entry* newList;
+
+    if (InitCRL(&tmp, crl->cm) < 0) {
+        CYASSL_MSG("Init tmp CRL failed");
+        return -1;
+    }
+
+    if (crl->monitors[0].path) {
+        ret = LoadCRL(&tmp, crl->monitors[0].path, SSL_FILETYPE_PEM, 0);
+        if (ret != SSL_SUCCESS) {
+            CYASSL_MSG("PEM LoadCRL on dir change failed");
+            FreeCRL(&tmp);
+            return -1;
         }
-       }
-       FreeDecodedCRL(&dcrl);
+    }
+
+    if (crl->monitors[1].path) {
+        ret = LoadCRL(&tmp, crl->monitors[1].path, SSL_FILETYPE_ASN1, 0);
+        if (ret != SSL_SUCCESS) {
+            CYASSL_MSG("DER LoadCRL on dir change failed");
+            FreeCRL(&tmp);
+            return -1;
+        }
+    }
+
+    if (LockMutex(&crl->crlLock) != 0) {
+        CYASSL_MSG("LockMutex failed");
+        FreeCRL(&tmp);
+        return -1;
+    }
+
+    newList = tmp.crlList;
+
+    /* swap lists */
+    tmp.crlList  = crl->crlList;
+    crl->crlList = newList;
 
-       if (der.buffer)
-               XFREE(der.buffer, NULL, DYNAMIC_TYPE_CRL);
+    UnLockMutex(&crl->crlLock);
 
-       if (ret == 0)
-               return SSL_SUCCESS;  /* convert */
-       return ret;
+    FreeCRL(&tmp);
+
+    return 0;
 }
 
 
+#ifdef __MACH__
+
+#include <sys/event.h>
+#include <sys/time.h>
+#include <fcntl.h>
+
+/* OS X  monitoring */
+static void* DoMonitor(void* arg)
+{
+    int fPEM, fDER, kq;
+    struct kevent change;
+
+    CYASSL_CRL* crl = (CYASSL_CRL*)arg;
+
+    CYASSL_ENTER("DoMonitor");
+
+    kq = kqueue();
+    if (kq == -1) {
+        CYASSL_MSG("kqueue failed");
+        return NULL;
+    }
+
+    fPEM = -1;
+    fDER = -1;
+
+    if (crl->monitors[0].path) {
+        fPEM = open(crl->monitors[0].path, O_EVTONLY);
+        if (fPEM == -1) {
+            CYASSL_MSG("PEM event dir open failed");
+            return NULL;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        fDER = open(crl->monitors[1].path, O_EVTONLY);
+        if (fDER == -1) {
+            CYASSL_MSG("DER event dir open failed");
+            return NULL;
+        }
+    }
+
+    if (fPEM != -1)
+        EV_SET(&change, fPEM, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
+                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
+
+    if (fDER != -1)
+        EV_SET(&change, fDER, EVFILT_VNODE, EV_ADD | EV_ENABLE | EV_ONESHOT,
+                NOTE_DELETE | NOTE_EXTEND | NOTE_WRITE | NOTE_ATTRIB, 0, 0);
+
+    for (;;) {
+        struct kevent event;
+        int           numEvents = kevent(kq, &change, 1, &event, 1, NULL);
+       
+        CYASSL_MSG("Got kevent");
+
+        if (numEvents == -1) {
+            CYASSL_MSG("kevent problem, continue");
+            continue;
+        }
+
+        if (SwapLists(crl) < 0) {
+            CYASSL_MSG("SwapLists problem, continue");
+        }
+    }
+
+    return NULL;
+}
+
+
+#elif __linux__
+
+#include <sys/types.h>
+#include <sys/inotify.h>
+#include <unistd.h>
+
+/* linux monitoring */
+static void* DoMonitor(void* arg)
+{
+    int         notifyFd;
+    int         wd;
+    CYASSL_CRL* crl = (CYASSL_CRL*)arg;
+
+    CYASSL_ENTER("DoMonitor");
+
+    notifyFd = inotify_init();
+    if (notifyFd < 0) {
+        CYASSL_MSG("inotify failed");
+        return NULL;
+    }
+
+    if (crl->monitors[0].path) {
+        wd = inotify_add_watch(notifyFd, crl->monitors[0].path, IN_CLOSE_WRITE |
+                                                                IN_DELETE);
+        if (wd < 0) {
+            CYASSL_MSG("PEM notify add watch failed");
+            return NULL;
+        }
+    }
+
+    if (crl->monitors[1].path) {
+        wd = inotify_add_watch(notifyFd, crl->monitors[1].path, IN_CLOSE_WRITE |
+                                                                IN_DELETE);
+        if (wd < 0) {
+            CYASSL_MSG("DER notify add watch failed");
+            return NULL;
+        }
+    }
+
+    for (;;) {
+        char          buffer[8192];
+        int           length = read(notifyFd, buffer, sizeof(buffer));
+       
+        CYASSL_MSG("Got notify event");
+
+        if (length < 0) {
+            CYASSL_MSG("notify read problem, continue");
+            continue;
+        } 
+
+        if (SwapLists(crl) < 0) {
+            CYASSL_MSG("SwapLists problem, continue");
+        }
+    }
+
+    return NULL;
+}
+
+
+
+#endif /* MACH or linux */
+
+
+/* Start Monitoring the CRL path(s) in a thread */
+static int StartMonitorCRL(CYASSL_CRL* crl)
+{
+    pthread_attr_t attr;
+
+    CYASSL_ENTER("StartMonitorCRL");
+
+    if (crl == NULL) 
+        return BAD_FUNC_ARG;
+
+    if (crl->tid != 0) {
+        CYASSL_MSG("Monitor thread already running");
+        return MONITOR_RUNNING_E;
+    }
+
+    pthread_attr_init(&attr);
+
+    if (pthread_create(&crl->tid, &attr, DoMonitor, crl) != 0) {
+        CYASSL_MSG("Thread creation error");
+        return THREAD_CREATE_E;
+    }
+
+    return SSL_SUCCESS;
+}
+
+
+#else /* HAVE_CRL_MONITOR */
+
+static int StartMonitorCRL(CYASSL_CRL* crl)
+{
+    CYASSL_ENTER("StartMonitorCRL");
+    CYASSL_MSG("Not compiled in");
+
+    return NOT_COMPILED_IN;
+}
+
+#endif  /* HAVE_CRL_MONITOR */
+
+
 /* Load CRL path files of type, SSL_SUCCESS on ok */ 
 int LoadCRL(CYASSL_CRL* crl, const char* path, int type, int monitor)
 {
-       struct dirent* entry;
-       DIR*   dir;
-       int    ret = SSL_SUCCESS;
-
-       CYASSL_ENTER("LoadCRL");
-       if (crl == NULL)
-               return BAD_FUNC_ARG;
-
-       dir = opendir(path);
-       if (dir == NULL) {
-               CYASSL_MSG("opendir path crl load failed");
-               return BAD_PATH_ERROR;
-       }
-       while ( ret == SSL_SUCCESS && (entry = readdir(dir)) != NULL) {
-               if (entry->d_type & DT_REG) {
-                       char name[MAX_FILENAME_SZ];
-
-                       if (type == SSL_FILETYPE_PEM) {
-                               if (strstr(entry->d_name, ".pem") == NULL) {
-                                       CYASSL_MSG("not .pem file, skipping");
-                                       continue;
-                               }
-                       }
-                       else {
-                               if (strstr(entry->d_name, ".der") == NULL &&
-                                       strstr(entry->d_name, ".crl") == NULL) {
-
-                                       CYASSL_MSG("not .der or .crl file, skipping");
-                                       continue;
-                               }
-                       }
-
-                       XMEMSET(name, 0, sizeof(name));
-                       XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
-                       XSTRNCAT(name, "/", 1);
-                       XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
-
-                       ret = ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl);
-               }
-       }
-
-    if (monitor) {
+    struct dirent* entry;
+    DIR*   dir;
+    int    ret = SSL_SUCCESS;
+
+    CYASSL_ENTER("LoadCRL");
+    if (crl == NULL)
+        return BAD_FUNC_ARG;
+
+    dir = opendir(path);
+    if (dir == NULL) {
+        CYASSL_MSG("opendir path crl load failed");
+        return BAD_PATH_ERROR;
+    }
+    while ( (entry = readdir(dir)) != NULL) {
+        if (entry->d_type & DT_REG) {
+            char name[MAX_FILENAME_SZ];
+
+            if (type == SSL_FILETYPE_PEM) {
+                if (strstr(entry->d_name, ".pem") == NULL) {
+                    CYASSL_MSG("not .pem file, skipping");
+                    continue;
+                }
+            }
+            else {
+                if (strstr(entry->d_name, ".der") == NULL &&
+                    strstr(entry->d_name, ".crl") == NULL) {
+
+                    CYASSL_MSG("not .der or .crl file, skipping");
+                    continue;
+                }
+            }
+
+            XMEMSET(name, 0, sizeof(name));
+            XSTRNCPY(name, path, MAX_FILENAME_SZ/2 - 2);
+            XSTRNCAT(name, "/", 1);
+            XSTRNCAT(name, entry->d_name, MAX_FILENAME_SZ/2);
+
+            if (ProcessFile(NULL, name, type, CRL_TYPE, NULL, 0, crl)
+                                                               != SSL_SUCCESS) {
+                CYASSL_MSG("CRL file load failed, continuing");
+            }
+        }
+    }
+
+    if (monitor & CYASSL_CRL_MONITOR) {
         CYASSL_MSG("monitor path requested");
+
+        if (type == SSL_FILETYPE_PEM) {
+            crl->monitors[0].path = strdup(path);
+            crl->monitors[0].type = SSL_FILETYPE_PEM;
+            if (crl->monitors[0].path == NULL)
+                ret = MEMORY_E;
+        } else {
+            crl->monitors[1].path = strdup(path);
+            crl->monitors[1].type = SSL_FILETYPE_ASN1;
+            if (crl->monitors[1].path == NULL)
+                ret = MEMORY_E;
+        }
+      
+        if (monitor & CYASSL_CRL_START_MON) {
+            CYASSL_MSG("start monitoring requested");
+    
+            ret = StartMonitorCRL(crl);
+       } 
     }
 
-       return SSL_SUCCESS;
+    return ret;
 }
 
 #endif /* HAVE_CRL */